• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/extensions/api/system_indicator/system_indicator_manager.h"
6 
7 #include "base/memory/linked_ptr.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/extension_action.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/status_icons/status_icon.h"
14 #include "chrome/browser/status_icons/status_icon_observer.h"
15 #include "chrome/browser/status_icons/status_tray.h"
16 #include "chrome/common/extensions/api/system_indicator.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_source.h"
19 #include "extensions/browser/event_router.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/common/extension.h"
23 #include "ui/gfx/image/image.h"
24 
25 namespace extensions {
26 
27 namespace system_indicator = api::system_indicator;
28 
29 // Observes clicks on a given status icon and forwards the event to the
30 // appropriate extension.  Handles icon updates, and responsible for creating
31 // and removing the icon from the notification area during construction and
32 // destruction.
33 class ExtensionIndicatorIcon : public StatusIconObserver,
34                                public ExtensionActionIconFactory::Observer {
35  public:
36   static ExtensionIndicatorIcon* Create(const Extension* extension,
37                                         const ExtensionAction* action,
38                                         Profile* profile,
39                                         StatusTray* status_tray);
40   virtual ~ExtensionIndicatorIcon();
41 
42   // StatusIconObserver implementation.
43   virtual void OnStatusIconClicked() OVERRIDE;
44 
45   // ExtensionActionIconFactory::Observer implementation.
46   virtual void OnIconUpdated() OVERRIDE;
47 
48  private:
49   ExtensionIndicatorIcon(const Extension* extension,
50                          const ExtensionAction* action,
51                          Profile* profile,
52                          StatusTray* status_tray);
53 
54   const extensions::Extension* extension_;
55   StatusTray* status_tray_;
56   StatusIcon* icon_;
57   Profile* profile_;
58   ExtensionActionIconFactory icon_factory_;
59 };
60 
Create(const Extension * extension,const ExtensionAction * action,Profile * profile,StatusTray * status_tray)61 ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create(
62     const Extension* extension,
63     const ExtensionAction* action,
64     Profile* profile,
65     StatusTray* status_tray) {
66   scoped_ptr<ExtensionIndicatorIcon> extension_icon(
67       new ExtensionIndicatorIcon(extension, action, profile, status_tray));
68 
69   // Check if a status icon was successfully created.
70   if (extension_icon->icon_)
71     return extension_icon.release();
72 
73   // We could not create a status icon.
74   return NULL;
75 }
76 
~ExtensionIndicatorIcon()77 ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
78   if (icon_) {
79     icon_->RemoveObserver(this);
80     status_tray_->RemoveStatusIcon(icon_);
81   }
82 }
83 
OnStatusIconClicked()84 void ExtensionIndicatorIcon::OnStatusIconClicked() {
85   scoped_ptr<base::ListValue> params(
86       api::system_indicator::OnClicked::Create());
87 
88   EventRouter* event_router = EventRouter::Get(profile_);
89   scoped_ptr<Event> event(new Event(
90       system_indicator::OnClicked::kEventName,
91       params.Pass(),
92       profile_));
93   event_router->DispatchEventToExtension(
94       extension_->id(), event.Pass());
95 }
96 
OnIconUpdated()97 void ExtensionIndicatorIcon::OnIconUpdated() {
98   icon_->SetImage(
99       icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia());
100 }
101 
ExtensionIndicatorIcon(const Extension * extension,const ExtensionAction * action,Profile * profile,StatusTray * status_tray)102 ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension,
103                                                const ExtensionAction* action,
104                                                Profile* profile,
105                                                StatusTray* status_tray)
106     : extension_(extension),
107       status_tray_(status_tray),
108       icon_(NULL),
109       profile_(profile),
110       icon_factory_(profile, extension, action, this) {
111   // Get the icon image and tool tip for the status icon. The extension name is
112   // used as the tool tip.
113   gfx::ImageSkia icon_image =
114       icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia();
115   base::string16 tool_tip = base::UTF8ToUTF16(extension_->name());
116 
117   icon_ = status_tray_->CreateStatusIcon(
118       StatusTray::OTHER_ICON, icon_image, tool_tip);
119   if (icon_)
120     icon_->AddObserver(this);
121 }
122 
SystemIndicatorManager(Profile * profile,StatusTray * status_tray)123 SystemIndicatorManager::SystemIndicatorManager(Profile* profile,
124                                                StatusTray* status_tray)
125     : profile_(profile),
126       status_tray_(status_tray),
127       extension_registry_observer_(this) {
128   extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
129 
130   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
131                  content::Source<Profile>(profile_->GetOriginalProfile()));
132 }
133 
~SystemIndicatorManager()134 SystemIndicatorManager::~SystemIndicatorManager() {
135   DCHECK(thread_checker_.CalledOnValidThread());
136 }
137 
Shutdown()138 void SystemIndicatorManager::Shutdown() {
139   DCHECK(thread_checker_.CalledOnValidThread());
140 }
141 
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionInfo::Reason reason)142 void SystemIndicatorManager::OnExtensionUnloaded(
143     content::BrowserContext* browser_context,
144     const Extension* extension,
145     UnloadedExtensionInfo::Reason reason) {
146   RemoveIndicator(extension->id());
147 }
148 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)149 void SystemIndicatorManager::Observe(
150     int type,
151     const content::NotificationSource& source,
152     const content::NotificationDetails& details) {
153   DCHECK(thread_checker_.CalledOnValidThread());
154   DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED);
155 
156   OnSystemIndicatorChanged(content::Details<ExtensionAction>(details).ptr());
157 }
158 
OnSystemIndicatorChanged(const ExtensionAction * extension_action)159 void SystemIndicatorManager::OnSystemIndicatorChanged(
160     const ExtensionAction* extension_action) {
161   DCHECK(thread_checker_.CalledOnValidThread());
162   std::string extension_id = extension_action->extension_id();
163   ExtensionService* service =
164       ExtensionSystem::Get(profile_)->extension_service();
165 
166   if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
167     const Extension* extension =
168         service->GetExtensionById(extension_id, false);
169     CreateOrUpdateIndicator(extension, extension_action);
170   } else {
171     RemoveIndicator(extension_id);
172   }
173 }
174 
SendClickEventToExtensionForTest(const std::string extension_id)175 bool SystemIndicatorManager::SendClickEventToExtensionForTest(
176     const std::string extension_id) {
177 
178     extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it =
179         system_indicators_.find(extension_id);
180 
181     if (it == system_indicators_.end())
182       return false;
183 
184     it->second->OnStatusIconClicked();
185     return true;
186 }
187 
CreateOrUpdateIndicator(const Extension * extension,const ExtensionAction * extension_action)188 void SystemIndicatorManager::CreateOrUpdateIndicator(
189     const Extension* extension,
190     const ExtensionAction* extension_action) {
191   DCHECK(thread_checker_.CalledOnValidThread());
192   SystemIndicatorMap::iterator it = system_indicators_.find(extension->id());
193   if (it != system_indicators_.end()) {
194     it->second->OnIconUpdated();
195     return;
196   }
197 
198   ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create(
199       extension, extension_action, profile_, status_tray_);
200   if (extension_icon)
201     system_indicators_[extension->id()] = make_linked_ptr(extension_icon);
202 }
203 
RemoveIndicator(const std::string & extension_id)204 void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) {
205   DCHECK(thread_checker_.CalledOnValidThread());
206   system_indicators_.erase(extension_id);
207 }
208 
209 }  // namespace extensions
210