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/extensions/extension_action.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/status_icons/status_icon.h"
12 #include "chrome/browser/status_icons/status_icon_observer.h"
13 #include "chrome/browser/status_icons/status_tray.h"
14 #include "chrome/common/extensions/api/system_indicator.h"
15 #include "content/public/browser/web_contents.h"
16 #include "extensions/browser/event_router.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/common/extension.h"
19 #include "ui/gfx/image/image.h"
21 namespace extensions
{
23 namespace system_indicator
= api::system_indicator
;
25 // Observes clicks on a given status icon and forwards the event to the
26 // appropriate extension. Handles icon updates, and responsible for creating
27 // and removing the icon from the notification area during construction and
29 class ExtensionIndicatorIcon
: public StatusIconObserver
,
30 public ExtensionActionIconFactory::Observer
{
32 static ExtensionIndicatorIcon
* Create(const Extension
* extension
,
33 ExtensionAction
* action
,
35 StatusTray
* status_tray
);
36 ~ExtensionIndicatorIcon() override
;
38 // StatusIconObserver implementation.
39 void OnStatusIconClicked() override
;
41 // ExtensionActionIconFactory::Observer implementation.
42 void OnIconUpdated() override
;
45 ExtensionIndicatorIcon(const Extension
* extension
,
46 ExtensionAction
* action
,
48 StatusTray
* status_tray
);
50 const extensions::Extension
* extension_
;
51 StatusTray
* status_tray_
;
54 ExtensionActionIconFactory icon_factory_
;
57 ExtensionIndicatorIcon
* ExtensionIndicatorIcon::Create(
58 const Extension
* extension
,
59 ExtensionAction
* action
,
61 StatusTray
* status_tray
) {
62 scoped_ptr
<ExtensionIndicatorIcon
> extension_icon(
63 new ExtensionIndicatorIcon(extension
, action
, profile
, status_tray
));
65 // Check if a status icon was successfully created.
66 if (extension_icon
->icon_
)
67 return extension_icon
.release();
69 // We could not create a status icon.
73 ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
75 icon_
->RemoveObserver(this);
76 status_tray_
->RemoveStatusIcon(icon_
);
80 void ExtensionIndicatorIcon::OnStatusIconClicked() {
81 scoped_ptr
<base::ListValue
> params(
82 api::system_indicator::OnClicked::Create());
84 EventRouter
* event_router
= EventRouter::Get(profile_
);
85 scoped_ptr
<Event
> event(new Event(events::SYSTEM_INDICATOR_ON_CLICKED
,
86 system_indicator::OnClicked::kEventName
,
87 params
.Pass(), profile_
));
88 event_router
->DispatchEventToExtension(
89 extension_
->id(), event
.Pass());
92 void ExtensionIndicatorIcon::OnIconUpdated() {
94 icon_factory_
.GetIcon(ExtensionAction::kDefaultTabId
).AsImageSkia());
97 ExtensionIndicatorIcon::ExtensionIndicatorIcon(const Extension
* extension
,
98 ExtensionAction
* action
,
100 StatusTray
* status_tray
)
101 : extension_(extension
),
102 status_tray_(status_tray
),
105 icon_factory_(profile
, extension
, action
, this) {
106 // Get the icon image and tool tip for the status icon. The extension name is
107 // used as the tool tip.
108 gfx::ImageSkia icon_image
=
109 icon_factory_
.GetIcon(ExtensionAction::kDefaultTabId
).AsImageSkia();
110 base::string16 tool_tip
= base::UTF8ToUTF16(extension_
->name());
112 icon_
= status_tray_
->CreateStatusIcon(
113 StatusTray::OTHER_ICON
, icon_image
, tool_tip
);
115 icon_
->AddObserver(this);
118 SystemIndicatorManager::SystemIndicatorManager(Profile
* profile
,
119 StatusTray
* status_tray
)
121 status_tray_(status_tray
),
122 extension_action_observer_(this),
123 extension_registry_observer_(this) {
124 extension_registry_observer_
.Add(ExtensionRegistry::Get(profile_
));
125 extension_action_observer_
.Add(ExtensionActionAPI::Get(profile_
));
128 SystemIndicatorManager::~SystemIndicatorManager() {
129 DCHECK(thread_checker_
.CalledOnValidThread());
132 void SystemIndicatorManager::Shutdown() {
133 DCHECK(thread_checker_
.CalledOnValidThread());
136 void SystemIndicatorManager::OnExtensionUnloaded(
137 content::BrowserContext
* browser_context
,
138 const Extension
* extension
,
139 UnloadedExtensionInfo::Reason reason
) {
140 RemoveIndicator(extension
->id());
143 void SystemIndicatorManager::OnExtensionActionUpdated(
144 ExtensionAction
* extension_action
,
145 content::WebContents
* web_contents
,
146 content::BrowserContext
* browser_context
) {
147 DCHECK(thread_checker_
.CalledOnValidThread());
148 if (profile_
->GetOriginalProfile() != browser_context
||
149 extension_action
->action_type() != ActionInfo::TYPE_SYSTEM_INDICATOR
)
152 std::string extension_id
= extension_action
->extension_id();
153 if (extension_action
->GetIsVisible(ExtensionAction::kDefaultTabId
)) {
154 CreateOrUpdateIndicator(
155 ExtensionRegistry::Get(profile_
)->enabled_extensions().GetByID(
159 RemoveIndicator(extension_id
);
163 bool SystemIndicatorManager::SendClickEventToExtensionForTest(
164 const std::string extension_id
) {
166 extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it
=
167 system_indicators_
.find(extension_id
);
169 if (it
== system_indicators_
.end())
172 it
->second
->OnStatusIconClicked();
176 void SystemIndicatorManager::CreateOrUpdateIndicator(
177 const Extension
* extension
,
178 ExtensionAction
* extension_action
) {
179 DCHECK(thread_checker_
.CalledOnValidThread());
180 SystemIndicatorMap::iterator it
= system_indicators_
.find(extension
->id());
181 if (it
!= system_indicators_
.end()) {
182 it
->second
->OnIconUpdated();
186 ExtensionIndicatorIcon
* extension_icon
= ExtensionIndicatorIcon::Create(
187 extension
, extension_action
, profile_
, status_tray_
);
189 system_indicators_
[extension
->id()] = make_linked_ptr(extension_icon
);
192 void SystemIndicatorManager::RemoveIndicator(const std::string
& extension_id
) {
193 DCHECK(thread_checker_
.CalledOnValidThread());
194 system_indicators_
.erase(extension_id
);
197 } // namespace extensions