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/common/extensions/extension_action.h" | 5 #include "chrome/common/extensions/extension_action.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
12 #include "chrome/common/badge_util.h" | 12 #include "chrome/common/badge_util.h" |
| 13 #include "chrome/common/extensions/extension_constants.h" |
13 #include "googleurl/src/gurl.h" | 14 #include "googleurl/src/gurl.h" |
14 #include "grit/theme_resources.h" | 15 #include "grit/theme_resources.h" |
15 #include "grit/ui_resources.h" | 16 #include "grit/ui_resources.h" |
16 #include "third_party/skia/include/core/SkBitmap.h" | 17 #include "third_party/skia/include/core/SkBitmap.h" |
17 #include "third_party/skia/include/core/SkCanvas.h" | 18 #include "third_party/skia/include/core/SkCanvas.h" |
18 #include "third_party/skia/include/core/SkDevice.h" | 19 #include "third_party/skia/include/core/SkDevice.h" |
19 #include "third_party/skia/include/core/SkPaint.h" | 20 #include "third_party/skia/include/core/SkPaint.h" |
20 #include "third_party/skia/include/effects/SkGradientShader.h" | 21 #include "third_party/skia/include/effects/SkGradientShader.h" |
21 #include "ui/base/animation/animation_delegate.h" | 22 #include "ui/base/animation/animation_delegate.h" |
22 #include "ui/base/resource/resource_bundle.h" | 23 #include "ui/base/resource/resource_bundle.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 const int kPadding = 2; | 55 const int kPadding = 2; |
55 // The padding between the top of the badge and the top of the text. | 56 // The padding between the top of the badge and the top of the text. |
56 const int kTopTextPadding = -1; | 57 const int kTopTextPadding = -1; |
57 #endif | 58 #endif |
58 | 59 |
59 const int kBadgeHeight = 11; | 60 const int kBadgeHeight = 11; |
60 const int kMaxTextWidth = 23; | 61 const int kMaxTextWidth = 23; |
61 // The minimum width for center-aligning the badge. | 62 // The minimum width for center-aligning the badge. |
62 const int kCenterAlignThreshold = 20; | 63 const int kCenterAlignThreshold = 20; |
63 | 64 |
| 65 gfx::Size GetIconSizeForActionType(ExtensionAction::Type type) { |
| 66 switch (type) { |
| 67 case ExtensionAction::TYPE_BROWSER: |
| 68 case ExtensionAction::TYPE_PAGE: |
| 69 return gfx::Size(extension_misc::EXTENSION_ICON_ACTION, |
| 70 extension_misc::EXTENSION_ICON_ACTION); |
| 71 case ExtensionAction::TYPE_SCRIPT_BADGE: |
| 72 return gfx::Size(extension_misc::EXTENSION_ICON_BITTY, |
| 73 extension_misc::EXTENSION_ICON_BITTY); |
| 74 default: |
| 75 NOTREACHED(); |
| 76 return gfx::Size(); |
| 77 } |
| 78 } |
| 79 |
64 class GetAttentionImageSource : public gfx::ImageSkiaSource { | 80 class GetAttentionImageSource : public gfx::ImageSkiaSource { |
65 public: | 81 public: |
66 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) | 82 explicit GetAttentionImageSource(const gfx::ImageSkia& icon) |
67 : icon_(icon) {} | 83 : icon_(icon) {} |
68 | 84 |
69 // gfx::ImageSkiaSource overrides: | 85 // gfx::ImageSkiaSource overrides: |
70 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) | 86 virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor) |
71 OVERRIDE { | 87 OVERRIDE { |
72 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); | 88 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor); |
73 color_utils::HSL shift = {-1, 0, 0.5}; | 89 color_utils::HSL shift = {-1, 0, 0.5}; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 scoped_ptr<ExtensionAction> copy( | 262 scoped_ptr<ExtensionAction> copy( |
247 new ExtensionAction(extension_id_, action_type_)); | 263 new ExtensionAction(extension_id_, action_type_)); |
248 copy->popup_url_ = popup_url_; | 264 copy->popup_url_ = popup_url_; |
249 copy->title_ = title_; | 265 copy->title_ = title_; |
250 copy->icon_ = icon_; | 266 copy->icon_ = icon_; |
251 copy->badge_text_ = badge_text_; | 267 copy->badge_text_ = badge_text_; |
252 copy->badge_background_color_ = badge_background_color_; | 268 copy->badge_background_color_ = badge_background_color_; |
253 copy->badge_text_color_ = badge_text_color_; | 269 copy->badge_text_color_ = badge_text_color_; |
254 copy->appearance_ = appearance_; | 270 copy->appearance_ = appearance_; |
255 copy->icon_animation_ = icon_animation_; | 271 copy->icon_animation_ = icon_animation_; |
256 copy->default_icon_path_ = default_icon_path_; | |
257 copy->id_ = id_; | 272 copy->id_ = id_; |
| 273 |
| 274 if (default_icon_.get()) { |
| 275 scoped_ptr<ExtensionIconSet> default_icon_copy(new ExtensionIconSet()); |
| 276 default_icon_->CopyForTest(default_icon_copy.get()); |
| 277 copy->default_icon_ = default_icon_copy.Pass(); |
| 278 } |
| 279 |
258 return copy.Pass(); | 280 return copy.Pass(); |
259 } | 281 } |
260 | 282 |
261 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { | 283 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { |
262 // We store |url| even if it is empty, rather than removing a URL from the | 284 // We store |url| even if it is empty, rather than removing a URL from the |
263 // map. If an extension has a default popup, and removes it for a tab via | 285 // map. If an extension has a default popup, and removes it for a tab via |
264 // the API, we must remember that there is no popup for that specific tab. | 286 // the API, we must remember that there is no popup for that specific tab. |
265 // If we removed the tab's URL, GetPopupURL would incorrectly return the | 287 // If we removed the tab's URL, GetPopupURL would incorrectly return the |
266 // default URL. | 288 // default URL. |
267 SetValue(&popup_url_, tab_id, url); | 289 SetValue(&popup_url_, tab_id, url); |
268 } | 290 } |
269 | 291 |
270 bool ExtensionAction::HasPopup(int tab_id) const { | 292 bool ExtensionAction::HasPopup(int tab_id) const { |
271 return !GetPopupUrl(tab_id).is_empty(); | 293 return !GetPopupUrl(tab_id).is_empty(); |
272 } | 294 } |
273 | 295 |
274 GURL ExtensionAction::GetPopupUrl(int tab_id) const { | 296 GURL ExtensionAction::GetPopupUrl(int tab_id) const { |
275 return GetValue(&popup_url_, tab_id); | 297 return GetValue(&popup_url_, tab_id); |
276 } | 298 } |
277 | 299 |
278 void ExtensionAction::CacheIcon(const gfx::Image& icon) { | |
279 if (!icon.IsEmpty()) | |
280 cached_icon_.reset(new gfx::ImageSkia(*icon.ToImageSkia())); | |
281 } | |
282 | |
283 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { | 300 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { |
284 SetValue(&icon_, tab_id, image.AsImageSkia()); | 301 SetValue(&icon_, tab_id, image.AsImageSkia()); |
285 } | 302 } |
286 | 303 |
287 gfx::Image ExtensionAction::GetIcon(int tab_id) const { | 304 gfx::Image ExtensionAction::ApplyAttentionAndAnimation( |
288 // Check if a specific icon is set for this tab. | 305 const gfx::ImageSkia& original_icon, |
289 gfx::ImageSkia icon = GetExplicitlySetIcon(tab_id); | 306 int tab_id) const { |
290 if (icon.isNull()) { | 307 gfx::ImageSkia icon = original_icon; |
291 if (cached_icon_.get()) { | |
292 icon = *cached_icon_; | |
293 } else { | |
294 icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
295 IDR_EXTENSIONS_FAVICON); | |
296 } | |
297 } | |
298 | |
299 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) | 308 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) |
300 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); | 309 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); |
301 | 310 |
302 return gfx::Image(ApplyIconAnimation(tab_id, icon)); | 311 return gfx::Image(ApplyIconAnimation(tab_id, icon)); |
303 } | 312 } |
304 | 313 |
305 gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const { | 314 gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const { |
306 return GetValue(&icon_, tab_id); | 315 return GetValue(&icon_, tab_id); |
307 } | 316 } |
308 | 317 |
(...skipping 27 matching lines...) Expand all Loading... |
336 | 345 |
337 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, | 346 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, |
338 const gfx::Rect& bounds, | 347 const gfx::Rect& bounds, |
339 int tab_id) { | 348 int tab_id) { |
340 ExtensionAction::DoPaintBadge( | 349 ExtensionAction::DoPaintBadge( |
341 canvas, | 350 canvas, |
342 bounds, | 351 bounds, |
343 GetBadgeText(tab_id), | 352 GetBadgeText(tab_id), |
344 GetBadgeTextColor(tab_id), | 353 GetBadgeTextColor(tab_id), |
345 GetBadgeBackgroundColor(tab_id), | 354 GetBadgeBackgroundColor(tab_id), |
346 GetValue(&icon_, tab_id).size().width()); | 355 GetIconWidth(tab_id)); |
347 } | 356 } |
348 | 357 |
349 gfx::ImageSkia ExtensionAction::GetIconWithBadge( | 358 gfx::ImageSkia ExtensionAction::GetIconWithBadge( |
350 const gfx::ImageSkia& icon, | 359 const gfx::ImageSkia& icon, |
351 int tab_id, | 360 int tab_id, |
352 const gfx::Size& spacing) const { | 361 const gfx::Size& spacing) const { |
353 if (tab_id < 0) | 362 if (tab_id < 0) |
354 return icon; | 363 return icon; |
355 | 364 |
356 return gfx::ImageSkia( | 365 return gfx::ImageSkia( |
357 new IconWithBadgeImageSource(icon, | 366 new IconWithBadgeImageSource(icon, |
358 spacing, | 367 spacing, |
359 GetBadgeText(tab_id), | 368 GetBadgeText(tab_id), |
360 GetBadgeTextColor(tab_id), | 369 GetBadgeTextColor(tab_id), |
361 GetBadgeBackgroundColor(tab_id)), | 370 GetBadgeBackgroundColor(tab_id)), |
362 icon.size()); | 371 icon.size()); |
363 } | 372 } |
364 | 373 |
| 374 // Determines which icon would be returned by |GetIcon|, and returns its width. |
| 375 int ExtensionAction::GetIconWidth(int tab_id) const { |
| 376 // If icon has been set, return its width. |
| 377 gfx::ImageSkia icon = GetValue(&icon_, tab_id); |
| 378 if (!icon.isNull()) |
| 379 return icon.width(); |
| 380 // If there is a default icon, the icon width will be set depending on our |
| 381 // action type. |
| 382 if (default_icon_.get()) |
| 383 return GetIconSizeForActionType(action_type()).width(); |
| 384 |
| 385 // If no icon has been set and there is no default icon, we need favicon |
| 386 // width. |
| 387 return ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 388 IDR_EXTENSIONS_FAVICON).ToImageSkia()->width(); |
| 389 } |
| 390 |
365 // static | 391 // static |
366 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, | 392 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, |
367 const gfx::Rect& bounds, | 393 const gfx::Rect& bounds, |
368 const std::string& text, | 394 const std::string& text, |
369 const SkColor& text_color_in, | 395 const SkColor& text_color_in, |
370 const SkColor& background_color_in, | 396 const SkColor& background_color_in, |
371 int icon_width) { | 397 int icon_width) { |
372 if (text.empty()) | 398 if (text.empty()) |
373 return; | 399 return; |
374 | 400 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 icon_animation->Start(); | 516 icon_animation->Start(); |
491 // After the icon is finished fading in (plus some padding to handle random | 517 // After the icon is finished fading in (plus some padding to handle random |
492 // timer delays), destroy it. We use a delayed task so that the Animation is | 518 // timer delays), destroy it. We use a delayed task so that the Animation is |
493 // deleted even if it hasn't finished by the time the MessageLoop is | 519 // deleted even if it hasn't finished by the time the MessageLoop is |
494 // destroyed. | 520 // destroyed. |
495 MessageLoop::current()->PostDelayedTask( | 521 MessageLoop::current()->PostDelayedTask( |
496 FROM_HERE, | 522 FROM_HERE, |
497 base::Bind(&DestroyIconAnimation, base::Passed(icon_animation.Pass())), | 523 base::Bind(&DestroyIconAnimation, base::Passed(icon_animation.Pass())), |
498 base::TimeDelta::FromMilliseconds(kIconFadeInDurationMs * 2)); | 524 base::TimeDelta::FromMilliseconds(kIconFadeInDurationMs * 2)); |
499 } | 525 } |
OLD | NEW |