OLD | NEW |
| (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/task_manager_extension_process_resource_pr
ovider.h" | |
6 | |
7 #include "base/string16.h" | |
8 #include "base/utf_string_conversions.h" | |
9 #include "chrome/browser/browser_process.h" | |
10 #include "chrome/browser/devtools/devtools_window.h" | |
11 #include "chrome/browser/extensions/extension_host.h" | |
12 #include "chrome/browser/extensions/extension_process_manager.h" | |
13 #include "chrome/browser/extensions/extension_system.h" | |
14 #include "chrome/browser/profiles/profile.h" | |
15 #include "chrome/browser/profiles/profile_manager.h" | |
16 #include "chrome/browser/task_manager/task_manager_resource_util.h" | |
17 #include "chrome/common/extensions/extension.h" | |
18 #include "content/public/browser/render_process_host.h" | |
19 #include "content/public/browser/render_view_host.h" | |
20 #include "content/public/browser/site_instance.h" | |
21 #include "content/public/browser/web_contents.h" | |
22 #include "extensions/browser/view_type_utils.h" | |
23 #include "grit/theme_resources.h" | |
24 #include "ui/base/l10n/l10n_util.h" | |
25 #include "ui/base/resource/resource_bundle.h" | |
26 #include "ui/gfx/image/image_skia.h" | |
27 | |
28 using content::WebContents; | |
29 using extensions::Extension; | |
30 | |
31 class TaskManagerExtensionProcessResource : public TaskManager::Resource { | |
32 public: | |
33 explicit TaskManagerExtensionProcessResource( | |
34 content::RenderViewHost* render_view_host); | |
35 virtual ~TaskManagerExtensionProcessResource(); | |
36 | |
37 // TaskManager::Resource methods: | |
38 virtual string16 GetTitle() const OVERRIDE; | |
39 virtual string16 GetProfileName() const OVERRIDE; | |
40 virtual gfx::ImageSkia GetIcon() const OVERRIDE; | |
41 virtual base::ProcessHandle GetProcess() const OVERRIDE; | |
42 virtual int GetUniqueChildProcessId() const OVERRIDE; | |
43 virtual Type GetType() const OVERRIDE; | |
44 virtual bool CanInspect() const OVERRIDE; | |
45 virtual void Inspect() const OVERRIDE; | |
46 virtual bool SupportNetworkUsage() const OVERRIDE; | |
47 virtual void SetSupportNetworkUsage() OVERRIDE; | |
48 virtual const extensions::Extension* GetExtension() const OVERRIDE; | |
49 | |
50 // Returns the pid of the extension process. | |
51 int process_id() const { return pid_; } | |
52 | |
53 // Returns true if the associated extension has a background page. | |
54 virtual bool IsBackground() const OVERRIDE; | |
55 | |
56 private: | |
57 // The icon painted for the extension process. | |
58 static gfx::ImageSkia* default_icon_; | |
59 | |
60 content::RenderViewHost* render_view_host_; | |
61 | |
62 // Cached data about the extension. | |
63 base::ProcessHandle process_handle_; | |
64 int pid_; | |
65 int unique_process_id_; | |
66 string16 title_; | |
67 | |
68 DISALLOW_COPY_AND_ASSIGN(TaskManagerExtensionProcessResource); | |
69 }; | |
70 | |
71 gfx::ImageSkia* TaskManagerExtensionProcessResource::default_icon_ = NULL; | |
72 | |
73 TaskManagerExtensionProcessResource::TaskManagerExtensionProcessResource( | |
74 content::RenderViewHost* render_view_host) | |
75 : render_view_host_(render_view_host) { | |
76 if (!default_icon_) { | |
77 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
78 default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON); | |
79 } | |
80 process_handle_ = render_view_host_->GetProcess()->GetHandle(); | |
81 unique_process_id_ = render_view_host->GetProcess()->GetID(); | |
82 pid_ = base::GetProcId(process_handle_); | |
83 string16 extension_name = UTF8ToUTF16(GetExtension()->name()); | |
84 DCHECK(!extension_name.empty()); | |
85 | |
86 Profile* profile = Profile::FromBrowserContext( | |
87 render_view_host->GetProcess()->GetBrowserContext()); | |
88 int message_id = TaskManagerResourceUtil::GetMessagePrefixID( | |
89 GetExtension()->is_app(), | |
90 true, // is_extension | |
91 profile->IsOffTheRecord(), | |
92 false, // is_prerender | |
93 false, // is_instant_overlay | |
94 IsBackground()); | |
95 title_ = l10n_util::GetStringFUTF16(message_id, extension_name); | |
96 } | |
97 | |
98 TaskManagerExtensionProcessResource::~TaskManagerExtensionProcessResource() { | |
99 } | |
100 | |
101 string16 TaskManagerExtensionProcessResource::GetTitle() const { | |
102 return title_; | |
103 } | |
104 | |
105 string16 TaskManagerExtensionProcessResource::GetProfileName() const { | |
106 return TaskManagerResourceUtil::GetProfileNameFromInfoCache( | |
107 Profile::FromBrowserContext( | |
108 render_view_host_->GetProcess()->GetBrowserContext())); | |
109 } | |
110 | |
111 gfx::ImageSkia TaskManagerExtensionProcessResource::GetIcon() const { | |
112 return *default_icon_; | |
113 } | |
114 | |
115 base::ProcessHandle TaskManagerExtensionProcessResource::GetProcess() const { | |
116 return process_handle_; | |
117 } | |
118 | |
119 int TaskManagerExtensionProcessResource::GetUniqueChildProcessId() const { | |
120 return unique_process_id_; | |
121 } | |
122 | |
123 TaskManager::Resource::Type | |
124 TaskManagerExtensionProcessResource::GetType() const { | |
125 return EXTENSION; | |
126 } | |
127 | |
128 bool TaskManagerExtensionProcessResource::CanInspect() const { | |
129 return true; | |
130 } | |
131 | |
132 void TaskManagerExtensionProcessResource::Inspect() const { | |
133 DevToolsWindow::OpenDevToolsWindow(render_view_host_); | |
134 } | |
135 | |
136 bool TaskManagerExtensionProcessResource::SupportNetworkUsage() const { | |
137 return true; | |
138 } | |
139 | |
140 void TaskManagerExtensionProcessResource::SetSupportNetworkUsage() { | |
141 NOTREACHED(); | |
142 } | |
143 | |
144 const Extension* TaskManagerExtensionProcessResource::GetExtension() const { | |
145 Profile* profile = Profile::FromBrowserContext( | |
146 render_view_host_->GetProcess()->GetBrowserContext()); | |
147 ExtensionProcessManager* process_manager = | |
148 extensions::ExtensionSystem::Get(profile)->process_manager(); | |
149 return process_manager->GetExtensionForRenderViewHost(render_view_host_); | |
150 } | |
151 | |
152 bool TaskManagerExtensionProcessResource::IsBackground() const { | |
153 WebContents* web_contents = | |
154 WebContents::FromRenderViewHost(render_view_host_); | |
155 extensions::ViewType view_type = extensions::GetViewType(web_contents); | |
156 return view_type == extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE; | |
157 } | |
158 | |
159 //////////////////////////////////////////////////////////////////////////////// | |
160 // TaskManagerExtensionProcessResourceProvider class | |
161 //////////////////////////////////////////////////////////////////////////////// | |
162 | |
163 TaskManagerExtensionProcessResourceProvider:: | |
164 TaskManagerExtensionProcessResourceProvider(TaskManager* task_manager) | |
165 : task_manager_(task_manager), | |
166 updating_(false) { | |
167 } | |
168 | |
169 TaskManagerExtensionProcessResourceProvider:: | |
170 ~TaskManagerExtensionProcessResourceProvider() { | |
171 } | |
172 | |
173 TaskManager::Resource* TaskManagerExtensionProcessResourceProvider::GetResource( | |
174 int origin_pid, | |
175 int render_process_host_id, | |
176 int routing_id) { | |
177 // If an origin PID was specified, the request is from a plugin, not the | |
178 // render view host process | |
179 if (origin_pid) | |
180 return NULL; | |
181 | |
182 for (ExtensionRenderViewHostMap::iterator i = resources_.begin(); | |
183 i != resources_.end(); i++) { | |
184 if (i->first->GetSiteInstance()->GetProcess()->GetID() == | |
185 render_process_host_id && | |
186 i->first->GetRoutingID() == routing_id) | |
187 return i->second; | |
188 } | |
189 | |
190 // Can happen if the page went away while a network request was being | |
191 // performed. | |
192 return NULL; | |
193 } | |
194 | |
195 void TaskManagerExtensionProcessResourceProvider::StartUpdating() { | |
196 DCHECK(!updating_); | |
197 updating_ = true; | |
198 | |
199 // Add all the existing extension views from all Profiles, including those | |
200 // from incognito split mode. | |
201 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
202 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles()); | |
203 size_t num_default_profiles = profiles.size(); | |
204 for (size_t i = 0; i < num_default_profiles; ++i) { | |
205 if (profiles[i]->HasOffTheRecordProfile()) { | |
206 profiles.push_back(profiles[i]->GetOffTheRecordProfile()); | |
207 } | |
208 } | |
209 | |
210 for (size_t i = 0; i < profiles.size(); ++i) { | |
211 ExtensionProcessManager* process_manager = | |
212 extensions::ExtensionSystem::Get(profiles[i])->process_manager(); | |
213 if (process_manager) { | |
214 const ExtensionProcessManager::ViewSet all_views = | |
215 process_manager->GetAllViews(); | |
216 ExtensionProcessManager::ViewSet::const_iterator jt = all_views.begin(); | |
217 for (; jt != all_views.end(); ++jt) { | |
218 content::RenderViewHost* rvh = *jt; | |
219 // Don't add dead extension processes. | |
220 if (!rvh->IsRenderViewLive()) | |
221 continue; | |
222 | |
223 AddToTaskManager(rvh); | |
224 } | |
225 } | |
226 } | |
227 | |
228 // Register for notifications about extension process changes. | |
229 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED, | |
230 content::NotificationService::AllBrowserContextsAndSources()); | |
231 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | |
232 content::NotificationService::AllBrowserContextsAndSources()); | |
233 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED, | |
234 content::NotificationService::AllBrowserContextsAndSources()); | |
235 } | |
236 | |
237 void TaskManagerExtensionProcessResourceProvider::StopUpdating() { | |
238 DCHECK(updating_); | |
239 updating_ = false; | |
240 | |
241 // Unregister for notifications about extension process changes. | |
242 registrar_.Remove( | |
243 this, chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED, | |
244 content::NotificationService::AllBrowserContextsAndSources()); | |
245 registrar_.Remove( | |
246 this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, | |
247 content::NotificationService::AllBrowserContextsAndSources()); | |
248 registrar_.Remove( | |
249 this, chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED, | |
250 content::NotificationService::AllBrowserContextsAndSources()); | |
251 | |
252 // Delete all the resources. | |
253 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); | |
254 | |
255 resources_.clear(); | |
256 } | |
257 | |
258 void TaskManagerExtensionProcessResourceProvider::Observe( | |
259 int type, | |
260 const content::NotificationSource& source, | |
261 const content::NotificationDetails& details) { | |
262 switch (type) { | |
263 case chrome::NOTIFICATION_EXTENSION_VIEW_REGISTERED: | |
264 AddToTaskManager( | |
265 content::Details<content::RenderViewHost>(details).ptr()); | |
266 break; | |
267 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: | |
268 RemoveFromTaskManager( | |
269 content::Details<extensions::ExtensionHost>(details).ptr()-> | |
270 render_view_host()); | |
271 break; | |
272 case chrome::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED: | |
273 RemoveFromTaskManager( | |
274 content::Details<content::RenderViewHost>(details).ptr()); | |
275 break; | |
276 default: | |
277 NOTREACHED() << "Unexpected notification."; | |
278 return; | |
279 } | |
280 } | |
281 | |
282 bool TaskManagerExtensionProcessResourceProvider:: | |
283 IsHandledByThisProvider(content::RenderViewHost* render_view_host) { | |
284 WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host); | |
285 // Don't add WebContents that belong to a guest (those are handled by | |
286 // TaskManagerGuestResourceProvider). Otherwise they will be added twice, and | |
287 // in this case they will have the app's name as a title (due to the | |
288 // TaskManagerExtensionProcessResource constructor). | |
289 if (web_contents->GetRenderProcessHost()->IsGuest()) | |
290 return false; | |
291 extensions::ViewType view_type = extensions::GetViewType(web_contents); | |
292 // Don't add WebContents (those are handled by | |
293 // TaskManagerTabContentsResourceProvider) or background contents (handled | |
294 // by TaskManagerBackgroundResourceProvider). | |
295 #if defined(USE_ASH) | |
296 return (view_type != extensions::VIEW_TYPE_TAB_CONTENTS && | |
297 view_type != extensions::VIEW_TYPE_BACKGROUND_CONTENTS); | |
298 #else | |
299 return (view_type != extensions::VIEW_TYPE_TAB_CONTENTS && | |
300 view_type != extensions::VIEW_TYPE_BACKGROUND_CONTENTS && | |
301 view_type != extensions::VIEW_TYPE_PANEL); | |
302 #endif // USE_ASH | |
303 } | |
304 | |
305 void TaskManagerExtensionProcessResourceProvider::AddToTaskManager( | |
306 content::RenderViewHost* render_view_host) { | |
307 if (!IsHandledByThisProvider(render_view_host)) | |
308 return; | |
309 | |
310 TaskManagerExtensionProcessResource* resource = | |
311 new TaskManagerExtensionProcessResource(render_view_host); | |
312 DCHECK(resources_.find(render_view_host) == resources_.end()); | |
313 resources_[render_view_host] = resource; | |
314 task_manager_->AddResource(resource); | |
315 } | |
316 | |
317 void TaskManagerExtensionProcessResourceProvider::RemoveFromTaskManager( | |
318 content::RenderViewHost* render_view_host) { | |
319 if (!updating_) | |
320 return; | |
321 std::map<content::RenderViewHost*, TaskManagerExtensionProcessResource*> | |
322 ::iterator iter = resources_.find(render_view_host); | |
323 if (iter == resources_.end()) | |
324 return; | |
325 | |
326 // Remove the resource from the Task Manager. | |
327 TaskManagerExtensionProcessResource* resource = iter->second; | |
328 task_manager_->RemoveResource(resource); | |
329 | |
330 // Remove it from the provider. | |
331 resources_.erase(iter); | |
332 | |
333 // Finally, delete the resource. | |
334 delete resource; | |
335 } | |
OLD | NEW |