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.
5 #include "chrome/browser/extensions/api/system_indicator/system_indicator_manager.h"
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_system.h"
21 #include "extensions/common/extension.h"
22 #include "ui/gfx/image/image.h"
24 namespace extensions {
26 namespace system_indicator = api::system_indicator;
28 // Observes clicks on a given status icon and forwards the event to the
29 // appropriate extension. Handles icon updates, and responsible for creating
30 // and removing the icon from the notification area during construction and
32 class ExtensionIndicatorIcon : public StatusIconObserver,
33 public ExtensionActionIconFactory::Observer {
35 static ExtensionIndicatorIcon* Create(const Extension* extension,
36 const ExtensionAction* action,
38 StatusTray* status_tray);
39 virtual ~ExtensionIndicatorIcon();
41 // StatusIconObserver implementation.
42 virtual void OnStatusIconClicked() OVERRIDE;
44 // ExtensionActionIconFactory::Observer implementation.
45 virtual void OnIconUpdated() OVERRIDE;
48 ExtensionIndicatorIcon(const Extension* extension,
49 const ExtensionAction* action,
51 StatusTray* status_tray);
53 const extensions::Extension* extension_;
54 StatusTray* status_tray_;
57 ExtensionActionIconFactory icon_factory_;
60 ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create(
61 const Extension* extension,
62 const ExtensionAction* action,
64 StatusTray* status_tray) {
65 scoped_ptr<ExtensionIndicatorIcon> extension_icon(
66 new ExtensionIndicatorIcon(extension, action, profile, status_tray));
68 // Check if a status icon was successfully created.
69 if (extension_icon->icon_)
70 return extension_icon.release();
72 // We could not create a status icon.
76 ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
78 icon_->RemoveObserver(this);
79 status_tray_->RemoveStatusIcon(icon_);
83 void ExtensionIndicatorIcon::OnStatusIconClicked() {
84 scoped_ptr<base::ListValue> params(
85 api::system_indicator::OnClicked::Create());
87 EventRouter* event_router =
88 ExtensionSystem::Get(profile_)->event_router();
89 scoped_ptr<Event> event(new Event(
90 system_indicator::OnClicked::kEventName,
93 event_router->DispatchEventToExtension(
94 extension_->id(), event.Pass());
97 void ExtensionIndicatorIcon::OnIconUpdated() {
99 icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia());
102 ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension* extension,
103 const ExtensionAction* action,
105 StatusTray* status_tray)
106 : extension_(extension),
107 status_tray_(status_tray),
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());
117 icon_ = status_tray_->CreateStatusIcon(
118 StatusTray::OTHER_ICON, icon_image, tool_tip);
120 icon_->AddObserver(this);
123 SystemIndicatorManager::SystemIndicatorManager(Profile* profile,
124 StatusTray* status_tray)
125 : profile_(profile), status_tray_(status_tray) {
126 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
127 content::Source<Profile>(profile_->GetOriginalProfile()));
128 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED,
129 content::Source<Profile>(profile_->GetOriginalProfile()));
132 SystemIndicatorManager::~SystemIndicatorManager() {
133 DCHECK(thread_checker_.CalledOnValidThread());
136 void SystemIndicatorManager::Shutdown() {
137 DCHECK(thread_checker_.CalledOnValidThread());
140 void SystemIndicatorManager::Observe(
142 const content::NotificationSource& source,
143 const content::NotificationDetails& details) {
144 DCHECK(thread_checker_.CalledOnValidThread());
147 case chrome::NOTIFICATION_EXTENSION_UNLOADED:
149 content::Details<UnloadedExtensionInfo>(details)->extension->id());
151 case chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED:
152 OnSystemIndicatorChanged(
153 content::Details<ExtensionAction>(details).ptr());
161 void SystemIndicatorManager::OnSystemIndicatorChanged(
162 const ExtensionAction* extension_action) {
163 DCHECK(thread_checker_.CalledOnValidThread());
164 std::string extension_id = extension_action->extension_id();
165 ExtensionService* service =
166 ExtensionSystem::Get(profile_)->extension_service();
168 if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
169 const Extension* extension =
170 service->GetExtensionById(extension_id, false);
171 CreateOrUpdateIndicator(extension, extension_action);
173 RemoveIndicator(extension_id);
177 bool SystemIndicatorManager::SendClickEventToExtensionForTest(
178 const std::string extension_id) {
180 extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it =
181 system_indicators_.find(extension_id);
183 if (it == system_indicators_.end())
186 it->second->OnStatusIconClicked();
190 void SystemIndicatorManager::CreateOrUpdateIndicator(
191 const Extension* extension,
192 const ExtensionAction* extension_action) {
193 DCHECK(thread_checker_.CalledOnValidThread());
194 SystemIndicatorMap::iterator it = system_indicators_.find(extension->id());
195 if (it != system_indicators_.end()) {
196 it->second->OnIconUpdated();
200 ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create(
201 extension, extension_action, profile_, status_tray_);
203 system_indicators_[extension->id()] = make_linked_ptr(extension_icon);
206 void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) {
207 DCHECK(thread_checker_.CalledOnValidThread());
208 system_indicators_.erase(extension_id);
211 } // namespace extensions