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