Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / task_manager / child_process_resource_provider.cc
blob8bfa9227101400a6c6715f28934a9af880be0f24
1 // Copyright 2013 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_manager/child_process_resource_provider.h"
7 #include <vector>
9 #include "base/i18n/rtl.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/strings/string16.h"
12 #include "chrome/browser/process_resource_usage.h"
13 #include "chrome/browser/task_manager/resource_provider.h"
14 #include "chrome/browser/task_manager/task_manager.h"
15 #include "chrome/grit/generated_resources.h"
16 #include "components/nacl/common/nacl_process_type.h"
17 #include "content/public/browser/browser_child_process_host.h"
18 #include "content/public/browser/browser_child_process_host_iterator.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/child_process_data.h"
21 #include "content/public/common/service_registry.h"
22 #include "grit/theme_resources.h"
23 #include "ui/base/l10n/l10n_util.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/gfx/image/image_skia.h"
27 using content::BrowserChildProcessHostIterator;
28 using content::BrowserThread;
29 using content::WebContents;
31 namespace task_manager {
33 class ChildProcessResource : public Resource {
34 public:
35 ChildProcessResource(int process_type,
36 const base::string16& name,
37 base::ProcessHandle handle,
38 int unique_process_id);
39 ~ChildProcessResource() override;
41 // Resource methods:
42 base::string16 GetTitle() const override;
43 base::string16 GetProfileName() const override;
44 gfx::ImageSkia GetIcon() const override;
45 base::ProcessHandle GetProcess() const override;
46 int GetUniqueChildProcessId() const override;
47 Type GetType() const override;
48 bool SupportNetworkUsage() const override;
49 void SetSupportNetworkUsage() override;
50 void Refresh() override;
51 bool ReportsV8MemoryStats() const override;
52 size_t GetV8MemoryAllocated() const override;
53 size_t GetV8MemoryUsed() const override;
55 // Returns the pid of the child process.
56 int process_id() const { return pid_; }
58 private:
59 // Returns a localized title for the child process. For example, a plugin
60 // process would be "Plugin: Flash" when name is "Flash".
61 base::string16 GetLocalizedTitle() const;
63 static void ConnectResourceReporterOnIOThread(
64 int id, mojo::InterfaceRequest<ResourceUsageReporter> req);
66 int process_type_;
67 base::string16 name_;
68 base::ProcessHandle handle_;
69 int pid_;
70 int unique_process_id_;
71 mutable base::string16 title_;
72 bool network_usage_support_;
73 scoped_ptr<ProcessResourceUsage> resource_usage_;
75 // The icon painted for the child processs.
76 // TODO(jcampan): we should have plugin specific icons for well-known
77 // plugins.
78 static gfx::ImageSkia* default_icon_;
80 DISALLOW_COPY_AND_ASSIGN(ChildProcessResource);
83 gfx::ImageSkia* ChildProcessResource::default_icon_ = NULL;
85 // static
86 void ChildProcessResource::ConnectResourceReporterOnIOThread(
87 int id, mojo::InterfaceRequest<ResourceUsageReporter> req) {
88 DCHECK_CURRENTLY_ON(BrowserThread::IO);
89 content::BrowserChildProcessHost* host =
90 content::BrowserChildProcessHost::FromID(id);
91 if (!host)
92 return;
94 content::ServiceRegistry* registry = host->GetServiceRegistry();
95 if (!registry)
96 return;
98 registry->ConnectToRemoteService(req.Pass());
101 ChildProcessResource::ChildProcessResource(int process_type,
102 const base::string16& name,
103 base::ProcessHandle handle,
104 int unique_process_id)
105 : process_type_(process_type),
106 name_(name),
107 handle_(handle),
108 unique_process_id_(unique_process_id),
109 network_usage_support_(false) {
110 // We cache the process id because it's not cheap to calculate, and it won't
111 // be available when we get the plugin disconnected notification.
112 pid_ = base::GetProcId(handle);
113 if (!default_icon_) {
114 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
115 default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON);
116 // TODO(jabdelmalek): use different icon for web workers.
118 ResourceUsageReporterPtr service;
119 mojo::InterfaceRequest<ResourceUsageReporter> request =
120 mojo::GetProxy(&service);
121 BrowserThread::PostTask(
122 BrowserThread::IO, FROM_HERE,
123 base::Bind(&ChildProcessResource::ConnectResourceReporterOnIOThread,
124 unique_process_id, base::Passed(&request)));
125 resource_usage_.reset(new ProcessResourceUsage(service.Pass()));
128 ChildProcessResource::~ChildProcessResource() {
131 // Resource methods:
132 base::string16 ChildProcessResource::GetTitle() const {
133 if (title_.empty())
134 title_ = GetLocalizedTitle();
136 return title_;
139 base::string16 ChildProcessResource::GetProfileName() const {
140 return base::string16();
143 gfx::ImageSkia ChildProcessResource::GetIcon() const {
144 return *default_icon_;
147 base::ProcessHandle ChildProcessResource::GetProcess() const {
148 return handle_;
151 int ChildProcessResource::GetUniqueChildProcessId() const {
152 return unique_process_id_;
155 Resource::Type ChildProcessResource::GetType() const {
156 // Translate types to Resource::Type, since ChildProcessData's type
157 // is not available for all TaskManager resources.
158 switch (process_type_) {
159 case content::PROCESS_TYPE_PLUGIN:
160 case content::PROCESS_TYPE_PPAPI_PLUGIN:
161 case content::PROCESS_TYPE_PPAPI_BROKER:
162 return Resource::PLUGIN;
163 case content::PROCESS_TYPE_UTILITY:
164 return Resource::UTILITY;
165 case content::PROCESS_TYPE_ZYGOTE:
166 return Resource::ZYGOTE;
167 case content::PROCESS_TYPE_SANDBOX_HELPER:
168 return Resource::SANDBOX_HELPER;
169 case content::PROCESS_TYPE_GPU:
170 return Resource::GPU;
171 case PROCESS_TYPE_NACL_LOADER:
172 case PROCESS_TYPE_NACL_BROKER:
173 return Resource::NACL;
174 default:
175 return Resource::UNKNOWN;
179 bool ChildProcessResource::SupportNetworkUsage() const {
180 return network_usage_support_;
183 void ChildProcessResource::SetSupportNetworkUsage() {
184 network_usage_support_ = true;
187 base::string16 ChildProcessResource::GetLocalizedTitle() const {
188 base::string16 title = name_;
189 if (title.empty()) {
190 switch (process_type_) {
191 case content::PROCESS_TYPE_PLUGIN:
192 case content::PROCESS_TYPE_PPAPI_PLUGIN:
193 case content::PROCESS_TYPE_PPAPI_BROKER:
194 title = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME);
195 break;
196 default:
197 // Nothing to do for non-plugin processes.
198 break;
202 // Explicitly mark name as LTR if there is no strong RTL character,
203 // to avoid the wrong concatenation result similar to "!Yahoo Mail: the
204 // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew
205 // or Arabic word for "plugin".
206 base::i18n::AdjustStringForLocaleDirection(&title);
208 switch (process_type_) {
209 case content::PROCESS_TYPE_UTILITY:
210 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX, title);
211 case content::PROCESS_TYPE_GPU:
212 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_GPU_PREFIX);
213 case content::PROCESS_TYPE_PLUGIN:
214 case content::PROCESS_TYPE_PPAPI_PLUGIN:
215 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX, title);
216 case content::PROCESS_TYPE_PPAPI_BROKER:
217 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_BROKER_PREFIX,
218 title);
219 case PROCESS_TYPE_NACL_BROKER:
220 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX);
221 case PROCESS_TYPE_NACL_LOADER:
222 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, title);
223 // These types don't need display names or get them from elsewhere.
224 case content::PROCESS_TYPE_BROWSER:
225 case content::PROCESS_TYPE_RENDERER:
226 case content::PROCESS_TYPE_ZYGOTE:
227 case content::PROCESS_TYPE_SANDBOX_HELPER:
228 case content::PROCESS_TYPE_MAX:
229 NOTREACHED();
230 break;
231 case content::PROCESS_TYPE_UNKNOWN:
232 NOTREACHED() << "Need localized name for child process type.";
235 return title;
238 void ChildProcessResource::Refresh() {
239 if (resource_usage_)
240 resource_usage_->Refresh(base::Closure());
243 bool ChildProcessResource::ReportsV8MemoryStats() const {
244 if (resource_usage_)
245 return resource_usage_->ReportsV8MemoryStats();
246 return false;
249 size_t ChildProcessResource::GetV8MemoryAllocated() const {
250 if (resource_usage_)
251 return resource_usage_->GetV8MemoryAllocated();
252 return 0;
255 size_t ChildProcessResource::GetV8MemoryUsed() const {
256 if (resource_usage_)
257 return resource_usage_->GetV8MemoryUsed();
258 return 0;
261 ////////////////////////////////////////////////////////////////////////////////
262 // ChildProcessResourceProvider class
263 ////////////////////////////////////////////////////////////////////////////////
265 ChildProcessResourceProvider::
266 ChildProcessResourceProvider(TaskManager* task_manager)
267 : task_manager_(task_manager),
268 updating_(false) {
271 ChildProcessResourceProvider::~ChildProcessResourceProvider() {
274 Resource* ChildProcessResourceProvider::GetResource(
275 int origin_pid,
276 int child_id,
277 int route_id) {
278 PidResourceMap::iterator iter = pid_to_resources_.find(origin_pid);
279 if (iter != pid_to_resources_.end())
280 return iter->second;
281 else
282 return NULL;
285 void ChildProcessResourceProvider::StartUpdating() {
286 DCHECK(!updating_);
287 updating_ = true;
289 // Get the existing child processes.
290 BrowserThread::PostTask(
291 BrowserThread::IO, FROM_HERE,
292 base::Bind(
293 &ChildProcessResourceProvider::RetrieveChildProcessData,
294 this));
296 BrowserChildProcessObserver::Add(this);
299 void ChildProcessResourceProvider::StopUpdating() {
300 DCHECK(updating_);
301 updating_ = false;
303 // Delete all the resources.
304 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
306 resources_.clear();
307 pid_to_resources_.clear();
309 BrowserChildProcessObserver::Remove(this);
312 void ChildProcessResourceProvider::BrowserChildProcessHostConnected(
313 const content::ChildProcessData& data) {
314 DCHECK(updating_);
316 if (resources_.count(data.handle)) {
317 // The case may happen that we have added a child_process_info as part of
318 // the iteration performed during StartUpdating() call but the notification
319 // that it has connected was not fired yet. So when the notification
320 // happens, we already know about this plugin and just ignore it.
321 return;
323 AddToTaskManager(data);
326 void ChildProcessResourceProvider::
327 BrowserChildProcessHostDisconnected(
328 const content::ChildProcessData& data) {
329 DCHECK(updating_);
331 ChildProcessMap::iterator iter = resources_.find(data.handle);
332 if (iter == resources_.end()) {
333 // ChildProcessData disconnection notifications are asynchronous, so we
334 // might be notified for a plugin we don't know anything about (if it was
335 // closed before the task manager was shown and destroyed after that).
336 return;
338 // Remove the resource from the Task Manager.
339 ChildProcessResource* resource = iter->second;
340 task_manager_->RemoveResource(resource);
341 // Remove it from the provider.
342 resources_.erase(iter);
343 // Remove it from our pid map.
344 PidResourceMap::iterator pid_iter =
345 pid_to_resources_.find(resource->process_id());
346 DCHECK(pid_iter != pid_to_resources_.end());
347 if (pid_iter != pid_to_resources_.end())
348 pid_to_resources_.erase(pid_iter);
350 // Finally, delete the resource.
351 delete resource;
354 void ChildProcessResourceProvider::AddToTaskManager(
355 const content::ChildProcessData& child_process_data) {
356 ChildProcessResource* resource =
357 new ChildProcessResource(
358 child_process_data.process_type,
359 child_process_data.name,
360 child_process_data.handle,
361 child_process_data.id);
362 resources_[child_process_data.handle] = resource;
363 pid_to_resources_[resource->process_id()] = resource;
364 task_manager_->AddResource(resource);
367 // The ChildProcessData::Iterator has to be used from the IO thread.
368 void ChildProcessResourceProvider::RetrieveChildProcessData() {
369 std::vector<content::ChildProcessData> child_processes;
370 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
371 // Only add processes which are already started, since we need their handle.
372 if (iter.GetData().handle == base::kNullProcessHandle)
373 continue;
374 child_processes.push_back(iter.GetData());
376 // Now notify the UI thread that we have retrieved information about child
377 // processes.
378 BrowserThread::PostTask(
379 BrowserThread::UI, FROM_HERE,
380 base::Bind(
381 &ChildProcessResourceProvider::ChildProcessDataRetreived,
382 this, child_processes));
385 // This is called on the UI thread.
386 void ChildProcessResourceProvider::ChildProcessDataRetreived(
387 const std::vector<content::ChildProcessData>& child_processes) {
388 for (size_t i = 0; i < child_processes.size(); ++i)
389 AddToTaskManager(child_processes[i]);
391 task_manager_->model()->NotifyDataReady();
394 } // namespace task_manager