OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_action.h" | 5 #include "chrome/browser/extensions/extension_action.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | |
11 #include "base/logging.h" | 10 #include "base/logging.h" |
12 #include "base/message_loop/message_loop.h" | |
13 #include "chrome/common/badge_util.h" | 11 #include "chrome/common/badge_util.h" |
14 #include "chrome/common/icon_with_badge_image_source.h" | 12 #include "chrome/common/icon_with_badge_image_source.h" |
| 13 #include "extensions/browser/extension_icon_image.h" |
15 #include "extensions/common/constants.h" | 14 #include "extensions/common/constants.h" |
| 15 #include "extensions/common/extension_icon_set.h" |
| 16 #include "extensions/common/manifest_handlers/icons_handler.h" |
16 #include "grit/theme_resources.h" | 17 #include "grit/theme_resources.h" |
17 #include "grit/ui_resources.h" | 18 #include "grit/ui_resources.h" |
18 #include "ipc/ipc_message.h" | 19 #include "ipc/ipc_message.h" |
19 #include "ipc/ipc_message_utils.h" | 20 #include "ipc/ipc_message_utils.h" |
20 #include "third_party/skia/include/core/SkBitmap.h" | 21 #include "third_party/skia/include/core/SkBitmap.h" |
21 #include "third_party/skia/include/core/SkCanvas.h" | 22 #include "third_party/skia/include/core/SkCanvas.h" |
22 #include "third_party/skia/include/core/SkPaint.h" | 23 #include "third_party/skia/include/core/SkPaint.h" |
23 #include "third_party/skia/include/effects/SkGradientShader.h" | 24 #include "third_party/skia/include/effects/SkGradientShader.h" |
24 #include "ui/base/resource/resource_bundle.h" | 25 #include "ui/base/resource/resource_bundle.h" |
25 #include "ui/gfx/animation/animation_delegate.h" | 26 #include "ui/gfx/animation/animation_delegate.h" |
26 #include "ui/gfx/canvas.h" | 27 #include "ui/gfx/canvas.h" |
27 #include "ui/gfx/color_utils.h" | 28 #include "ui/gfx/color_utils.h" |
28 #include "ui/gfx/geometry/rect.h" | 29 #include "ui/gfx/geometry/rect.h" |
29 #include "ui/gfx/geometry/size.h" | 30 #include "ui/gfx/geometry/size.h" |
30 #include "ui/gfx/image/image.h" | 31 #include "ui/gfx/image/image.h" |
31 #include "ui/gfx/image/image_skia.h" | 32 #include "ui/gfx/image/image_skia.h" |
32 #include "ui/gfx/image/image_skia_source.h" | 33 #include "ui/gfx/image/image_skia_source.h" |
33 #include "ui/gfx/ipc/gfx_param_traits.h" | 34 #include "ui/gfx/ipc/gfx_param_traits.h" |
34 #include "ui/gfx/skbitmap_operations.h" | 35 #include "ui/gfx/skbitmap_operations.h" |
35 #include "url/gurl.h" | 36 #include "url/gurl.h" |
36 | 37 |
37 namespace { | 38 namespace { |
38 | 39 |
| 40 // Returns the default icon image for extensions. |
| 41 gfx::Image GetDefaultIcon() { |
| 42 return ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 43 IDR_EXTENSIONS_FAVICON); |
| 44 } |
| 45 |
| 46 // Given the extension action type, returns the size the extension action icon |
| 47 // should have. The icon should be square, so only one dimension is |
| 48 // returned. |
| 49 int GetIconSizeForType(extensions::ActionInfo::Type type) { |
| 50 switch (type) { |
| 51 case extensions::ActionInfo::TYPE_BROWSER: |
| 52 case extensions::ActionInfo::TYPE_PAGE: |
| 53 case extensions::ActionInfo::TYPE_SYSTEM_INDICATOR: |
| 54 // TODO(dewittj) Report the actual icon size of the system |
| 55 // indicator. |
| 56 return extension_misc::EXTENSION_ICON_ACTION; |
| 57 default: |
| 58 NOTREACHED(); |
| 59 return 0; |
| 60 } |
| 61 } |
| 62 |
39 class GetAttentionImageSource : public gfx::ImageSkiaSource { | 63 class GetAttentionImageSource : public gfx::ImageSkiaSource { |
40 public: | 64 public: |
41 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) | 65 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) |
42 : icon_(icon) {} | 66 : icon_(icon) {} |
43 | 67 |
44 // gfx::ImageSkiaSource overrides: | 68 // gfx::ImageSkiaSource overrides: |
45 gfx::ImageSkiaRep GetImageForScale(float scale) override { | 69 gfx::ImageSkiaRep GetImageForScale(float scale) override { |
46 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale); | 70 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale); |
47 color_utils::HSL shift = {-1, 0, 0.5}; | 71 color_utils::HSL shift = {-1, 0, 0.5}; |
48 return gfx::ImageSkiaRep( | 72 return gfx::ImageSkiaRep( |
(...skipping 20 matching lines...) Expand all Loading... |
69 bool HasValue(const std::map<int, T>& map, int tab_id) { | 93 bool HasValue(const std::map<int, T>& map, int tab_id) { |
70 return map.find(tab_id) != map.end(); | 94 return map.find(tab_id) != map.end(); |
71 } | 95 } |
72 | 96 |
73 } // namespace | 97 } // namespace |
74 | 98 |
75 const int ExtensionAction::kDefaultTabId = -1; | 99 const int ExtensionAction::kDefaultTabId = -1; |
76 const int ExtensionAction::kPageActionIconMaxSize = | 100 const int ExtensionAction::kPageActionIconMaxSize = |
77 extension_misc::EXTENSION_ICON_ACTION; | 101 extension_misc::EXTENSION_ICON_ACTION; |
78 | 102 |
79 ExtensionAction::ExtensionAction(const std::string& extension_id, | 103 ExtensionAction::ExtensionAction(const extensions::Extension& extension, |
80 extensions::ActionInfo::Type action_type, | 104 extensions::ActionInfo::Type action_type, |
81 const extensions::ActionInfo& manifest_data) | 105 const extensions::ActionInfo& manifest_data) |
82 : extension_id_(extension_id), action_type_(action_type) { | 106 : extension_id_(extension.id()), action_type_(action_type) { |
83 // Page/script actions are hidden/disabled by default, and browser actions are | 107 // Page/script actions are hidden/disabled by default, and browser actions are |
84 // visible/enabled by default. | 108 // visible/enabled by default. |
85 SetIsVisible(kDefaultTabId, | 109 SetIsVisible(kDefaultTabId, |
86 action_type == extensions::ActionInfo::TYPE_BROWSER); | 110 action_type == extensions::ActionInfo::TYPE_BROWSER); |
87 SetTitle(kDefaultTabId, manifest_data.default_title); | 111 Populate(extension, manifest_data); |
88 SetPopupUrl(kDefaultTabId, manifest_data.default_popup_url); | |
89 if (!manifest_data.default_icon.empty()) { | |
90 set_default_icon(make_scoped_ptr(new ExtensionIconSet( | |
91 manifest_data.default_icon))); | |
92 } | |
93 set_id(manifest_data.id); | |
94 } | 112 } |
95 | 113 |
96 ExtensionAction::~ExtensionAction() { | 114 ExtensionAction::~ExtensionAction() { |
97 } | 115 } |
98 | 116 |
99 scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const { | |
100 scoped_ptr<ExtensionAction> copy( | |
101 new ExtensionAction(extension_id_, action_type_, | |
102 extensions::ActionInfo())); | |
103 copy->popup_url_ = popup_url_; | |
104 copy->title_ = title_; | |
105 copy->icon_ = icon_; | |
106 copy->badge_text_ = badge_text_; | |
107 copy->badge_background_color_ = badge_background_color_; | |
108 copy->badge_text_color_ = badge_text_color_; | |
109 copy->is_visible_ = is_visible_; | |
110 copy->id_ = id_; | |
111 | |
112 if (default_icon_) | |
113 copy->default_icon_.reset(new ExtensionIconSet(*default_icon_)); | |
114 | |
115 return copy.Pass(); | |
116 } | |
117 | |
118 // static | |
119 int ExtensionAction::GetIconSizeForType( | |
120 extensions::ActionInfo::Type type) { | |
121 switch (type) { | |
122 case extensions::ActionInfo::TYPE_BROWSER: | |
123 case extensions::ActionInfo::TYPE_PAGE: | |
124 case extensions::ActionInfo::TYPE_SYSTEM_INDICATOR: | |
125 // TODO(dewittj) Report the actual icon size of the system | |
126 // indicator. | |
127 return extension_misc::EXTENSION_ICON_ACTION; | |
128 default: | |
129 NOTREACHED(); | |
130 return 0; | |
131 } | |
132 } | |
133 | |
134 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { | 117 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { |
135 // We store |url| even if it is empty, rather than removing a URL from the | 118 // We store |url| even if it is empty, rather than removing a URL from the |
136 // map. If an extension has a default popup, and removes it for a tab via | 119 // map. If an extension has a default popup, and removes it for a tab via |
137 // the API, we must remember that there is no popup for that specific tab. | 120 // the API, we must remember that there is no popup for that specific tab. |
138 // If we removed the tab's URL, GetPopupURL would incorrectly return the | 121 // If we removed the tab's URL, GetPopupURL would incorrectly return the |
139 // default URL. | 122 // default URL. |
140 SetValue(&popup_url_, tab_id, url); | 123 SetValue(&popup_url_, tab_id, url); |
141 } | 124 } |
142 | 125 |
143 bool ExtensionAction::HasPopup(int tab_id) const { | 126 bool ExtensionAction::HasPopup(int tab_id) const { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 new IconWithBadgeImageSource(icon, | 258 new IconWithBadgeImageSource(icon, |
276 icon.size(), | 259 icon.size(), |
277 spacing, | 260 spacing, |
278 GetBadgeText(tab_id), | 261 GetBadgeText(tab_id), |
279 GetBadgeTextColor(tab_id), | 262 GetBadgeTextColor(tab_id), |
280 GetBadgeBackgroundColor(tab_id), | 263 GetBadgeBackgroundColor(tab_id), |
281 action_type()), | 264 action_type()), |
282 icon.size()); | 265 icon.size()); |
283 } | 266 } |
284 | 267 |
| 268 extensions::IconImage* ExtensionAction::LoadDefaultIconImage( |
| 269 const extensions::Extension& extension, |
| 270 content::BrowserContext* browser_context) { |
| 271 if (default_icon_ && !default_icon_image_) { |
| 272 default_icon_image_.reset(new extensions::IconImage( |
| 273 browser_context, |
| 274 &extension, |
| 275 *default_icon(), |
| 276 GetIconSizeForType(action_type_), |
| 277 *GetDefaultIcon().ToImageSkia(), |
| 278 nullptr)); |
| 279 } |
| 280 return default_icon_image_.get(); |
| 281 } |
| 282 |
| 283 gfx::ImageSkia ExtensionAction::GetDefaultIconImage() const { |
| 284 // If we have a default icon, it should be loaded before trying to use it. |
| 285 DCHECK(!default_icon_image_ == !default_icon_); |
| 286 return default_icon_image_ ? default_icon_image_->image_skia() : |
| 287 *GetDefaultIcon().ToImageSkia(); |
| 288 } |
| 289 |
285 bool ExtensionAction::HasPopupUrl(int tab_id) const { | 290 bool ExtensionAction::HasPopupUrl(int tab_id) const { |
286 return HasValue(popup_url_, tab_id); | 291 return HasValue(popup_url_, tab_id); |
287 } | 292 } |
288 | 293 |
289 bool ExtensionAction::HasTitle(int tab_id) const { | 294 bool ExtensionAction::HasTitle(int tab_id) const { |
290 return HasValue(title_, tab_id); | 295 return HasValue(title_, tab_id); |
291 } | 296 } |
292 | 297 |
293 bool ExtensionAction::HasBadgeText(int tab_id) const { | 298 bool ExtensionAction::HasBadgeText(int tab_id) const { |
294 return HasValue(badge_text_, tab_id); | 299 return HasValue(badge_text_, tab_id); |
295 } | 300 } |
296 | 301 |
297 bool ExtensionAction::HasBadgeBackgroundColor(int tab_id) const { | 302 bool ExtensionAction::HasBadgeBackgroundColor(int tab_id) const { |
298 return HasValue(badge_background_color_, tab_id); | 303 return HasValue(badge_background_color_, tab_id); |
299 } | 304 } |
300 | 305 |
301 bool ExtensionAction::HasBadgeTextColor(int tab_id) const { | 306 bool ExtensionAction::HasBadgeTextColor(int tab_id) const { |
302 return HasValue(badge_text_color_, tab_id); | 307 return HasValue(badge_text_color_, tab_id); |
303 } | 308 } |
304 | 309 |
305 bool ExtensionAction::HasIsVisible(int tab_id) const { | 310 bool ExtensionAction::HasIsVisible(int tab_id) const { |
306 return HasValue(is_visible_, tab_id); | 311 return HasValue(is_visible_, tab_id); |
307 } | 312 } |
308 | 313 |
309 bool ExtensionAction::HasIcon(int tab_id) const { | 314 bool ExtensionAction::HasIcon(int tab_id) const { |
310 return HasValue(icon_, tab_id); | 315 return HasValue(icon_, tab_id); |
311 } | 316 } |
312 | 317 |
| 318 void ExtensionAction::SetDefaultIconForTest( |
| 319 scoped_ptr<ExtensionIconSet> default_icon) { |
| 320 default_icon_ = default_icon.Pass(); |
| 321 } |
| 322 |
| 323 void ExtensionAction::Populate(const extensions::Extension& extension, |
| 324 const extensions::ActionInfo& manifest_data) { |
| 325 // If the manifest doesn't specify a title, set it to |extension|'s name. |
| 326 const std::string& title = |
| 327 !manifest_data.default_title.empty() ? manifest_data.default_title : |
| 328 extension.name(); |
| 329 SetTitle(kDefaultTabId, title); |
| 330 SetPopupUrl(kDefaultTabId, manifest_data.default_popup_url); |
| 331 set_id(manifest_data.id); |
| 332 |
| 333 // Initialize the specified icon set. |
| 334 if (!manifest_data.default_icon.empty()) |
| 335 default_icon_.reset(new ExtensionIconSet(manifest_data.default_icon)); |
| 336 |
| 337 const ExtensionIconSet& extension_icons = |
| 338 extensions::IconsInfo::GetIcons(&extension); |
| 339 // Look for any other icons. |
| 340 std::string largest_icon = extension_icons.Get( |
| 341 extension_misc::EXTENSION_ICON_GIGANTOR, |
| 342 ExtensionIconSet::MATCH_SMALLER); |
| 343 |
| 344 if (!largest_icon.empty()) { |
| 345 // We found an icon to use, so create an icon set if one doesn't exist. |
| 346 if (!default_icon_) |
| 347 default_icon_.reset(new ExtensionIconSet()); |
| 348 int largest_icon_size = extension_icons.GetIconSizeFromPath(largest_icon); |
| 349 // Replace any missing extension action icons with the largest icon |
| 350 // retrieved from |extension|'s manifest so long as the largest icon is |
| 351 // larger than the current key. |
| 352 for (int i = extension_misc::kNumExtensionActionIconSizes - 1; |
| 353 i >= 0; --i) { |
| 354 int size = extension_misc::kExtensionActionIconSizes[i].size; |
| 355 if (default_icon_->Get(size, ExtensionIconSet::MATCH_BIGGER).empty() |
| 356 && largest_icon_size > size) { |
| 357 default_icon_->Add(size, largest_icon); |
| 358 break; |
| 359 } |
| 360 } |
| 361 } |
| 362 } |
| 363 |
313 // Determines which icon would be returned by |GetIcon|, and returns its width. | 364 // Determines which icon would be returned by |GetIcon|, and returns its width. |
314 int ExtensionAction::GetIconWidth(int tab_id) const { | 365 int ExtensionAction::GetIconWidth(int tab_id) const { |
315 // If icon has been set, return its width. | 366 // If icon has been set, return its width. |
316 gfx::ImageSkia icon = GetValue(&icon_, tab_id); | 367 gfx::ImageSkia icon = GetValue(&icon_, tab_id); |
317 if (!icon.isNull()) | 368 if (!icon.isNull()) |
318 return icon.width(); | 369 return icon.width(); |
319 // If there is a default icon, the icon width will be set depending on our | 370 // If there is a default icon, the icon width will be set depending on our |
320 // action type. | 371 // action type. |
321 if (default_icon_) | 372 if (default_icon_) |
322 return GetIconSizeForType(action_type()); | 373 return GetIconSizeForType(action_type()); |
323 | 374 |
324 // If no icon has been set and there is no default icon, we need favicon | 375 // If no icon has been set and there is no default icon, we need favicon |
325 // width. | 376 // width. |
326 return ui::ResourceBundle::GetSharedInstance().GetImageNamed( | 377 return ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
327 IDR_EXTENSIONS_FAVICON).ToImageSkia()->width(); | 378 IDR_EXTENSIONS_FAVICON).Width(); |
328 } | 379 } |
OLD | NEW |