| 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 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 scoped_ptr<ExtensionAction> copy( | 247 scoped_ptr<ExtensionAction> copy( |
| 247 new ExtensionAction(extension_id_, action_type_)); | 248 new ExtensionAction(extension_id_, action_type_)); |
| 248 copy->popup_url_ = popup_url_; | 249 copy->popup_url_ = popup_url_; |
| 249 copy->title_ = title_; | 250 copy->title_ = title_; |
| 250 copy->icon_ = icon_; | 251 copy->icon_ = icon_; |
| 251 copy->badge_text_ = badge_text_; | 252 copy->badge_text_ = badge_text_; |
| 252 copy->badge_background_color_ = badge_background_color_; | 253 copy->badge_background_color_ = badge_background_color_; |
| 253 copy->badge_text_color_ = badge_text_color_; | 254 copy->badge_text_color_ = badge_text_color_; |
| 254 copy->appearance_ = appearance_; | 255 copy->appearance_ = appearance_; |
| 255 copy->icon_animation_ = icon_animation_; | 256 copy->icon_animation_ = icon_animation_; |
| 256 copy->default_icon_path_ = default_icon_path_; | |
| 257 copy->id_ = id_; | 257 copy->id_ = id_; |
| 258 |
| 259 if (default_icon_.get()) |
| 260 copy->default_icon_.reset(new ExtensionIconSet(*default_icon_)); |
| 261 |
| 258 return copy.Pass(); | 262 return copy.Pass(); |
| 259 } | 263 } |
| 260 | 264 |
| 265 // static |
| 266 int ExtensionAction::GetIconSizeForType(ExtensionAction::Type type) { |
| 267 switch (type) { |
| 268 case ExtensionAction::TYPE_BROWSER: |
| 269 case ExtensionAction::TYPE_PAGE: |
| 270 return extension_misc::EXTENSION_ICON_ACTION; |
| 271 case ExtensionAction::TYPE_SCRIPT_BADGE: |
| 272 return extension_misc::EXTENSION_ICON_BITTY; |
| 273 default: |
| 274 NOTREACHED(); |
| 275 return 0; |
| 276 } |
| 277 } |
| 278 |
| 261 void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) { | 279 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 | 280 // 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 | 281 // 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. | 282 // 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 | 283 // If we removed the tab's URL, GetPopupURL would incorrectly return the |
| 266 // default URL. | 284 // default URL. |
| 267 SetValue(&popup_url_, tab_id, url); | 285 SetValue(&popup_url_, tab_id, url); |
| 268 } | 286 } |
| 269 | 287 |
| 270 bool ExtensionAction::HasPopup(int tab_id) const { | 288 bool ExtensionAction::HasPopup(int tab_id) const { |
| 271 return !GetPopupUrl(tab_id).is_empty(); | 289 return !GetPopupUrl(tab_id).is_empty(); |
| 272 } | 290 } |
| 273 | 291 |
| 274 GURL ExtensionAction::GetPopupUrl(int tab_id) const { | 292 GURL ExtensionAction::GetPopupUrl(int tab_id) const { |
| 275 return GetValue(&popup_url_, tab_id); | 293 return GetValue(&popup_url_, tab_id); |
| 276 } | 294 } |
| 277 | 295 |
| 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) { | 296 void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) { |
| 284 SetValue(&icon_, tab_id, image.AsImageSkia()); | 297 SetValue(&icon_, tab_id, image.AsImageSkia()); |
| 285 } | 298 } |
| 286 | 299 |
| 287 gfx::Image ExtensionAction::GetIcon(int tab_id) const { | 300 gfx::Image ExtensionAction::ApplyAttentionAndAnimation( |
| 288 // Check if a specific icon is set for this tab. | 301 const gfx::ImageSkia& original_icon, |
| 289 gfx::ImageSkia icon = GetExplicitlySetIcon(tab_id); | 302 int tab_id) const { |
| 290 if (icon.isNull()) { | 303 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) | 304 if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION) |
| 300 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); | 305 icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size()); |
| 301 | 306 |
| 302 return gfx::Image(ApplyIconAnimation(tab_id, icon)); | 307 return gfx::Image(ApplyIconAnimation(tab_id, icon)); |
| 303 } | 308 } |
| 304 | 309 |
| 305 gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const { | 310 gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const { |
| 306 return GetValue(&icon_, tab_id); | 311 return GetValue(&icon_, tab_id); |
| 307 } | 312 } |
| 308 | 313 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 336 | 341 |
| 337 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, | 342 void ExtensionAction::PaintBadge(gfx::Canvas* canvas, |
| 338 const gfx::Rect& bounds, | 343 const gfx::Rect& bounds, |
| 339 int tab_id) { | 344 int tab_id) { |
| 340 ExtensionAction::DoPaintBadge( | 345 ExtensionAction::DoPaintBadge( |
| 341 canvas, | 346 canvas, |
| 342 bounds, | 347 bounds, |
| 343 GetBadgeText(tab_id), | 348 GetBadgeText(tab_id), |
| 344 GetBadgeTextColor(tab_id), | 349 GetBadgeTextColor(tab_id), |
| 345 GetBadgeBackgroundColor(tab_id), | 350 GetBadgeBackgroundColor(tab_id), |
| 346 GetValue(&icon_, tab_id).size().width()); | 351 GetIconWidth(tab_id)); |
| 347 } | 352 } |
| 348 | 353 |
| 349 gfx::ImageSkia ExtensionAction::GetIconWithBadge( | 354 gfx::ImageSkia ExtensionAction::GetIconWithBadge( |
| 350 const gfx::ImageSkia& icon, | 355 const gfx::ImageSkia& icon, |
| 351 int tab_id, | 356 int tab_id, |
| 352 const gfx::Size& spacing) const { | 357 const gfx::Size& spacing) const { |
| 353 if (tab_id < 0) | 358 if (tab_id < 0) |
| 354 return icon; | 359 return icon; |
| 355 | 360 |
| 356 return gfx::ImageSkia( | 361 return gfx::ImageSkia( |
| 357 new IconWithBadgeImageSource(icon, | 362 new IconWithBadgeImageSource(icon, |
| 358 spacing, | 363 spacing, |
| 359 GetBadgeText(tab_id), | 364 GetBadgeText(tab_id), |
| 360 GetBadgeTextColor(tab_id), | 365 GetBadgeTextColor(tab_id), |
| 361 GetBadgeBackgroundColor(tab_id)), | 366 GetBadgeBackgroundColor(tab_id)), |
| 362 icon.size()); | 367 icon.size()); |
| 363 } | 368 } |
| 364 | 369 |
| 370 // Determines which icon would be returned by |GetIcon|, and returns its width. |
| 371 int ExtensionAction::GetIconWidth(int tab_id) const { |
| 372 // If icon has been set, return its width. |
| 373 gfx::ImageSkia icon = GetValue(&icon_, tab_id); |
| 374 if (!icon.isNull()) |
| 375 return icon.width(); |
| 376 // If there is a default icon, the icon width will be set depending on our |
| 377 // action type. |
| 378 if (default_icon_.get()) |
| 379 return GetIconSizeForType(action_type()); |
| 380 |
| 381 // If no icon has been set and there is no default icon, we need favicon |
| 382 // width. |
| 383 return ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 384 IDR_EXTENSIONS_FAVICON).ToImageSkia()->width(); |
| 385 } |
| 386 |
| 365 // static | 387 // static |
| 366 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, | 388 void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas, |
| 367 const gfx::Rect& bounds, | 389 const gfx::Rect& bounds, |
| 368 const std::string& text, | 390 const std::string& text, |
| 369 const SkColor& text_color_in, | 391 const SkColor& text_color_in, |
| 370 const SkColor& background_color_in, | 392 const SkColor& background_color_in, |
| 371 int icon_width) { | 393 int icon_width) { |
| 372 if (text.empty()) | 394 if (text.empty()) |
| 373 return; | 395 return; |
| 374 | 396 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 icon_animation->Start(); | 512 icon_animation->Start(); |
| 491 // After the icon is finished fading in (plus some padding to handle random | 513 // 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 | 514 // 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 | 515 // deleted even if it hasn't finished by the time the MessageLoop is |
| 494 // destroyed. | 516 // destroyed. |
| 495 MessageLoop::current()->PostDelayedTask( | 517 MessageLoop::current()->PostDelayedTask( |
| 496 FROM_HERE, | 518 FROM_HERE, |
| 497 base::Bind(&DestroyIconAnimation, base::Passed(icon_animation.Pass())), | 519 base::Bind(&DestroyIconAnimation, base::Passed(icon_animation.Pass())), |
| 498 base::TimeDelta::FromMilliseconds(kIconFadeInDurationMs * 2)); | 520 base::TimeDelta::FromMilliseconds(kIconFadeInDurationMs * 2)); |
| 499 } | 521 } |
| OLD | NEW |