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/basictypes.h"
13 #include "base/memory/linked_ptr.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/observer_list.h"
18 #include "chrome/common/extensions/api/extension_action/action_info.h"
19 #include "chrome/common/extensions/extension_icon_set.h"
20 #include "third_party/skia/include/core/SkColor.h"
21 // TODO(robertphillips): change this to "class SkBaseDevice;"
22 #include "third_party/skia/include/core/SkDevice.h"
23 #include "ui/gfx/animation/linear_animation.h"
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 // Use this ID to indicate the default state for properties that take a tab_id
43 static const int kDefaultTabId
;
45 ExtensionAction(const std::string
& extension_id
,
46 extensions::ActionInfo::Type action_type
,
47 const extensions::ActionInfo
& manifest_data
);
50 // Gets a copy of this, ownership passed to caller.
51 // It doesn't make sense to copy of an ExtensionAction except in tests.
52 scoped_ptr
<ExtensionAction
> CopyForTest() const;
54 // Given the extension action type, returns the size the extension action icon
55 // should have. The icon should be square, so only one dimension is
57 static int GetIconSizeForType(extensions::ActionInfo::Type type
);
60 const std::string
& extension_id() const { return extension_id_
; }
62 // What kind of action is this?
63 extensions::ActionInfo::Type
action_type() const {
67 // action id -- only used with legacy page actions API
68 std::string
id() const { return id_
; }
69 void set_id(const std::string
& id
) { id_
= id
; }
71 bool has_changed() const { return has_changed_
; }
72 void set_has_changed(bool value
) { has_changed_
= value
; }
74 // Set the url which the popup will load when the user clicks this action's
75 // icon. Setting an empty URL will disable the popup for a given tab.
76 void SetPopupUrl(int tab_id
, const GURL
& url
);
78 // Use HasPopup() to see if a popup should be displayed.
79 bool HasPopup(int tab_id
) const;
81 // Get the URL to display in a popup.
82 GURL
GetPopupUrl(int tab_id
) const;
84 // Set this action's title on a specific tab.
85 void SetTitle(int tab_id
, const std::string
& title
) {
86 SetValue(&title_
, tab_id
, title
);
89 // If tab |tab_id| has a set title, return it. Otherwise, return
91 std::string
GetTitle(int tab_id
) const { return GetValue(&title_
, tab_id
); }
93 // Icons are a bit different because the default value can be set to either a
94 // bitmap or a path. However, conceptually, there is only one default icon.
95 // Setting the default icon using a path clears the bitmap and vice-versa.
96 // To retrieve the icon for the extension action, use
97 // ExtensionActionIconFactory.
99 // Set this action's icon bitmap on a specific tab.
100 void SetIcon(int tab_id
, const gfx::Image
& image
);
102 // Gets the icon that has been set using |SetIcon| for the tab.
103 gfx::ImageSkia
GetExplicitlySetIcon(int tab_id
) const;
105 // Non-tab-specific icon path. This is used to support the default_icon key of
106 // page and browser actions.
107 void set_default_icon(scoped_ptr
<ExtensionIconSet
> icon_set
) {
108 default_icon_
= icon_set
.Pass();
111 const ExtensionIconSet
* default_icon() const {
112 return default_icon_
.get();
115 // Set this action's badge text on a specific tab.
116 void SetBadgeText(int tab_id
, const std::string
& text
) {
117 SetValue(&badge_text_
, tab_id
, text
);
119 // Get the badge text for a tab, or the default if no badge text was set.
120 std::string
GetBadgeText(int tab_id
) const {
121 return GetValue(&badge_text_
, tab_id
);
124 // Set this action's badge text color on a specific tab.
125 void SetBadgeTextColor(int tab_id
, SkColor text_color
) {
126 SetValue(&badge_text_color_
, tab_id
, text_color
);
128 // Get the text color for a tab, or the default color if no text color
130 SkColor
GetBadgeTextColor(int tab_id
) const {
131 return GetValue(&badge_text_color_
, tab_id
);
134 // Set this action's badge background color on a specific tab.
135 void SetBadgeBackgroundColor(int tab_id
, SkColor color
) {
136 SetValue(&badge_background_color_
, tab_id
, color
);
138 // Get the badge background color for a tab, or the default if no color
140 SkColor
GetBadgeBackgroundColor(int tab_id
) const {
141 return GetValue(&badge_background_color_
, tab_id
);
144 // Set this action's badge visibility on a specific tab. Returns true if
145 // the visibility has changed.
146 bool SetIsVisible(int tab_id
, bool value
);
147 // The declarative appearance overrides a default appearance but is overridden
148 // by an appearance set directly on the tab.
149 void DeclarativeShow(int tab_id
);
150 void UndoDeclarativeShow(int tab_id
);
152 // Get the badge visibility for a tab, or the default badge visibility
154 // Gets the visibility of |tab_id|. Returns the first of: a specific
155 // visibility set on the tab; a declarative visibility set on the tab; the
156 // default visibility set for all tabs; or |false|. Don't return this
157 // result to an extension's background page because the declarative state can
158 // leak information about hosts the extension doesn't have permission to
160 bool GetIsVisible(int tab_id
) const {
161 if (const bool* tab_is_visible
= FindOrNull(&is_visible_
, tab_id
))
162 return *tab_is_visible
;
164 if (ContainsKey(declarative_show_count_
, tab_id
))
167 if (const bool* default_is_visible
=
168 FindOrNull(&is_visible_
, kDefaultTabId
))
169 return *default_is_visible
;
174 // Remove all tab-specific state.
175 void ClearAllValuesForTab(int tab_id
);
177 // If the specified tab has a badge, paint it into the provided bounds.
178 void PaintBadge(gfx::Canvas
* canvas
, const gfx::Rect
& bounds
, int tab_id
);
180 // Returns icon image with badge for specified tab.
181 gfx::ImageSkia
GetIconWithBadge(const gfx::ImageSkia
& icon
,
183 const gfx::Size
& spacing
) const;
186 // Returns width of the current icon for tab_id.
187 // TODO(tbarzic): The icon selection is done in ExtensionActionIconFactory.
188 // We should probably move this there too.
189 int GetIconWidth(int tab_id
) const;
193 static T
CreateEmpty() {
199 void SetValue(std::map
<int, T
>* map
, int tab_id
, const T
& val
) {
200 (*map
)[tab_id
] = val
;
204 static const typename
Map::mapped_type
* FindOrNull(
206 const typename
Map::key_type
& key
) {
207 typename
Map::const_iterator iter
= map
->find(key
);
208 if (iter
== map
->end())
210 return &iter
->second
;
214 T
GetValue(const std::map
<int, T
>* map
, int tab_id
) const {
215 if (const T
* tab_value
= FindOrNull(map
, tab_id
)) {
217 } else if (const T
* default_value
= FindOrNull(map
, kDefaultTabId
)) {
218 return *default_value
;
220 return ValueTraits
<T
>::CreateEmpty();
224 // The id for the extension this action belongs to (as defined in the
225 // extension manifest).
226 const std::string extension_id_
;
228 const extensions::ActionInfo::Type action_type_
;
230 // Each of these data items can have both a global state (stored with the key
231 // kDefaultTabId), or tab-specific state (stored with the tab_id as the key).
232 std::map
<int, GURL
> popup_url_
;
233 std::map
<int, std::string
> title_
;
234 std::map
<int, gfx::ImageSkia
> icon_
;
235 std::map
<int, std::string
> badge_text_
;
236 std::map
<int, SkColor
> badge_background_color_
;
237 std::map
<int, SkColor
> badge_text_color_
;
238 std::map
<int, bool> is_visible_
;
240 // Declarative state exists for two reasons: First, we need to hide it from
241 // the extension's background/event page to avoid leaking data from hosts the
242 // extension doesn't have permission to access. Second, the action's state
243 // gets both reset and given its declarative values in response to a
244 // WebContentsObserver::DidNavigateMainFrame event, and there's no way to set
245 // those up to be called in the right order.
247 // Maps tab_id to the number of active (applied-but-not-reverted)
248 // declarativeContent.ShowPageAction actions.
249 std::map
<int, int> declarative_show_count_
;
251 // ExtensionIconSet containing paths to bitmaps from which default icon's
252 // image representations will be selected.
253 scoped_ptr
<const ExtensionIconSet
> default_icon_
;
255 // The id for the ExtensionAction, for example: "RssPageAction". This is
256 // needed for compat with an older version of the page actions API.
259 // True if the ExtensionAction's settings have changed from what was
260 // specified in the manifest.
263 DISALLOW_COPY_AND_ASSIGN(ExtensionAction
);
267 struct ExtensionAction::ValueTraits
<int> {
268 static int CreateEmpty() {
273 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_