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