Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(515)

Side by Side Diff: chrome/browser/task_manager/child_process_resource_provider.cc

Issue 2197483003: Move the Mac Task Manager to the new backend code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mark Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/task_manager/child_process_resource_provider.h"
6
7 #include <stddef.h>
8 #include <utility>
9 #include <vector>
10
11 #include "base/i18n/rtl.h"
12 #include "base/macros.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/strings/string16.h"
15 #include "chrome/browser/process_resource_usage.h"
16 #include "chrome/browser/task_manager/resource_provider.h"
17 #include "chrome/browser/task_manager/task_manager.h"
18 #include "chrome/grit/generated_resources.h"
19 #include "components/nacl/common/nacl_process_type.h"
20 #include "content/public/browser/browser_child_process_host.h"
21 #include "content/public/browser/browser_child_process_host_iterator.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/child_process_data.h"
24 #include "grit/theme_resources.h"
25 #include "services/shell/public/cpp/interface_provider.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/image/image_skia.h"
29
30 using content::BrowserChildProcessHostIterator;
31 using content::BrowserThread;
32 using content::WebContents;
33
34 namespace task_manager {
35
36 class ChildProcessResource : public Resource {
37 public:
38 ChildProcessResource(int process_type,
39 const base::string16& name,
40 base::ProcessHandle handle,
41 int unique_process_id);
42 ~ChildProcessResource() override;
43
44 // Resource methods:
45 base::string16 GetTitle() const override;
46 base::string16 GetProfileName() const override;
47 gfx::ImageSkia GetIcon() const override;
48 base::ProcessHandle GetProcess() const override;
49 int GetUniqueChildProcessId() const override;
50 Type GetType() const override;
51 bool SupportNetworkUsage() const override;
52 void SetSupportNetworkUsage() override;
53 void Refresh() override;
54 bool ReportsV8MemoryStats() const override;
55 size_t GetV8MemoryAllocated() const override;
56 size_t GetV8MemoryUsed() const override;
57
58 // Returns the pid of the child process.
59 int process_id() const { return pid_; }
60
61 private:
62 // Returns a localized title for the child process. For example, a plugin
63 // process would be "Plugin: Flash" when name is "Flash".
64 base::string16 GetLocalizedTitle() const;
65
66 static void ConnectResourceReporterOnIOThread(
67 int id,
68 mojo::InterfaceRequest<mojom::ResourceUsageReporter> req);
69
70 int process_type_;
71 base::string16 name_;
72 base::ProcessHandle handle_;
73 int pid_;
74 int unique_process_id_;
75 mutable base::string16 title_;
76 bool network_usage_support_;
77 std::unique_ptr<ProcessResourceUsage> resource_usage_;
78
79 // The icon painted for the child processs.
80 // TODO(jcampan): we should have plugin specific icons for well-known
81 // plugins.
82 static gfx::ImageSkia* default_icon_;
83
84 DISALLOW_COPY_AND_ASSIGN(ChildProcessResource);
85 };
86
87 gfx::ImageSkia* ChildProcessResource::default_icon_ = NULL;
88
89 // static
90 void ChildProcessResource::ConnectResourceReporterOnIOThread(
91 int id,
92 mojo::InterfaceRequest<mojom::ResourceUsageReporter> req) {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 content::BrowserChildProcessHost* host =
95 content::BrowserChildProcessHost::FromID(id);
96 if (!host || !host->GetRemoteInterfaces())
97 return;
98
99 host->GetRemoteInterfaces()->GetInterface(std::move(req));
100 }
101
102 ChildProcessResource::ChildProcessResource(int process_type,
103 const base::string16& name,
104 base::ProcessHandle handle,
105 int unique_process_id)
106 : process_type_(process_type),
107 name_(name),
108 handle_(handle),
109 unique_process_id_(unique_process_id),
110 network_usage_support_(false) {
111 // We cache the process id because it's not cheap to calculate, and it won't
112 // be available when we get the plugin disconnected notification.
113 pid_ = base::GetProcId(handle);
114 if (!default_icon_) {
115 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
116 default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON);
117 // TODO(jabdelmalek): use different icon for web workers.
118 }
119 mojom::ResourceUsageReporterPtr service;
120 mojo::InterfaceRequest<mojom::ResourceUsageReporter> request =
121 mojo::GetProxy(&service);
122 BrowserThread::PostTask(
123 BrowserThread::IO, FROM_HERE,
124 base::Bind(&ChildProcessResource::ConnectResourceReporterOnIOThread,
125 unique_process_id, base::Passed(&request)));
126 resource_usage_.reset(new ProcessResourceUsage(std::move(service)));
127 }
128
129 ChildProcessResource::~ChildProcessResource() {
130 }
131
132 // Resource methods:
133 base::string16 ChildProcessResource::GetTitle() const {
134 if (title_.empty())
135 title_ = GetLocalizedTitle();
136
137 return title_;
138 }
139
140 base::string16 ChildProcessResource::GetProfileName() const {
141 return base::string16();
142 }
143
144 gfx::ImageSkia ChildProcessResource::GetIcon() const {
145 return *default_icon_;
146 }
147
148 base::ProcessHandle ChildProcessResource::GetProcess() const {
149 return handle_;
150 }
151
152 int ChildProcessResource::GetUniqueChildProcessId() const {
153 return unique_process_id_;
154 }
155
156 Resource::Type ChildProcessResource::GetType() const {
157 // Translate types to Resource::Type, since ChildProcessData's type
158 // is not available for all TaskManager resources.
159 switch (process_type_) {
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;
176 }
177 }
178
179 bool ChildProcessResource::SupportNetworkUsage() const {
180 return network_usage_support_;
181 }
182
183 void ChildProcessResource::SetSupportNetworkUsage() {
184 network_usage_support_ = true;
185 }
186
187 base::string16 ChildProcessResource::GetLocalizedTitle() const {
188 base::string16 title = name_;
189 if (title.empty()) {
190 switch (process_type_) {
191 case content::PROCESS_TYPE_PPAPI_PLUGIN:
192 case content::PROCESS_TYPE_PPAPI_BROKER:
193 title = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME);
194 break;
195 default:
196 // Nothing to do for non-plugin processes.
197 break;
198 }
199 }
200
201 // Explicitly mark name as LTR if there is no strong RTL character,
202 // to avoid the wrong concatenation result similar to "!Yahoo Mail: the
203 // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew
204 // or Arabic word for "plugin".
205 base::i18n::AdjustStringForLocaleDirection(&title);
206
207 switch (process_type_) {
208 case content::PROCESS_TYPE_UTILITY:
209 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX, title);
210 case content::PROCESS_TYPE_GPU:
211 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_GPU_PREFIX);
212 case content::PROCESS_TYPE_PPAPI_PLUGIN:
213 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX, title);
214 case content::PROCESS_TYPE_PPAPI_BROKER:
215 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_BROKER_PREFIX,
216 title);
217 case PROCESS_TYPE_NACL_BROKER:
218 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX);
219 case PROCESS_TYPE_NACL_LOADER:
220 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, title);
221 // These types don't need display names or get them from elsewhere.
222 case content::PROCESS_TYPE_BROWSER:
223 case content::PROCESS_TYPE_RENDERER:
224 case content::PROCESS_TYPE_ZYGOTE:
225 case content::PROCESS_TYPE_SANDBOX_HELPER:
226 case content::PROCESS_TYPE_MAX:
227 NOTREACHED();
228 break;
229 case content::PROCESS_TYPE_UNKNOWN:
230 NOTREACHED() << "Need localized name for child process type.";
231 }
232
233 return title;
234 }
235
236 void ChildProcessResource::Refresh() {
237 if (resource_usage_)
238 resource_usage_->Refresh(base::Closure());
239 }
240
241 bool ChildProcessResource::ReportsV8MemoryStats() const {
242 if (resource_usage_)
243 return resource_usage_->ReportsV8MemoryStats();
244 return false;
245 }
246
247 size_t ChildProcessResource::GetV8MemoryAllocated() const {
248 if (resource_usage_)
249 return resource_usage_->GetV8MemoryAllocated();
250 return 0;
251 }
252
253 size_t ChildProcessResource::GetV8MemoryUsed() const {
254 if (resource_usage_)
255 return resource_usage_->GetV8MemoryUsed();
256 return 0;
257 }
258
259 ////////////////////////////////////////////////////////////////////////////////
260 // ChildProcessResourceProvider class
261 ////////////////////////////////////////////////////////////////////////////////
262
263 ChildProcessResourceProvider::
264 ChildProcessResourceProvider(TaskManager* task_manager)
265 : task_manager_(task_manager),
266 updating_(false) {
267 }
268
269 ChildProcessResourceProvider::~ChildProcessResourceProvider() {
270 }
271
272 Resource* ChildProcessResourceProvider::GetResource(
273 int origin_pid,
274 int child_id,
275 int route_id) {
276 PidResourceMap::iterator iter = pid_to_resources_.find(origin_pid);
277 if (iter != pid_to_resources_.end())
278 return iter->second;
279 else
280 return NULL;
281 }
282
283 void ChildProcessResourceProvider::StartUpdating() {
284 DCHECK(!updating_);
285 updating_ = true;
286
287 // Get the existing child processes.
288 BrowserThread::PostTask(
289 BrowserThread::IO, FROM_HERE,
290 base::Bind(
291 &ChildProcessResourceProvider::RetrieveChildProcessData,
292 this));
293
294 BrowserChildProcessObserver::Add(this);
295 }
296
297 void ChildProcessResourceProvider::StopUpdating() {
298 DCHECK(updating_);
299 updating_ = false;
300
301 // Delete all the resources.
302 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
303
304 resources_.clear();
305 pid_to_resources_.clear();
306
307 BrowserChildProcessObserver::Remove(this);
308 }
309
310 void ChildProcessResourceProvider::BrowserChildProcessHostConnected(
311 const content::ChildProcessData& data) {
312 DCHECK(updating_);
313
314 if (resources_.count(data.handle)) {
315 // The case may happen that we have added a child_process_info as part of
316 // the iteration performed during StartUpdating() call but the notification
317 // that it has connected was not fired yet. So when the notification
318 // happens, we already know about this plugin and just ignore it.
319 return;
320 }
321 AddToTaskManager(data);
322 }
323
324 void ChildProcessResourceProvider::
325 BrowserChildProcessHostDisconnected(
326 const content::ChildProcessData& data) {
327 DCHECK(updating_);
328
329 ChildProcessMap::iterator iter = resources_.find(data.handle);
330 if (iter == resources_.end()) {
331 // ChildProcessData disconnection notifications are asynchronous, so we
332 // might be notified for a plugin we don't know anything about (if it was
333 // closed before the task manager was shown and destroyed after that).
334 return;
335 }
336 // Remove the resource from the Task Manager.
337 ChildProcessResource* resource = iter->second;
338 task_manager_->RemoveResource(resource);
339 // Remove it from the provider.
340 resources_.erase(iter);
341 // Remove it from our pid map.
342 PidResourceMap::iterator pid_iter =
343 pid_to_resources_.find(resource->process_id());
344 DCHECK(pid_iter != pid_to_resources_.end());
345 if (pid_iter != pid_to_resources_.end())
346 pid_to_resources_.erase(pid_iter);
347
348 // Finally, delete the resource.
349 delete resource;
350 }
351
352 void ChildProcessResourceProvider::AddToTaskManager(
353 const content::ChildProcessData& child_process_data) {
354 ChildProcessResource* resource =
355 new ChildProcessResource(
356 child_process_data.process_type,
357 child_process_data.name,
358 child_process_data.handle,
359 child_process_data.id);
360 resources_[child_process_data.handle] = resource;
361 pid_to_resources_[resource->process_id()] = resource;
362 task_manager_->AddResource(resource);
363 }
364
365 // The ChildProcessData::Iterator has to be used from the IO thread.
366 void ChildProcessResourceProvider::RetrieveChildProcessData() {
367 std::vector<content::ChildProcessData> child_processes;
368 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
369 // Only add processes which are already started, since we need their handle.
370 if (iter.GetData().handle == base::kNullProcessHandle)
371 continue;
372 child_processes.push_back(iter.GetData());
373 }
374 // Now notify the UI thread that we have retrieved information about child
375 // processes.
376 BrowserThread::PostTask(
377 BrowserThread::UI, FROM_HERE,
378 base::Bind(
379 &ChildProcessResourceProvider::ChildProcessDataRetreived,
380 this, child_processes));
381 }
382
383 // This is called on the UI thread.
384 void ChildProcessResourceProvider::ChildProcessDataRetreived(
385 const std::vector<content::ChildProcessData>& child_processes) {
386 for (size_t i = 0; i < child_processes.size(); ++i)
387 AddToTaskManager(child_processes[i]);
388
389 task_manager_->model()->NotifyDataReady();
390 }
391
392 } // namespace task_manager
OLDNEW
« no previous file with comments | « chrome/browser/task_manager/child_process_resource_provider.h ('k') | chrome/browser/task_manager/extension_information.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698