Home | History | Annotate | Download | only in task_manager
      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