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/guest_resource_provider.h" 6 7 #include "base/strings/string16.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/favicon/favicon_tab_helper.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/task_manager/renderer_resource.h" 12 #include "chrome/browser/task_manager/resource_provider.h" 13 #include "chrome/browser/task_manager/task_manager.h" 14 #include "chrome/browser/task_manager/task_manager_util.h" 15 #include "content/public/browser/notification_service.h" 16 #include "content/public/browser/render_process_host.h" 17 #include "content/public/browser/render_view_host.h" 18 #include "content/public/browser/site_instance.h" 19 #include "content/public/browser/web_contents.h" 20 #include "grit/generated_resources.h" 21 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/gfx/image/image.h" 23 #include "ui/gfx/image/image_skia.h" 24 25 using content::RenderProcessHost; 26 using content::RenderViewHost; 27 using content::RenderWidgetHost; 28 using content::WebContents; 29 using extensions::Extension; 30 31 namespace task_manager { 32 33 class GuestResource : public RendererResource { 34 public: 35 explicit GuestResource(content::RenderViewHost* render_view_host); 36 virtual ~GuestResource(); 37 38 // Resource methods: 39 virtual Type GetType() const OVERRIDE; 40 virtual string16 GetTitle() const OVERRIDE; 41 virtual string16 GetProfileName() const OVERRIDE; 42 virtual gfx::ImageSkia GetIcon() const OVERRIDE; 43 virtual content::WebContents* GetWebContents() const OVERRIDE; 44 virtual const extensions::Extension* GetExtension() const OVERRIDE; 45 46 private: 47 DISALLOW_COPY_AND_ASSIGN(GuestResource); 48 }; 49 50 GuestResource::GuestResource(RenderViewHost* render_view_host) 51 : RendererResource( 52 render_view_host->GetSiteInstance()->GetProcess()->GetHandle(), 53 render_view_host) { 54 } 55 56 GuestResource::~GuestResource() { 57 } 58 59 Resource::Type GuestResource::GetType() const { 60 return GUEST; 61 } 62 63 string16 GuestResource::GetTitle() const { 64 WebContents* web_contents = GetWebContents(); 65 const int message_id = IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX; 66 if (web_contents) { 67 string16 title = util::GetTitleFromWebContents(web_contents); 68 return l10n_util::GetStringFUTF16(message_id, title); 69 } 70 return l10n_util::GetStringFUTF16(message_id, string16()); 71 } 72 73 string16 GuestResource::GetProfileName() const { 74 WebContents* web_contents = GetWebContents(); 75 if (web_contents) { 76 Profile* profile = Profile::FromBrowserContext( 77 web_contents->GetBrowserContext()); 78 return util::GetProfileNameFromInfoCache(profile); 79 } 80 return string16(); 81 } 82 83 gfx::ImageSkia GuestResource::GetIcon() const { 84 WebContents* web_contents = GetWebContents(); 85 if (web_contents && FaviconTabHelper::FromWebContents(web_contents)) { 86 return FaviconTabHelper::FromWebContents(web_contents)-> 87 GetFavicon().AsImageSkia(); 88 } 89 return gfx::ImageSkia(); 90 } 91 92 WebContents* GuestResource::GetWebContents() const { 93 return WebContents::FromRenderViewHost(render_view_host()); 94 } 95 96 const Extension* GuestResource::GetExtension() const { 97 return NULL; 98 } 99 100 GuestResourceProvider::GuestResourceProvider(TaskManager* task_manager) 101 : updating_(false), 102 task_manager_(task_manager) { 103 } 104 105 GuestResourceProvider::~GuestResourceProvider() { 106 } 107 108 Resource* GuestResourceProvider::GetResource( 109 int origin_pid, 110 int render_process_host_id, 111 int routing_id) { 112 // If an origin PID was specified then the request originated in a plugin 113 // working on the WebContents's behalf, so ignore it. 114 if (origin_pid) 115 return NULL; 116 117 for (GuestResourceMap::iterator i = resources_.begin(); 118 i != resources_.end(); ++i) { 119 WebContents* contents = WebContents::FromRenderViewHost(i->first); 120 if (contents && 121 contents->GetRenderProcessHost()->GetID() == render_process_host_id && 122 contents->GetRenderViewHost()->GetRoutingID() == routing_id) { 123 return i->second; 124 } 125 } 126 127 return NULL; 128 } 129 130 void GuestResourceProvider::StartUpdating() { 131 DCHECK(!updating_); 132 updating_ = true; 133 134 // Add all the existing guest WebContents. 135 RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts(); 136 for (size_t i = 0; i < widgets.size(); ++i) { 137 if (widgets[i]->IsRenderView()) { 138 RenderViewHost* rvh = RenderViewHost::From(widgets[i]); 139 if (rvh->IsSubframe()) 140 Add(rvh); 141 } 142 } 143 144 // Then we register for notifications to get new guests. 145 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, 146 content::NotificationService::AllBrowserContextsAndSources()); 147 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 148 content::NotificationService::AllBrowserContextsAndSources()); 149 } 150 151 void GuestResourceProvider::StopUpdating() { 152 DCHECK(updating_); 153 updating_ = false; 154 155 // Unregister for notifications. 156 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED, 157 content::NotificationService::AllBrowserContextsAndSources()); 158 registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, 159 content::NotificationService::AllBrowserContextsAndSources()); 160 161 // Delete all the resources. 162 STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); 163 164 resources_.clear(); 165 } 166 167 void GuestResourceProvider::Add(RenderViewHost* render_view_host) { 168 GuestResource* resource = new GuestResource(render_view_host); 169 resources_[render_view_host] = resource; 170 task_manager_->AddResource(resource); 171 } 172 173 void GuestResourceProvider::Remove(RenderViewHost* render_view_host) { 174 if (!updating_) 175 return; 176 177 GuestResourceMap::iterator iter = resources_.find(render_view_host); 178 if (iter == resources_.end()) 179 return; 180 181 GuestResource* resource = iter->second; 182 task_manager_->RemoveResource(resource); 183 resources_.erase(iter); 184 delete resource; 185 } 186 187 void GuestResourceProvider::Observe(int type, 188 const content::NotificationSource& source, 189 const content::NotificationDetails& details) { 190 WebContents* web_contents = content::Source<WebContents>(source).ptr(); 191 if (!web_contents || !web_contents->GetRenderViewHost()->IsSubframe()) 192 return; 193 194 switch (type) { 195 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: 196 Add(web_contents->GetRenderViewHost()); 197 break; 198 case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED: 199 Remove(web_contents->GetRenderViewHost()); 200 break; 201 default: 202 NOTREACHED() << "Unexpected notification."; 203 } 204 } 205 206 } // namespace task_manager 207