NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / extensions / extension_action.cc
blobf4f70471ac1cf073b5146f575f41e477a81a2946
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/extension_action.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "chrome/common/badge_util.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/icon_with_badge_image_source.h"
15 #include "grit/theme_resources.h"
16 #include "grit/ui_resources.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "third_party/skia/include/core/SkBitmapDevice.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkPaint.h"
21 #include "third_party/skia/include/effects/SkGradientShader.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/gfx/animation/animation_delegate.h"
24 #include "ui/gfx/canvas.h"
25 #include "ui/gfx/color_utils.h"
26 #include "ui/gfx/image/image.h"
27 #include "ui/gfx/image/image_skia.h"
28 #include "ui/gfx/image/image_skia_source.h"
29 #include "ui/gfx/rect.h"
30 #include "ui/gfx/size.h"
31 #include "ui/gfx/skbitmap_operations.h"
32 #include "url/gurl.h"
34 namespace {
36 class GetAttentionImageSource : public gfx::ImageSkiaSource {
37 public:
38 explicit GetAttentionImageSource(const gfx::ImageSkia& icon)
39 : icon_(icon) {}
41 // gfx::ImageSkiaSource overrides:
42 virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
43 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale);
44 color_utils::HSL shift = {-1, 0, 0.5};
45 return gfx::ImageSkiaRep(
46 SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift),
47 icon_rep.scale());
50 private:
51 const gfx::ImageSkia icon_;
54 } // namespace
56 const int ExtensionAction::kDefaultTabId = -1;
58 ExtensionAction::ExtensionAction(
59 const std::string& extension_id,
60 extensions::ActionInfo::Type action_type,
61 const extensions::ActionInfo& manifest_data)
62 : extension_id_(extension_id),
63 action_type_(action_type),
64 has_changed_(false) {
65 // Page/script actions are hidden/disabled by default, and browser actions are
66 // visible/enabled by default.
67 SetIsVisible(kDefaultTabId,
68 action_type == extensions::ActionInfo::TYPE_BROWSER);
69 SetTitle(kDefaultTabId, manifest_data.default_title);
70 SetPopupUrl(kDefaultTabId, manifest_data.default_popup_url);
71 if (!manifest_data.default_icon.empty()) {
72 set_default_icon(make_scoped_ptr(new ExtensionIconSet(
73 manifest_data.default_icon)));
75 set_id(manifest_data.id);
78 ExtensionAction::~ExtensionAction() {
81 scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const {
82 scoped_ptr<ExtensionAction> copy(
83 new ExtensionAction(extension_id_, action_type_,
84 extensions::ActionInfo()));
85 copy->popup_url_ = popup_url_;
86 copy->title_ = title_;
87 copy->icon_ = icon_;
88 copy->badge_text_ = badge_text_;
89 copy->badge_background_color_ = badge_background_color_;
90 copy->badge_text_color_ = badge_text_color_;
91 copy->is_visible_ = is_visible_;
92 copy->id_ = id_;
94 if (default_icon_)
95 copy->default_icon_.reset(new ExtensionIconSet(*default_icon_));
97 return copy.Pass();
100 // static
101 int ExtensionAction::GetIconSizeForType(
102 extensions::ActionInfo::Type type) {
103 switch (type) {
104 case extensions::ActionInfo::TYPE_BROWSER:
105 case extensions::ActionInfo::TYPE_PAGE:
106 case extensions::ActionInfo::TYPE_SYSTEM_INDICATOR:
107 // TODO(dewittj) Report the actual icon size of the system
108 // indicator.
109 return extension_misc::EXTENSION_ICON_ACTION;
110 default:
111 NOTREACHED();
112 return 0;
116 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) {
117 // We store |url| even if it is empty, rather than removing a URL from the
118 // map. If an extension has a default popup, and removes it for a tab via
119 // the API, we must remember that there is no popup for that specific tab.
120 // If we removed the tab's URL, GetPopupURL would incorrectly return the
121 // default URL.
122 SetValue(&popup_url_, tab_id, url);
125 bool ExtensionAction::HasPopup(int tab_id) const {
126 return !GetPopupUrl(tab_id).is_empty();
129 GURL ExtensionAction::GetPopupUrl(int tab_id) const {
130 return GetValue(&popup_url_, tab_id);
133 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) {
134 SetValue(&icon_, tab_id, image.AsImageSkia());
137 gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const {
138 return GetValue(&icon_, tab_id);
141 bool ExtensionAction::SetIsVisible(int tab_id, bool new_visibility) {
142 const bool old_visibility = GetValue(&is_visible_, tab_id);
144 if (old_visibility == new_visibility)
145 return false;
147 SetValue(&is_visible_, tab_id, new_visibility);
149 return true;
152 void ExtensionAction::DeclarativeShow(int tab_id) {
153 DCHECK_NE(tab_id, kDefaultTabId);
154 ++declarative_show_count_[tab_id]; // Use default initialization to 0.
157 void ExtensionAction::UndoDeclarativeShow(int tab_id) {
158 int& show_count = declarative_show_count_[tab_id];
159 DCHECK_GT(show_count, 0);
160 if (--show_count == 0)
161 declarative_show_count_.erase(tab_id);
164 void ExtensionAction::ClearAllValuesForTab(int tab_id) {
165 popup_url_.erase(tab_id);
166 title_.erase(tab_id);
167 icon_.erase(tab_id);
168 badge_text_.erase(tab_id);
169 badge_text_color_.erase(tab_id);
170 badge_background_color_.erase(tab_id);
171 is_visible_.erase(tab_id);
172 // TODO(jyasskin): Erase the element from declarative_show_count_
173 // when the tab's closed. There's a race between the
174 // PageActionController and the ContentRulesRegistry on navigation,
175 // which prevents me from cleaning everything up now.
178 void ExtensionAction::PaintBadge(gfx::Canvas* canvas,
179 const gfx::Rect& bounds,
180 int tab_id) {
181 badge_util::PaintBadge(
182 canvas,
183 bounds,
184 GetBadgeText(tab_id),
185 GetBadgeTextColor(tab_id),
186 GetBadgeBackgroundColor(tab_id),
187 GetIconWidth(tab_id),
188 action_type());
191 gfx::ImageSkia ExtensionAction::GetIconWithBadge(
192 const gfx::ImageSkia& icon,
193 int tab_id,
194 const gfx::Size& spacing) const {
195 if (tab_id < 0)
196 return icon;
198 return gfx::ImageSkia(
199 new IconWithBadgeImageSource(icon,
200 icon.size(),
201 spacing,
202 GetBadgeText(tab_id),
203 GetBadgeTextColor(tab_id),
204 GetBadgeBackgroundColor(tab_id),
205 action_type()),
206 icon.size());
209 // Determines which icon would be returned by |GetIcon|, and returns its width.
210 int ExtensionAction::GetIconWidth(int tab_id) const {
211 // If icon has been set, return its width.
212 gfx::ImageSkia icon = GetValue(&icon_, tab_id);
213 if (!icon.isNull())
214 return icon.width();
215 // If there is a default icon, the icon width will be set depending on our
216 // action type.
217 if (default_icon_)
218 return GetIconSizeForType(action_type());
220 // If no icon has been set and there is no default icon, we need favicon
221 // width.
222 return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
223 IDR_EXTENSIONS_FAVICON).ToImageSkia()->width();