Home | History | Annotate | Download | only in task_manager
      1 // Copyright (c) 2012 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/notification_resource_provider.h"
      6 
      7 #include "base/strings/string16.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/chrome_notification_types.h"
     10 #include "chrome/browser/devtools/devtools_window.h"
     11 #include "chrome/browser/notifications/balloon_host.h"
     12 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
     13 #include "chrome/browser/task_manager/task_manager.h"
     14 #include "content/public/browser/notification_service.h"
     15 #include "content/public/browser/render_process_host.h"
     16 #include "content/public/browser/web_contents.h"
     17 #include "grit/generated_resources.h"
     18 #include "grit/theme_resources.h"
     19 #include "ui/base/l10n/l10n_util.h"
     20 #include "ui/base/resource/resource_bundle.h"
     21 #include "ui/gfx/image/image_skia.h"
     22 
     23 namespace task_manager {
     24 
     25 class NotificationResource : public Resource {
     26  public:
     27   explicit NotificationResource(BalloonHost* balloon_host);
     28   virtual ~NotificationResource();
     29 
     30   // Resource interface
     31   virtual base::string16 GetTitle() const OVERRIDE;
     32   virtual base::string16 GetProfileName() const OVERRIDE;
     33   virtual gfx::ImageSkia GetIcon() const OVERRIDE;
     34   virtual base::ProcessHandle GetProcess() const OVERRIDE;
     35   virtual int GetUniqueChildProcessId() const OVERRIDE;
     36   virtual Type GetType() const OVERRIDE;
     37   virtual bool CanInspect() const OVERRIDE;
     38   virtual void Inspect() const OVERRIDE;
     39   virtual bool SupportNetworkUsage() const OVERRIDE;
     40   virtual void SetSupportNetworkUsage() OVERRIDE { }
     41 
     42  private:
     43   // The icon painted for notifications.       .
     44   static gfx::ImageSkia* default_icon_;
     45 
     46   // Non-owned pointer to the balloon host.
     47   BalloonHost* balloon_host_;
     48 
     49   // Cached data about the balloon host.
     50   base::ProcessHandle process_handle_;
     51   int pid_;
     52   int unique_process_id_;
     53   base::string16 title_;
     54 
     55   DISALLOW_COPY_AND_ASSIGN(NotificationResource);
     56 };
     57 
     58 gfx::ImageSkia* NotificationResource::default_icon_ = NULL;
     59 
     60 NotificationResource::NotificationResource(BalloonHost* balloon_host)
     61     : balloon_host_(balloon_host) {
     62   if (!default_icon_) {
     63     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
     64     default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON);
     65   }
     66   process_handle_ =
     67       balloon_host_->web_contents()->GetRenderProcessHost()->GetHandle();
     68   unique_process_id_ =
     69       balloon_host_->web_contents()->GetRenderProcessHost()->GetID();
     70   pid_ = base::GetProcId(process_handle_);
     71   title_ = l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NOTIFICATION_PREFIX,
     72                                       balloon_host_->GetSource());
     73 }
     74 
     75 NotificationResource::~NotificationResource() {
     76 }
     77 
     78 base::string16 NotificationResource::GetTitle() const {
     79   return title_;
     80 }
     81 
     82 base::string16 NotificationResource::GetProfileName() const {
     83   return base::string16();
     84 }
     85 
     86 gfx::ImageSkia NotificationResource::GetIcon() const {
     87   return *default_icon_;
     88 }
     89 
     90 base::ProcessHandle NotificationResource::GetProcess() const {
     91   return process_handle_;
     92 }
     93 
     94 int NotificationResource::GetUniqueChildProcessId() const {
     95   return unique_process_id_;
     96 }
     97 
     98 Resource::Type NotificationResource::GetType() const {
     99   return NOTIFICATION;
    100 }
    101 
    102 bool NotificationResource::CanInspect() const {
    103   return true;
    104 }
    105 
    106 void NotificationResource::Inspect() const {
    107   DevToolsWindow::OpenDevToolsWindow(
    108       balloon_host_->web_contents()->GetRenderViewHost());
    109 }
    110 
    111 bool NotificationResource::SupportNetworkUsage() const {
    112   return false;
    113 }
    114 
    115 ////////////////////////////////////////////////////////////////////////////////
    116 // NotificationResourceProvider class
    117 ////////////////////////////////////////////////////////////////////////////////
    118 
    119 // static
    120 NotificationResourceProvider*
    121 NotificationResourceProvider::Create(TaskManager* task_manager) {
    122   return new NotificationResourceProvider(task_manager);
    123 }
    124 
    125 NotificationResourceProvider::
    126     NotificationResourceProvider(TaskManager* task_manager)
    127     : task_manager_(task_manager),
    128       updating_(false) {
    129 }
    130 
    131 NotificationResourceProvider::~NotificationResourceProvider() {
    132 }
    133 
    134 Resource* NotificationResourceProvider::GetResource(
    135     int origin_pid,
    136     int render_process_host_id,
    137     int routing_id) {
    138   // TODO(johnnyg): provide resources by pid if necessary.
    139   return NULL;
    140 }
    141 
    142 void NotificationResourceProvider::StartUpdating() {
    143   // MessageCenter does not use Balloons.
    144   if (NotificationUIManager::DelegatesToMessageCenter())
    145     return;
    146 
    147   DCHECK(!updating_);
    148   updating_ = true;
    149 
    150   // Add all the existing BalloonHosts.
    151   BalloonNotificationUIManager* balloon_manager =
    152       static_cast<BalloonNotificationUIManager*>(
    153           g_browser_process->notification_ui_manager());
    154   BalloonCollection* collection = balloon_manager->balloon_collection();
    155   const BalloonCollection::Balloons& balloons =
    156       collection->GetActiveBalloons();
    157   for (BalloonCollection::Balloons::const_iterator it = balloons.begin();
    158        it != balloons.end(); ++it) {
    159     BalloonHost* balloon_host = (*it)->balloon_view()->GetHost();
    160     if (balloon_host)
    161       AddToTaskManager(balloon_host);
    162   }
    163   // Register for notifications about extension process changes.
    164   registrar_.Add(this, chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED,
    165                  content::NotificationService::AllSources());
    166   registrar_.Add(this, chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
    167                  content::NotificationService::AllSources());
    168 }
    169 
    170 void NotificationResourceProvider::StopUpdating() {
    171   // MessageCenter does not use Balloons.
    172   if (NotificationUIManager::DelegatesToMessageCenter())
    173     return;
    174 
    175   DCHECK(updating_);
    176   updating_ = false;
    177 
    178   // Unregister for notifications about extension process changes.
    179   registrar_.Remove(this, chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED,
    180                     content::NotificationService::AllSources());
    181   registrar_.Remove(this, chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED,
    182                     content::NotificationService::AllSources());
    183 
    184   // Delete all the resources.
    185   STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
    186   resources_.clear();
    187 }
    188 
    189 void NotificationResourceProvider::Observe(
    190     int type,
    191     const content::NotificationSource& source,
    192     const content::NotificationDetails& details) {
    193   switch (type) {
    194     case chrome::NOTIFICATION_NOTIFY_BALLOON_CONNECTED:
    195       AddToTaskManager(content::Source<BalloonHost>(source).ptr());
    196       break;
    197     case chrome::NOTIFICATION_NOTIFY_BALLOON_DISCONNECTED:
    198       RemoveFromTaskManager(content::Source<BalloonHost>(source).ptr());
    199       break;
    200     default:
    201       NOTREACHED() << "Unexpected notification.";
    202       return;
    203   }
    204 }
    205 
    206 void NotificationResourceProvider::AddToTaskManager(
    207     BalloonHost* balloon_host) {
    208   NotificationResource* resource = new NotificationResource(balloon_host);
    209   DCHECK(resources_.find(balloon_host) == resources_.end());
    210   resources_[balloon_host] = resource;
    211   task_manager_->AddResource(resource);
    212 }
    213 
    214 void NotificationResourceProvider::RemoveFromTaskManager(
    215     BalloonHost* balloon_host) {
    216   if (!updating_)
    217     return;
    218   std::map<BalloonHost*, NotificationResource*>::iterator iter =
    219       resources_.find(balloon_host);
    220   if (iter == resources_.end())
    221     return;
    222 
    223   // Remove the resource from the Task Manager.
    224   NotificationResource* resource = iter->second;
    225   task_manager_->RemoveResource(resource);
    226 
    227   // Remove it from the map.
    228   resources_.erase(iter);
    229 
    230   // Finally, delete the resource.
    231   delete resource;
    232 }
    233 
    234 }  // namespace task_manager
    235