Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / system_indicator / system_indicator_manager.cc
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_system.h"
21 #include "extensions/common/extension.h"
22 #include "ui/gfx/image/image.h"
23
24 namespace extensions {
25
26 namespace system_indicator = api::system_indicator;
27
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
31 // destruction.
32 class ExtensionIndicatorIcon : public StatusIconObserver,
33                                public ExtensionActionIconFactory::Observer {
34  public:
35   static ExtensionIndicatorIcon* Create(const Extension* extension,
36                                         const ExtensionAction* action,
37                                         Profile* profile,
38                                         StatusTray* status_tray);
39   virtual ~ExtensionIndicatorIcon();
40
41   // StatusIconObserver implementation.
42   virtual void OnStatusIconClicked() OVERRIDE;
43
44   // ExtensionActionIconFactory::Observer implementation.
45   virtual void OnIconUpdated() OVERRIDE;
46
47  private:
48   ExtensionIndicatorIcon(const Extension* extension,
49                          const ExtensionAction* action,
50                          Profile* profile,
51                          StatusTray* status_tray);
52
53   const extensions::Extension* extension_;
54   StatusTray* status_tray_;
55   StatusIcon* icon_;
56   Profile* profile_;
57   ExtensionActionIconFactory icon_factory_;
58 };
59
60 ExtensionIndicatorIcon* ExtensionIndicatorIcon::Create(
61     const Extension* extension,
62     const ExtensionAction* action,
63     Profile* profile,
64     StatusTray* status_tray) {
65   scoped_ptr<ExtensionIndicatorIcon> extension_icon(
66       new ExtensionIndicatorIcon(extension, action, profile, status_tray));
67
68   // Check if a status icon was successfully created.
69   if (extension_icon->icon_)
70     return extension_icon.release();
71
72   // We could not create a status icon.
73   return NULL;
74 }
75
76 ExtensionIndicatorIcon::~ExtensionIndicatorIcon() {
77   if (icon_) {
78     icon_->RemoveObserver(this);
79     status_tray_->RemoveStatusIcon(icon_);
80   }
81 }
82
83 void ExtensionIndicatorIcon::OnStatusIconClicked() {
84   scoped_ptr<base::ListValue> params(
85       api::system_indicator::OnClicked::Create());
86
87   EventRouter* event_router =
88       ExtensionSystem::Get(profile_)->event_router();
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
97 void ExtensionIndicatorIcon::OnIconUpdated() {
98   icon_->SetImage(
99       icon_factory_.GetIcon(ExtensionAction::kDefaultTabId).AsImageSkia());
100 }
101
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
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()));
130 }
131
132 SystemIndicatorManager::~SystemIndicatorManager() {
133   DCHECK(thread_checker_.CalledOnValidThread());
134 }
135
136 void SystemIndicatorManager::Shutdown() {
137   DCHECK(thread_checker_.CalledOnValidThread());
138 }
139
140 void SystemIndicatorManager::Observe(
141     int type,
142     const content::NotificationSource& source,
143     const content::NotificationDetails& details) {
144   DCHECK(thread_checker_.CalledOnValidThread());
145
146   switch (type) {
147     case chrome::NOTIFICATION_EXTENSION_UNLOADED:
148       RemoveIndicator(
149           content::Details<UnloadedExtensionInfo>(details)->extension->id());
150       break;
151     case chrome::NOTIFICATION_EXTENSION_SYSTEM_INDICATOR_UPDATED:
152       OnSystemIndicatorChanged(
153           content::Details<ExtensionAction>(details).ptr());
154       break;
155     default:
156       NOTREACHED();
157       break;
158   }
159 }
160
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();
167
168   if (extension_action->GetIsVisible(ExtensionAction::kDefaultTabId)) {
169     const Extension* extension =
170         service->GetExtensionById(extension_id, false);
171     CreateOrUpdateIndicator(extension, extension_action);
172   } else {
173     RemoveIndicator(extension_id);
174   }
175 }
176
177 bool SystemIndicatorManager::SendClickEventToExtensionForTest(
178     const std::string extension_id) {
179
180     extensions::SystemIndicatorManager::SystemIndicatorMap::iterator it =
181         system_indicators_.find(extension_id);
182
183     if (it == system_indicators_.end())
184       return false;
185
186     it->second->OnStatusIconClicked();
187     return true;
188 }
189
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();
197     return;
198   }
199
200   ExtensionIndicatorIcon* extension_icon = ExtensionIndicatorIcon::Create(
201       extension, extension_action, profile_, status_tray_);
202   if (extension_icon)
203     system_indicators_[extension->id()] = make_linked_ptr(extension_icon);
204 }
205
206 void SystemIndicatorManager::RemoveIndicator(const std::string& extension_id) {
207   DCHECK(thread_checker_.CalledOnValidThread());
208   system_indicators_.erase(extension_id);
209 }
210
211 }  // namespace extensions