blob: 4c3256005edcd961577b1a84cd076b439188d8ed [file] [log] [blame]
[email protected]0f34d9082012-10-08 19:16:441// 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/extension_action_manager.h"
6
[email protected]f0eb58a2012-12-17 22:10:497#include "chrome/browser/extensions/api/system_indicator/system_indicator_manager.h"
8#include "chrome/browser/extensions/api/system_indicator/system_indicator_manager_factory.h"
[email protected]8ddcc922012-10-13 05:13:039#include "chrome/browser/extensions/extension_action.h"
[email protected]0f34d9082012-10-08 19:16:4410#include "chrome/browser/extensions/extension_system.h"
[email protected]018bf652013-05-03 23:18:3411#include "chrome/browser/profiles/incognito_helpers.h"
[email protected]0f34d9082012-10-08 19:16:4412#include "chrome/browser/profiles/profile.h"
13#include "chrome/common/chrome_notification_types.h"
[email protected]23b3c0a2013-01-16 23:36:3614#include "chrome/common/extensions/api/extension_action/action_info.h"
[email protected]f9655482013-02-13 09:22:5115#include "chrome/common/extensions/api/extension_action/page_action_handler.h"
16#include "chrome/common/extensions/api/extension_action/script_badge_handler.h"
[email protected]0f34d9082012-10-08 19:16:4417#include "chrome/common/extensions/extension.h"
[email protected]544471a2012-10-13 05:27:0918#include "chrome/common/extensions/feature_switch.h"
[email protected]0dd6f2032013-05-20 23:33:4019#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
20#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
[email protected]0f34d9082012-10-08 19:16:4421#include "content/public/browser/notification_service.h"
22#include "content/public/browser/notification_source.h"
23
24namespace extensions {
25
[email protected]61e3cbe2012-10-14 22:06:5026namespace {
27
[email protected]f1484c52013-05-22 23:25:4428// BrowserContextKeyedServiceFactory for ExtensionActionManager.
29class ExtensionActionManagerFactory : public BrowserContextKeyedServiceFactory {
[email protected]61e3cbe2012-10-14 22:06:5030 public:
[email protected]f1484c52013-05-22 23:25:4431 // BrowserContextKeyedServiceFactory implementation:
[email protected]61e3cbe2012-10-14 22:06:5032 static ExtensionActionManager* GetForProfile(Profile* profile) {
33 return static_cast<ExtensionActionManager*>(
[email protected]f1484c52013-05-22 23:25:4434 GetInstance()->GetServiceForBrowserContext(profile, true));
[email protected]61e3cbe2012-10-14 22:06:5035 }
36
37 static ExtensionActionManagerFactory* GetInstance();
38
39 private:
40 friend struct DefaultSingletonTraits<ExtensionActionManagerFactory>;
41
42 ExtensionActionManagerFactory()
[email protected]f1484c52013-05-22 23:25:4443 : BrowserContextKeyedServiceFactory(
44 "ExtensionActionManager",
45 BrowserContextDependencyManager::GetInstance()) {
[email protected]61e3cbe2012-10-14 22:06:5046 }
47
[email protected]f1484c52013-05-22 23:25:4448 virtual BrowserContextKeyedService* BuildServiceInstanceFor(
[email protected]c7fa4362013-04-26 18:09:0249 content::BrowserContext* profile) const OVERRIDE {
50 return new ExtensionActionManager(static_cast<Profile*>(profile));
[email protected]61e3cbe2012-10-14 22:06:5051 }
52
[email protected]018bf652013-05-03 23:18:3453 virtual content::BrowserContext* GetBrowserContextToUse(
54 content::BrowserContext* context) const OVERRIDE {
55 return chrome::GetBrowserContextRedirectedInIncognito(context);
[email protected]61e3cbe2012-10-14 22:06:5056 }
57};
58
59ExtensionActionManagerFactory*
60ExtensionActionManagerFactory::GetInstance() {
61 return Singleton<ExtensionActionManagerFactory>::get();
62}
63
64} // namespace
65
[email protected]f0eb58a2012-12-17 22:10:4966ExtensionActionManager::ExtensionActionManager(Profile* profile)
67 : profile_(profile) {
[email protected]0f34d9082012-10-08 19:16:4468 CHECK_EQ(profile, profile->GetOriginalProfile())
69 << "Don't instantiate this with an incognito profile.";
[email protected]0f34d9082012-10-08 19:16:4470 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
71 content::Source<Profile>(profile));
72}
73
74ExtensionActionManager::~ExtensionActionManager() {
75 // Don't assert that the ExtensionAction maps are empty because Extensions are
76 // sometimes (only in tests?) not unloaded before the Profile is destroyed.
77}
78
[email protected]5ed5ec52012-10-12 21:28:3079ExtensionActionManager* ExtensionActionManager::Get(Profile* profile) {
[email protected]61e3cbe2012-10-14 22:06:5080 return ExtensionActionManagerFactory::GetForProfile(profile);
[email protected]0f34d9082012-10-08 19:16:4481}
82
83void ExtensionActionManager::Observe(
84 int type,
85 const content::NotificationSource& source,
86 const content::NotificationDetails& details) {
87 switch (type) {
[email protected]0f34d9082012-10-08 19:16:4488 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
89 const Extension* extension =
90 content::Details<UnloadedExtensionInfo>(details)->extension;
[email protected]5ed5ec52012-10-12 21:28:3091 page_actions_.erase(extension->id());
92 browser_actions_.erase(extension->id());
93 script_badges_.erase(extension->id());
[email protected]f0eb58a2012-12-17 22:10:4994 system_indicators_.erase(extension->id());
[email protected]0f34d9082012-10-08 19:16:4495 break;
96 }
97 }
98}
99
[email protected]5ed5ec52012-10-12 21:28:30100namespace {
101
[email protected]61e3cbe2012-10-14 22:06:50102// Returns map[extension_id] if that entry exists. Otherwise, if
103// action_info!=NULL, creates an ExtensionAction from it, fills in the map, and
104// returns that. Otherwise (action_info==NULL), returns NULL.
105ExtensionAction* GetOrCreateOrNull(
106 std::map<std::string, linked_ptr<ExtensionAction> >* map,
107 const std::string& extension_id,
[email protected]23b3c0a2013-01-16 23:36:36108 ActionInfo::Type action_type,
109 const ActionInfo* action_info) {
[email protected]61e3cbe2012-10-14 22:06:50110 std::map<std::string, linked_ptr<ExtensionAction> >::const_iterator it =
111 map->find(extension_id);
112 if (it != map->end())
113 return it->second.get();
114 if (!action_info)
115 return NULL;
116 linked_ptr<ExtensionAction> action(new ExtensionAction(
117 extension_id, action_type, *action_info));
118 (*map)[extension_id] = action;
119 return action.get();
[email protected]5ed5ec52012-10-12 21:28:30120}
121
[email protected]ad12b6b2012-11-28 23:21:15122} // namespace
[email protected]5ed5ec52012-10-12 21:28:30123
124ExtensionAction* ExtensionActionManager::GetPageAction(
125 const extensions::Extension& extension) const {
[email protected]61e3cbe2012-10-14 22:06:50126 // The action box changes the meaning of the page action area, so we
127 // need to convert page actions into browser actions.
128 if (FeatureSwitch::script_badges()->IsEnabled())
129 return NULL;
130 return GetOrCreateOrNull(&page_actions_, extension.id(),
[email protected]23b3c0a2013-01-16 23:36:36131 ActionInfo::TYPE_PAGE,
[email protected]f9655482013-02-13 09:22:51132 ActionInfo::GetPageActionInfo(&extension));
[email protected]5ed5ec52012-10-12 21:28:30133}
134
135ExtensionAction* ExtensionActionManager::GetBrowserAction(
136 const extensions::Extension& extension) const {
[email protected]972b02f2013-01-28 20:38:14137 const ActionInfo* action_info = ActionInfo::GetBrowserActionInfo(&extension);
[email protected]23b3c0a2013-01-16 23:36:36138 ActionInfo::Type action_type = ActionInfo::TYPE_BROWSER;
[email protected]61e3cbe2012-10-14 22:06:50139 if (FeatureSwitch::script_badges()->IsEnabled() &&
[email protected]f9655482013-02-13 09:22:51140 ActionInfo::GetPageActionInfo(&extension)) {
[email protected]61e3cbe2012-10-14 22:06:50141 // The action box changes the meaning of the page action area, so we
142 // need to convert page actions into browser actions.
[email protected]f9655482013-02-13 09:22:51143 action_info = ActionInfo::GetPageActionInfo(&extension);
[email protected]23b3c0a2013-01-16 23:36:36144 action_type = ActionInfo::TYPE_PAGE;
[email protected]61e3cbe2012-10-14 22:06:50145 }
146 return GetOrCreateOrNull(&browser_actions_, extension.id(),
147 action_type, action_info);
[email protected]5ed5ec52012-10-12 21:28:30148}
149
[email protected]ad12b6b2012-11-28 23:21:15150ExtensionAction* ExtensionActionManager::GetSystemIndicator(
151 const extensions::Extension& extension) const {
[email protected]f0eb58a2012-12-17 22:10:49152 // If it does not already exist, create the SystemIndicatorManager for the
153 // given profile. This could return NULL if the system indicator area is
154 // unavailable on the current system. If so, return NULL to signal that
155 // the system indicator area is unusable.
156 if (!extensions::SystemIndicatorManagerFactory::GetForProfile(profile_))
157 return NULL;
158
[email protected]ad12b6b2012-11-28 23:21:15159 return GetOrCreateOrNull(&system_indicators_, extension.id(),
[email protected]23b3c0a2013-01-16 23:36:36160 ActionInfo::TYPE_SYSTEM_INDICATOR,
[email protected]4e786932013-03-25 19:21:04161 ActionInfo::GetSystemIndicatorInfo(&extension));
[email protected]ad12b6b2012-11-28 23:21:15162}
163
[email protected]5ed5ec52012-10-12 21:28:30164ExtensionAction* ExtensionActionManager::GetScriptBadge(
165 const extensions::Extension& extension) const {
[email protected]61e3cbe2012-10-14 22:06:50166 return GetOrCreateOrNull(&script_badges_, extension.id(),
[email protected]23b3c0a2013-01-16 23:36:36167 ActionInfo::TYPE_SCRIPT_BADGE,
168 ActionInfo::GetScriptBadgeInfo(&extension));
[email protected]5ed5ec52012-10-12 21:28:30169}
170
[email protected]ad12b6b2012-11-28 23:21:15171} // namespace extensions