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