| 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 |