Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3524)

Unified Diff: chrome/common/extensions/extension_action.cc

Issue 10911300: Move ExtensionAction from common/ to browser/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: proof of concept Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/extension_action.cc
diff --git a/chrome/common/extensions/extension_action.cc b/chrome/common/extensions/extension_action.cc
deleted file mode 100644
index bab5dfbd563094bd9399a0c64bbb4539d0c1440e..0000000000000000000000000000000000000000
--- a/chrome/common/extensions/extension_action.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/extension_action.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "chrome/common/badge_util.h"
-#include "googleurl/src/gurl.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkDevice.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/effects/SkGradientShader.h"
-#include "ui/base/animation/animation_delegate.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/color_utils.h"
-#include "ui/gfx/image/canvas_image_source.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_source.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/image/image_skia_source.h"
-#include "ui/gfx/skbitmap_operations.h"
-
-namespace {
-
-// Different platforms need slightly different constants to look good.
-#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
-const float kTextSize = 9.0;
-const int kBottomMargin = 0;
-const int kPadding = 2;
-const int kTopTextPadding = 0;
-#elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
-const float kTextSize = 8.0;
-const int kBottomMargin = 5;
-const int kPadding = 2;
-const int kTopTextPadding = 1;
-#elif defined(OS_MACOSX)
-const float kTextSize = 9.0;
-const int kBottomMargin = 5;
-const int kPadding = 2;
-const int kTopTextPadding = 0;
-#else
-const float kTextSize = 10;
-const int kBottomMargin = 5;
-const int kPadding = 2;
-// The padding between the top of the badge and the top of the text.
-const int kTopTextPadding = -1;
-#endif
-
-const int kBadgeHeight = 11;
-const int kMaxTextWidth = 23;
-// The minimum width for center-aligning the badge.
-const int kCenterAlignThreshold = 20;
-
-class GetAttentionImageSource : public gfx::ImageSkiaSource {
- public:
- explicit GetAttentionImageSource(const gfx::ImageSkia& icon)
- : icon_(icon) {}
-
- // gfx::ImageSkiaSource overrides:
- virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale_factor)
- OVERRIDE {
- gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor);
- color_utils::HSL shift = {-1, 0, 0.5};
- return gfx::ImageSkiaRep(
- SkBitmapOperations::CreateHSLShiftedBitmap(icon_rep.sk_bitmap(), shift),
- icon_rep.scale_factor());
- }
-
- private:
- const gfx::ImageSkia icon_;
-};
-
-} // namespace
-
-// TODO(tbarzic): Merge AnimationIconImageSource and IconAnimation together.
-// Source for painting animated skia image.
-class AnimatedIconImageSource : public gfx::ImageSkiaSource {
- public:
- AnimatedIconImageSource(
- const gfx::ImageSkia& image,
- base::WeakPtr<ExtensionAction::IconAnimation> animation)
- : image_(image),
- animation_(animation) {
- }
-
- private:
- virtual ~AnimatedIconImageSource() {}
-
- virtual gfx::ImageSkiaRep GetImageForScale(ui::ScaleFactor scale) OVERRIDE {
- gfx::ImageSkiaRep original_rep = image_.GetRepresentation(scale);
- if (!animation_)
- return original_rep;
-
- // Original representation's scale factor may be different from scale
- // factor passed to this method. We want to use the former (since we are
- // using bitmap for that scale).
- return gfx::ImageSkiaRep(
- animation_->Apply(original_rep.sk_bitmap()),
- original_rep.scale_factor());
- }
-
- gfx::ImageSkia image_;
- base::WeakPtr<ExtensionAction::IconAnimation> animation_;
-
- DISALLOW_COPY_AND_ASSIGN(AnimatedIconImageSource);
-};
-
-// CanvasImageSource for creating browser action icon with a badge.
-class ExtensionAction::IconWithBadgeImageSource
- : public gfx::CanvasImageSource {
- public:
- IconWithBadgeImageSource(const gfx::ImageSkia& icon,
- const gfx::Size& spacing,
- const std::string& text,
- const SkColor& text_color,
- const SkColor& background_color)
- : gfx::CanvasImageSource(icon.size(), false),
- icon_(icon),
- spacing_(spacing),
- text_(text),
- text_color_(text_color),
- background_color_(background_color) {
- }
-
- virtual ~IconWithBadgeImageSource() {}
-
- private:
- virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
- canvas->DrawImageInt(icon_, 0, 0, SkPaint());
-
- gfx::Rect bounds(size_.width() + spacing_.width(),
- size_.height() + spacing_.height());
-
- // Draw a badge on the provided browser action icon's canvas.
- ExtensionAction::DoPaintBadge(canvas, bounds, text_, text_color_,
- background_color_, size_.width());
- }
-
- // Browser action icon image.
- gfx::ImageSkia icon_;
- // Extra spacing for badge compared to icon bounds.
- gfx::Size spacing_;
- // Text to be displayed on the badge.
- std::string text_;
- // Color of badge text.
- SkColor text_color_;
- // Color of the badge.
- SkColor background_color_;
-
- DISALLOW_COPY_AND_ASSIGN(IconWithBadgeImageSource);
-};
-
-
-const int ExtensionAction::kDefaultTabId = -1;
-// 100ms animation at 50fps (so 5 animation frames in total).
-const int kIconFadeInDurationMs = 100;
-const int kIconFadeInFramesPerSecond = 50;
-
-ExtensionAction::IconAnimation::IconAnimation()
- : ui::LinearAnimation(kIconFadeInDurationMs, kIconFadeInFramesPerSecond,
- NULL),
- weak_ptr_factory_(this) {}
-
-ExtensionAction::IconAnimation::~IconAnimation() {
- // Make sure observers don't access *this after its destructor has started.
- weak_ptr_factory_.InvalidateWeakPtrs();
- // In case the animation was destroyed before it finished (likely due to
- // delays in timer scheduling), make sure it's fully visible.
- FOR_EACH_OBSERVER(Observer, observers_, OnIconChanged());
-}
-
-const SkBitmap& ExtensionAction::IconAnimation::Apply(
- const SkBitmap& icon) const {
- DCHECK_GT(icon.width(), 0);
- DCHECK_GT(icon.height(), 0);
-
- if (!device_.get() ||
- (device_->width() != icon.width()) ||
- (device_->height() != icon.height())) {
- device_.reset(new SkDevice(
- SkBitmap::kARGB_8888_Config, icon.width(), icon.height(), true));
- }
-
- SkCanvas canvas(device_.get());
- canvas.clear(SK_ColorWHITE);
- SkPaint paint;
- paint.setAlpha(CurrentValueBetween(0, 255));
- canvas.drawBitmap(icon, 0, 0, &paint);
- return device_->accessBitmap(false);
-}
-
-base::WeakPtr<ExtensionAction::IconAnimation>
-ExtensionAction::IconAnimation::AsWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
-}
-
-void ExtensionAction::IconAnimation::AddObserver(
- ExtensionAction::IconAnimation::Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void ExtensionAction::IconAnimation::RemoveObserver(
- ExtensionAction::IconAnimation::Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void ExtensionAction::IconAnimation::AnimateToState(double state) {
- FOR_EACH_OBSERVER(Observer, observers_, OnIconChanged());
-}
-
-ExtensionAction::IconAnimation::ScopedObserver::ScopedObserver(
- const base::WeakPtr<IconAnimation>& icon_animation,
- Observer* observer)
- : icon_animation_(icon_animation),
- observer_(observer) {
- if (icon_animation.get())
- icon_animation->AddObserver(observer);
-}
-
-ExtensionAction::IconAnimation::ScopedObserver::~ScopedObserver() {
- if (icon_animation_.get())
- icon_animation_->RemoveObserver(observer_);
-}
-
-ExtensionAction::ExtensionAction(const std::string& extension_id,
- Type action_type)
- : extension_id_(extension_id),
- action_type_(action_type),
- has_changed_(false) {
-}
-
-ExtensionAction::~ExtensionAction() {
-}
-
-scoped_ptr<ExtensionAction> ExtensionAction::CopyForTest() const {
- scoped_ptr<ExtensionAction> copy(
- new ExtensionAction(extension_id_, action_type_));
- copy->popup_url_ = popup_url_;
- copy->title_ = title_;
- copy->icon_ = icon_;
- copy->icon_index_ = icon_index_;
- copy->badge_text_ = badge_text_;
- copy->badge_background_color_ = badge_background_color_;
- copy->badge_text_color_ = badge_text_color_;
- copy->appearance_ = appearance_;
- copy->icon_animation_ = icon_animation_;
- copy->default_icon_path_ = default_icon_path_;
- copy->id_ = id_;
- copy->icon_paths_ = icon_paths_;
- return copy.Pass();
-}
-
-void ExtensionAction::SetPopupUrl(int tab_id, const GURL& url) {
- // We store |url| even if it is empty, rather than removing a URL from the
- // map. If an extension has a default popup, and removes it for a tab via
- // the API, we must remember that there is no popup for that specific tab.
- // If we removed the tab's URL, GetPopupURL would incorrectly return the
- // default URL.
- SetValue(&popup_url_, tab_id, url);
-}
-
-bool ExtensionAction::HasPopup(int tab_id) const {
- return !GetPopupUrl(tab_id).is_empty();
-}
-
-GURL ExtensionAction::GetPopupUrl(int tab_id) const {
- return GetValue(&popup_url_, tab_id);
-}
-
-void ExtensionAction::CacheIcon(const std::string& path,
- const gfx::Image& icon) {
- if (!icon.IsEmpty())
- path_to_icon_cache_.insert(std::make_pair(path, *icon.ToImageSkia()));
-}
-
-void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) {
- SetValue(&icon_, tab_id, image.AsImageSkia());
-}
-
-gfx::Image ExtensionAction::GetIcon(int tab_id) const {
- // Check if a specific icon is set for this tab.
- gfx::ImageSkia icon = GetExplicitlySetIcon(tab_id);
- if (icon.isNull()) {
- // Need to find an icon from a path.
- const std::string* path = NULL;
- // Check if one of the elements of icon_path() was selected.
- int icon_index = GetIconIndex(tab_id);
- if (icon_index >= 0) {
- path = &icon_paths()->at(icon_index);
- } else {
- // Otherwise, use the default icon.
- path = &default_icon_path();
- }
-
- std::map<std::string, gfx::ImageSkia>::const_iterator cached_icon =
- path_to_icon_cache_.find(*path);
- if (cached_icon != path_to_icon_cache_.end()) {
- icon = cached_icon->second;
- } else {
- icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_EXTENSIONS_FAVICON);
- }
- }
-
- if (GetValue(&appearance_, tab_id) == WANTS_ATTENTION)
- icon = gfx::ImageSkia(new GetAttentionImageSource(icon), icon.size());
-
- return gfx::Image(ApplyIconAnimation(tab_id, icon));
-}
-
-gfx::ImageSkia ExtensionAction::GetExplicitlySetIcon(int tab_id) const {
- return GetValue(&icon_, tab_id);
-}
-
-void ExtensionAction::SetIconIndex(int tab_id, int index) {
- if (static_cast<size_t>(index) >= icon_paths_.size()) {
- NOTREACHED();
- return;
- }
- SetValue(&icon_index_, tab_id, index);
-}
-
-bool ExtensionAction::SetAppearance(int tab_id, Appearance new_appearance) {
- const Appearance old_appearance = GetValue(&appearance_, tab_id);
-
- if (old_appearance == new_appearance)
- return false;
-
- SetValue(&appearance_, tab_id, new_appearance);
-
- // When showing a badge for the first time on a web page, fade it
- // in. Other transitions happen instantly.
- if (old_appearance == INVISIBLE && tab_id != kDefaultTabId) {
- RunIconAnimation(tab_id);
- }
-
- return true;
-}
-
-void ExtensionAction::ClearAllValuesForTab(int tab_id) {
- popup_url_.erase(tab_id);
- title_.erase(tab_id);
- icon_.erase(tab_id);
- icon_index_.erase(tab_id);
- badge_text_.erase(tab_id);
- badge_text_color_.erase(tab_id);
- badge_background_color_.erase(tab_id);
- appearance_.erase(tab_id);
- icon_animation_.erase(tab_id);
-}
-
-void ExtensionAction::PaintBadge(gfx::Canvas* canvas,
- const gfx::Rect& bounds,
- int tab_id) {
- ExtensionAction::DoPaintBadge(
- canvas,
- bounds,
- GetBadgeText(tab_id),
- GetBadgeTextColor(tab_id),
- GetBadgeBackgroundColor(tab_id),
- GetValue(&icon_, tab_id).size().width());
-}
-
-gfx::ImageSkia ExtensionAction::GetIconWithBadge(
- const gfx::ImageSkia& icon,
- int tab_id,
- const gfx::Size& spacing) const {
- if (tab_id < 0)
- return icon;
-
- return gfx::ImageSkia(
- new IconWithBadgeImageSource(icon,
- spacing,
- GetBadgeText(tab_id),
- GetBadgeTextColor(tab_id),
- GetBadgeBackgroundColor(tab_id)),
- icon.size());
-}
-
-// static
-void ExtensionAction::DoPaintBadge(gfx::Canvas* canvas,
- const gfx::Rect& bounds,
- const std::string& text,
- const SkColor& text_color_in,
- const SkColor& background_color_in,
- int icon_width) {
- if (text.empty())
- return;
-
- SkColor text_color = text_color_in;
- if (SkColorGetA(text_color_in) == 0x00)
- text_color = SK_ColorWHITE;
-
- SkColor background_color = background_color_in;
- if (SkColorGetA(background_color_in) == 0x00)
- background_color = SkColorSetARGB(255, 218, 0, 24);
-
- canvas->Save();
-
- SkPaint* text_paint = badge_util::GetBadgeTextPaintSingleton();
- text_paint->setTextSize(SkFloatToScalar(kTextSize));
- text_paint->setColor(text_color);
-
- // Calculate text width. We clamp it to a max size.
- SkScalar sk_text_width = text_paint->measureText(text.c_str(), text.size());
- int text_width = std::min(kMaxTextWidth, SkScalarFloor(sk_text_width));
-
- // Calculate badge size. It is clamped to a min width just because it looks
- // silly if it is too skinny.
- int badge_width = text_width + kPadding * 2;
- // Force the pixel width of badge to be either odd (if the icon width is odd)
- // or even otherwise. If there is a mismatch you get http://crbug.com/26400.
- if (icon_width != 0 && (badge_width % 2 != icon_width % 2))
- badge_width += 1;
- badge_width = std::max(kBadgeHeight, badge_width);
-
- // Paint the badge background color in the right location. It is usually
- // right-aligned, but it can also be center-aligned if it is large.
- int rect_height = kBadgeHeight;
- int rect_y = bounds.bottom() - kBottomMargin - kBadgeHeight;
- int rect_width = badge_width;
- int rect_x = (badge_width >= kCenterAlignThreshold) ?
- (bounds.x() + bounds.width() - badge_width) / 2 :
- bounds.right() - badge_width;
- gfx::Rect rect(rect_x, rect_y, rect_width, rect_height);
-
- SkPaint rect_paint;
- rect_paint.setStyle(SkPaint::kFill_Style);
- rect_paint.setAntiAlias(true);
- rect_paint.setColor(background_color);
- canvas->DrawRoundRect(rect, 2, rect_paint);
-
- // Overlay the gradient. It is stretchy, so we do this in three parts.
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- gfx::ImageSkia* gradient_left = rb.GetImageSkiaNamed(
- IDR_BROWSER_ACTION_BADGE_LEFT);
- gfx::ImageSkia* gradient_right = rb.GetImageSkiaNamed(
- IDR_BROWSER_ACTION_BADGE_RIGHT);
- gfx::ImageSkia* gradient_center = rb.GetImageSkiaNamed(
- IDR_BROWSER_ACTION_BADGE_CENTER);
-
- canvas->DrawImageInt(*gradient_left, rect.x(), rect.y());
- canvas->TileImageInt(*gradient_center,
- rect.x() + gradient_left->width(),
- rect.y(),
- rect.width() - gradient_left->width() - gradient_right->width(),
- rect.height());
- canvas->DrawImageInt(*gradient_right,
- rect.right() - gradient_right->width(), rect.y());
-
- // Finally, draw the text centered within the badge. We set a clip in case the
- // text was too large.
- rect.Inset(kPadding, 0);
- canvas->ClipRect(rect);
- canvas->sk_canvas()->drawText(
- text.c_str(), text.size(),
- SkFloatToScalar(rect.x() +
- static_cast<float>(rect.width() - text_width) / 2),
- SkFloatToScalar(rect.y() + kTextSize + kTopTextPadding),
- *text_paint);
- canvas->Restore();
-}
-
-base::WeakPtr<ExtensionAction::IconAnimation> ExtensionAction::GetIconAnimation(
- int tab_id) const {
- std::map<int, base::WeakPtr<IconAnimation> >::iterator it =
- icon_animation_.find(tab_id);
- if (it == icon_animation_.end())
- return base::WeakPtr<ExtensionAction::IconAnimation>();
- if (it->second)
- return it->second;
-
- // Take this opportunity to remove all the NULL IconAnimations from
- // icon_animation_.
- icon_animation_.erase(it);
- for (it = icon_animation_.begin(); it != icon_animation_.end();) {
- if (it->second) {
- ++it;
- } else {
- // The WeakPtr is null; remove it from the map.
- icon_animation_.erase(it++);
- }
- }
- return base::WeakPtr<ExtensionAction::IconAnimation>();
-}
-
-gfx::ImageSkia ExtensionAction::ApplyIconAnimation(
- int tab_id,
- const gfx::ImageSkia& icon) const {
- base::WeakPtr<IconAnimation> animation = GetIconAnimation(tab_id);
- if (animation == NULL)
- return icon;
-
- return gfx::ImageSkia(new AnimatedIconImageSource(icon, animation),
- icon.size());
-}
-
-namespace {
-// Used to create a Callback owning an IconAnimation.
-void DestroyIconAnimation(scoped_ptr<ExtensionAction::IconAnimation>) {}
-}
-void ExtensionAction::RunIconAnimation(int tab_id) {
- scoped_ptr<IconAnimation> icon_animation(new IconAnimation());
- icon_animation_[tab_id] = icon_animation->AsWeakPtr();
- icon_animation->Start();
- // After the icon is finished fading in (plus some padding to handle random
- // timer delays), destroy it. We use a delayed task so that the Animation is
- // deleted even if it hasn't finished by the time the MessageLoop is
- // destroyed.
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DestroyIconAnimation, base::Passed(icon_animation.Pass())),
- base::TimeDelta::FromMilliseconds(kIconFadeInDurationMs * 2));
-}

Powered by Google App Engine
This is Rietveld 408576698