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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h"
14 #include "chrome/common/extensions/api/extension_action/action_info.h"
15 #include "third_party/skia/include/core/SkColor.h"
23 namespace extensions
{
36 // ExtensionAction encapsulates the state of a browser action or page action.
37 // Instances can have both global and per-tab state. If a property does not have
38 // a per-tab value, the global value is used instead.
39 class ExtensionAction
{
41 // The action that the UI should take after the ExtensionAction is clicked.
45 // We don't need a SHOW_CONTEXT_MENU because that's handled separately in
49 // Use this ID to indicate the default state for properties that take a tab_id
51 static const int kDefaultTabId
;
53 // Max size (both dimensions) for page actions.
54 static const int kPageActionIconMaxSize
;
56 ExtensionAction(const extensions::Extension
& extension
,
57 extensions::ActionInfo::Type action_type
,
58 const extensions::ActionInfo
& manifest_data
);
62 const std::string
& extension_id() const { return extension_id_
; }
64 // What kind of action is this?
65 extensions::ActionInfo::Type
action_type() const {
69 // action id -- only used with legacy page actions API
70 std::string
id() const { return id_
; }
71 void set_id(const std::string
& id
) { id_
= id
; }
73 // Set the url which the popup will load when the user clicks this action's
74 // icon. Setting an empty URL will disable the popup for a given tab.
75 void SetPopupUrl(int tab_id
, const GURL
& url
);
77 // Use HasPopup() to see if a popup should be displayed.
78 bool HasPopup(int tab_id
) const;
80 // Get the URL to display in a popup.
81 GURL
GetPopupUrl(int tab_id
) const;
83 // Set this action's title on a specific tab.
84 void SetTitle(int tab_id
, const std::string
& title
) {
85 SetValue(&title_
, tab_id
, title
);
88 // If tab |tab_id| has a set title, return it. Otherwise, return
90 std::string
GetTitle(int tab_id
) const { return GetValue(&title_
, tab_id
); }
92 // Icons are a bit different because the default value can be set to either a
93 // bitmap or a path. However, conceptually, there is only one default icon.
94 // Setting the default icon using a path clears the bitmap and vice-versa.
95 // To retrieve the icon for the extension action, use
96 // ExtensionActionIconFactory.
98 // Set this action's icon bitmap on a specific tab.
99 void SetIcon(int tab_id
, const gfx::Image
& image
);
101 // Tries to parse |*icon| from a dictionary {"19": imageData19, "38":
102 // imageData38}, returning false if a value is corrupt.
103 static bool ParseIconFromCanvasDictionary(const base::DictionaryValue
& dict
,
104 gfx::ImageSkia
* icon
);
106 // Gets the icon that has been set using |SetIcon| for the tab.
107 gfx::Image
GetExplicitlySetIcon(int tab_id
) const;
109 // Sets the icon for a tab, in a way that can't be read by the extension's
110 // javascript. Multiple icons can be set at the same time; some icon with the
111 // highest priority will be used.
112 void DeclarativeSetIcon(int tab_id
, int priority
, const gfx::Image
& icon
);
113 void UndoDeclarativeSetIcon(int tab_id
, int priority
, const gfx::Image
& icon
);
115 const ExtensionIconSet
* default_icon() const {
116 return default_icon_
.get();
119 // Set this action's badge text on a specific tab.
120 void SetBadgeText(int tab_id
, const std::string
& text
) {
121 SetValue(&badge_text_
, tab_id
, text
);
123 // Get the badge text for a tab, or the default if no badge text was set.
124 std::string
GetBadgeText(int tab_id
) const {
125 return GetValue(&badge_text_
, tab_id
);
128 // Set this action's badge text color on a specific tab.
129 void SetBadgeTextColor(int tab_id
, SkColor text_color
) {
130 SetValue(&badge_text_color_
, tab_id
, text_color
);
132 // Get the text color for a tab, or the default color if no text color
134 SkColor
GetBadgeTextColor(int tab_id
) const {
135 return GetValue(&badge_text_color_
, tab_id
);
138 // Set this action's badge background color on a specific tab.
139 void SetBadgeBackgroundColor(int tab_id
, SkColor color
) {
140 SetValue(&badge_background_color_
, tab_id
, color
);
142 // Get the badge background color for a tab, or the default if no color
144 SkColor
GetBadgeBackgroundColor(int tab_id
) const {
145 return GetValue(&badge_background_color_
, tab_id
);
148 // Set this action's badge visibility on a specific tab. Returns true if
149 // the visibility has changed.
150 bool SetIsVisible(int tab_id
, bool value
);
151 // The declarative appearance overrides a default appearance but is overridden
152 // by an appearance set directly on the tab.
153 void DeclarativeShow(int tab_id
);
154 void UndoDeclarativeShow(int tab_id
);
155 const gfx::Image
GetDeclarativeIcon(int tab_id
) const;
157 // Get the badge visibility for a tab, or the default badge visibility
159 // Gets the visibility of |tab_id|. Returns the first of: a specific
160 // visibility set on the tab; a declarative visibility set on the tab; the
161 // default visibility set for all tabs; or |false|. Don't return this
162 // result to an extension's background page because the declarative state can
163 // leak information about hosts the extension doesn't have permission to
165 bool GetIsVisible(int tab_id
) const {
166 if (const bool* tab_is_visible
= FindOrNull(&is_visible_
, tab_id
))
167 return *tab_is_visible
;
169 if (ContainsKey(declarative_show_count_
, tab_id
))
172 if (const bool* default_is_visible
=
173 FindOrNull(&is_visible_
, kDefaultTabId
))
174 return *default_is_visible
;
179 // Remove all tab-specific state.
180 void ClearAllValuesForTab(int tab_id
);
182 // Lazily loads and returns the default icon image, if one exists for the
184 extensions::IconImage
* LoadDefaultIconImage(
185 const extensions::Extension
& extension
,
186 content::BrowserContext
* browser_context
);
188 // Returns the image to use as the default icon for the action. Can only be
189 // called after LoadDefaultIconImage().
190 gfx::Image
GetDefaultIconImage() const;
192 // Determine whether or not the ExtensionAction has a value set for the given
193 // |tab_id| for each property.
194 bool HasPopupUrl(int tab_id
) const;
195 bool HasTitle(int tab_id
) const;
196 bool HasBadgeText(int tab_id
) const;
197 bool HasBadgeBackgroundColor(int tab_id
) const;
198 bool HasBadgeTextColor(int tab_id
) const;
199 bool HasIsVisible(int tab_id
) const;
200 bool HasIcon(int tab_id
) const;
202 void SetDefaultIconForTest(scoped_ptr
<ExtensionIconSet
> default_icon
);
205 // Populates the action from the |extension| and |manifest_data|, filling in
206 // any missing values (like title or icons) as possible.
207 void Populate(const extensions::Extension
& extension
,
208 const extensions::ActionInfo
& manifest_data
);
210 // Returns width of the current icon for tab_id.
211 // TODO(tbarzic): The icon selection is done in ExtensionActionIconFactory.
212 // We should probably move this there too.
213 int GetIconWidth(int tab_id
) const;
217 static T
CreateEmpty() {
223 void SetValue(std::map
<int, T
>* map
, int tab_id
, const T
& val
) {
224 (*map
)[tab_id
] = val
;
228 static const typename
Map::mapped_type
* FindOrNull(
230 const typename
Map::key_type
& key
) {
231 typename
Map::const_iterator iter
= map
->find(key
);
232 if (iter
== map
->end())
234 return &iter
->second
;
238 T
GetValue(const std::map
<int, T
>* map
, int tab_id
) const {
239 if (const T
* tab_value
= FindOrNull(map
, tab_id
)) {
241 } else if (const T
* default_value
= FindOrNull(map
, kDefaultTabId
)) {
242 return *default_value
;
244 return ValueTraits
<T
>::CreateEmpty();
248 // The id for the extension this action belongs to (as defined in the
249 // extension manifest).
250 const std::string extension_id_
;
252 // The name of the extension.
253 const std::string extension_name_
;
255 const extensions::ActionInfo::Type action_type_
;
257 // Each of these data items can have both a global state (stored with the key
258 // kDefaultTabId), or tab-specific state (stored with the tab_id as the key).
259 std::map
<int, GURL
> popup_url_
;
260 std::map
<int, std::string
> title_
;
261 std::map
<int, gfx::Image
> icon_
;
262 std::map
<int, std::string
> badge_text_
;
263 std::map
<int, SkColor
> badge_background_color_
;
264 std::map
<int, SkColor
> badge_text_color_
;
265 std::map
<int, bool> is_visible_
;
267 // Declarative state exists for two reasons: First, we need to hide it from
268 // the extension's background/event page to avoid leaking data from hosts the
269 // extension doesn't have permission to access. Second, the action's state
270 // gets both reset and given its declarative values in response to a
271 // WebContentsObserver::DidNavigateMainFrame event, and there's no way to set
272 // those up to be called in the right order.
274 // Maps tab_id to the number of active (applied-but-not-reverted)
275 // declarativeContent.ShowPageAction actions.
276 std::map
<int, int> declarative_show_count_
;
278 // declarative_icon_[tab_id][declarative_rule_priority] is a vector of icon
279 // images that are currently in effect
280 std::map
<int, std::map
<int, std::vector
<gfx::Image
> > > declarative_icon_
;
282 // ExtensionIconSet containing paths to bitmaps from which default icon's
283 // image representations will be selected.
284 scoped_ptr
<ExtensionIconSet
> default_icon_
;
286 // The default icon image, if |default_icon_| exists.
287 // Lazily initialized via LoadDefaultIconImage().
288 scoped_ptr
<extensions::IconImage
> default_icon_image_
;
290 // The id for the ExtensionAction, for example: "RssPageAction". This is
291 // needed for compat with an older version of the page actions API.
294 DISALLOW_COPY_AND_ASSIGN(ExtensionAction
);
298 struct ExtensionAction::ValueTraits
<int> {
299 static int CreateEmpty() {
304 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_