1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/task_management/providers/web_contents/renderer_task.h"
7 #include "base/i18n/rtl.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/favicon/favicon_utils.h"
12 #include "chrome/browser/process_resource_usage.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/profiles/profile_info_cache.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/task_management/task_manager_observer.h"
17 #include "chrome/grit/generated_resources.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/browser/web_contents_delegate.h"
21 #include "content/public/common/service_registry.h"
22 #include "ui/base/l10n/l10n_util.h"
24 namespace task_management
{
28 // Creates the Mojo service wrapper that will be used to sample the V8 memory
29 // usage and the the WebCache resource stats of the render process hosted by
30 // |render_process_host|.
31 ProcessResourceUsage
* CreateRendererResourcesSampler(
32 content::RenderProcessHost
* render_process_host
) {
33 ResourceUsageReporterPtr service
;
34 content::ServiceRegistry
* service_registry
=
35 render_process_host
->GetServiceRegistry();
37 service_registry
->ConnectToRemoteService(mojo::GetProxy(&service
));
38 return new ProcessResourceUsage(service
.Pass());
41 // Gets the profile name associated with the browser context of the given
42 // |render_process_host| from the profile info cache.
43 base::string16
GetRendererProfileName(
44 const content::RenderProcessHost
* render_process_host
) {
46 Profile::FromBrowserContext(render_process_host
->GetBrowserContext());
48 ProfileInfoCache
& cache
=
49 g_browser_process
->profile_manager()->GetProfileInfoCache();
51 cache
.GetIndexOfProfileWithPath(profile
->GetOriginalProfile()->GetPath());
52 if (index
!= std::string::npos
)
53 return cache
.GetNameOfProfileAtIndex(index
);
55 return base::string16();
58 inline bool IsRendererResourceSamplingDisabled(int64 flags
) {
59 return (flags
& (REFRESH_TYPE_V8_MEMORY
| REFRESH_TYPE_WEBCACHE_STATS
)) == 0;
64 RendererTask::RendererTask(const base::string16
& title
,
65 const gfx::ImageSkia
* icon
,
66 content::WebContents
* web_contents
,
67 content::RenderProcessHost
* render_process_host
)
68 : Task(title
, icon
, render_process_host
->GetHandle()),
69 web_contents_(web_contents
),
70 render_process_host_(render_process_host
),
71 renderer_resources_sampler_(
72 CreateRendererResourcesSampler(render_process_host_
)),
73 render_process_id_(render_process_host_
->GetID()),
74 v8_memory_allocated_(0),
77 profile_name_(GetRendererProfileName(render_process_host_
)) {
78 // All renderer tasks are capable of reporting network usage, so the default
79 // invalid value of -1 doesn't apply here.
80 OnNetworkBytesRead(0);
83 RendererTask::~RendererTask() {
86 void RendererTask::Activate() {
87 if (!web_contents_
->GetDelegate())
90 web_contents_
->GetDelegate()->ActivateContents(web_contents_
);
93 void RendererTask::Refresh(const base::TimeDelta
& update_interval
,
94 int64 refresh_flags
) {
95 Task::Refresh(update_interval
, refresh_flags
);
97 if (IsRendererResourceSamplingDisabled(refresh_flags
))
100 // The renderer resources refresh is performed asynchronously, we will invoke
101 // it and record the current values (which might be invalid at the moment. We
102 // can safely ignore that and count on future refresh cycles potentially
103 // having valid values).
104 renderer_resources_sampler_
->Refresh(base::Closure());
106 v8_memory_allocated_
= base::saturated_cast
<int64
>(
107 renderer_resources_sampler_
->GetV8MemoryAllocated());
108 v8_memory_used_
= base::saturated_cast
<int64
>(
109 renderer_resources_sampler_
->GetV8MemoryUsed());
110 webcache_stats_
= renderer_resources_sampler_
->GetWebCoreCacheStats();
113 Task::Type
RendererTask::GetType() const {
114 return Task::RENDERER
;
117 int RendererTask::GetChildProcessUniqueID() const {
118 return render_process_id_
;
121 base::string16
RendererTask::GetProfileName() const {
122 return profile_name_
;
125 int64
RendererTask::GetV8MemoryAllocated() const {
126 return v8_memory_allocated_
;
129 int64
RendererTask::GetV8MemoryUsed() const {
130 return v8_memory_used_
;
133 bool RendererTask::ReportsWebCacheStats() const {
137 blink::WebCache::ResourceTypeStats
RendererTask::GetWebCacheStats() const {
138 return webcache_stats_
;
142 base::string16
RendererTask::GetTitleFromWebContents(
143 content::WebContents
* web_contents
) {
144 DCHECK(web_contents
);
145 base::string16 title
= web_contents
->GetTitle();
147 GURL url
= web_contents
->GetURL();
148 title
= base::UTF8ToUTF16(url
.spec());
149 // Force URL to be LTR.
150 title
= base::i18n::GetDisplayStringInLTRDirectionality(title
);
152 // Since the title could later be concatenated with
153 // IDS_TASK_MANAGER_TAB_PREFIX (for example), we need to explicitly set the
154 // title to be LTR format if there is no strong RTL charater in it.
155 // Otherwise, if IDS_TASK_MANAGER_TAB_PREFIX is an RTL word, the
156 // concatenated result might be wrong. For example, http://mail.yahoo.com,
157 // whose title is "Yahoo! Mail: The best web-based Email!", without setting
158 // it explicitly as LTR format, the concatenated result will be "!Yahoo!
159 // Mail: The best web-based Email :BAT", in which the capital letters "BAT"
160 // stands for the Hebrew word for "tab".
161 base::i18n::AdjustStringForLocaleDirection(&title
);
167 const gfx::ImageSkia
* RendererTask::GetFaviconFromWebContents(
168 content::WebContents
* web_contents
) {
169 DCHECK(web_contents
);
171 // Tag the web_contents with a |ContentFaviconDriver| (if needed) so that
172 // we can use it to retrieve the favicon if there is one.
173 favicon::CreateContentFaviconDriverForWebContents(web_contents
);
175 favicon::ContentFaviconDriver::FromWebContents(web_contents
)->
180 return image
.ToImageSkia();
184 const base::string16
RendererTask::PrefixRendererTitle(
185 const base::string16
& title
,
189 bool is_background
) {
190 int message_id
= IDS_TASK_MANAGER_TAB_PREFIX
;
192 if (is_incognito
&& !is_app
&& !is_extension
) {
193 message_id
= IDS_TASK_MANAGER_TAB_INCOGNITO_PREFIX
;
196 message_id
= IDS_TASK_MANAGER_BACKGROUND_PREFIX
;
197 else if (is_incognito
)
198 message_id
= IDS_TASK_MANAGER_APP_INCOGNITO_PREFIX
;
200 message_id
= IDS_TASK_MANAGER_APP_PREFIX
;
201 } else if (is_extension
) {
203 message_id
= IDS_TASK_MANAGER_EXTENSION_INCOGNITO_PREFIX
;
205 message_id
= IDS_TASK_MANAGER_EXTENSION_PREFIX
;
208 return l10n_util::GetStringFUTF16(message_id
, title
);
211 } // namespace task_management