15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/extension_action/action_info.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_icon_set.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/animation/linear_animation.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GURL;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkBitmap;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkDevice;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Canvas;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Image;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ImageSkia;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Rect;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Size;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ExtensionAction encapsulates the state of a browser action, page action, or
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// script badge.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instances can have both global and per-tab state. If a property does not have
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a per-tab value, the global value is used instead.
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionAction {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use this ID to indicate the default state for properties that take a tab_id
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parameter.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kDefaultTabId;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Appearance {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The action icon is hidden.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INVISIBLE,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The action is trying to get the user's attention but isn't yet
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // running on the page.  Currently only used for script badges.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WANTS_ATTENTION,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The action icon is visible with its normal appearance.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACTIVE,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A fade-in animation.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class IconAnimation : public ui::LinearAnimation {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Observes changes to icon animation state.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class Observer {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual void OnIconChanged() = 0;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     protected:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      virtual ~Observer() {}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A holder for an IconAnimation with a scoped observer.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    class ScopedObserver {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     public:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScopedObserver(const base::WeakPtr<IconAnimation>& icon_animation,
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     Observer* observer);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ~ScopedObserver();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Gets the icon animation, or NULL if the reference has expired.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const IconAnimation* icon_animation() const {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return icon_animation_.get();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     private:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::WeakPtr<IconAnimation> icon_animation_;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Observer* observer_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DISALLOW_COPY_AND_ASSIGN(ScopedObserver);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~IconAnimation();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Returns the icon derived from the current animation state applied to
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |icon|. Ownership remains with this.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SkBitmap& Apply(const SkBitmap& icon) const;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddObserver(Observer* observer);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RemoveObserver(Observer* observer);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct using ExtensionAction::RunIconAnimation().
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class ExtensionAction;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IconAnimation();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<IconAnimation> AsWeakPtr();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // ui::LinearAnimation implementation.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void AnimateToState(double state) OVERRIDE;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Device we use to paint icons to.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mutable scoped_ptr<SkDevice> device_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ObserverList<Observer> observers_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtrFactory<IconAnimation> weak_ptr_factory_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(IconAnimation);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAction(const std::string& extension_id,
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  extensions::ActionInfo::Type action_type,
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const extensions::ActionInfo& manifest_data);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ExtensionAction();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets a copy of this, ownership passed to caller.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It doesn't make sense to copy of an ExtensionAction except in tests.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionAction> CopyForTest() const;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Given the extension action type, returns the size the extension action icon
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should have. The icon should be square, so only one dimension is
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returned.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static int GetIconSizeForType(extensions::ActionInfo::Type type);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension id
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& extension_id() const { return extension_id_; }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // What kind of action is this?
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::ActionInfo::Type action_type() const {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return action_type_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // action id -- only used with legacy page actions API
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id() const { return id_; }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_id(const std::string& id) { id_ = id; }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_changed() const { return has_changed_; }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_has_changed(bool value) { has_changed_ = value; }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the url which the popup will load when the user clicks this action's
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon.  Setting an empty URL will disable the popup for a given tab.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetPopupUrl(int tab_id, const GURL& url);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use HasPopup() to see if a popup should be displayed.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasPopup(int tab_id) const;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the URL to display in a popup.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL GetPopupUrl(int tab_id) const;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's title on a specific tab.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetTitle(int tab_id, const std::string& title) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetValue(&title_, tab_id, title);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If tab |tab_id| has a set title, return it.  Otherwise, return
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the default title.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetTitle(int tab_id) const { return GetValue(&title_, tab_id); }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Icons are a bit different because the default value can be set to either a
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bitmap or a path. However, conceptually, there is only one default icon.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setting the default icon using a path clears the bitmap and vice-versa.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To retrieve the icon for the extension action, use
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionActionIconFactory.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's icon bitmap on a specific tab.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetIcon(int tab_id, const gfx::Image& image);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Applies the attention and animation image transformations registered for
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the tab on the provided icon.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image ApplyAttentionAndAnimation(const gfx::ImageSkia& icon,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        int tab_id) const;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the icon that has been set using |SetIcon| for the tab.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetExplicitlySetIcon(int tab_id) const;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Non-tab-specific icon path. This is used to support the default_icon key of
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // page and browser actions.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_default_icon(scoped_ptr<ExtensionIconSet> icon_set) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     default_icon_ = icon_set.Pass();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExtensionIconSet* default_icon() const {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return default_icon_.get();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's badge text on a specific tab.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBadgeText(int tab_id, const std::string& text) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetValue(&badge_text_, tab_id, text);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the badge text for a tab, or the default if no badge text was set.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetBadgeText(int tab_id) const {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetValue(&badge_text_, tab_id);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's badge text color on a specific tab.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBadgeTextColor(int tab_id, SkColor text_color) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetValue(&badge_text_color_, tab_id, text_color);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the text color for a tab, or the default color if no text color
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was set.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor GetBadgeTextColor(int tab_id) const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetValue(&badge_text_color_, tab_id);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's badge background color on a specific tab.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetBadgeBackgroundColor(int tab_id, SkColor color) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetValue(&badge_background_color_, tab_id, color);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the badge background color for a tab, or the default if no color
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was set.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkColor GetBadgeBackgroundColor(int tab_id) const {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetValue(&badge_background_color_, tab_id);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set this action's badge visibility on a specific tab.  This takes
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // care of any appropriate transition animations.  Returns true if
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the appearance has changed.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetAppearance(int tab_id, Appearance value);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The declarative appearance overrides a default appearance but is overridden
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by an appearance set directly on the tab.
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DeclarativeShow(int tab_id);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UndoDeclarativeShow(int tab_id);
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the badge visibility for a tab, or the default badge visibility
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if none was set.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetIsVisible(int tab_id) const {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return GetAppearance(tab_id) != INVISIBLE;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the tab's action wants the user's attention.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool WantsAttention(int tab_id) const {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return GetAppearance(tab_id) == WANTS_ATTENTION;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove all tab-specific state.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearAllValuesForTab(int tab_id);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the specified tab has a badge, paint it into the provided bounds.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PaintBadge(gfx::Canvas* canvas, const gfx::Rect& bounds, int tab_id);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns icon image with badge for specified tab.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetIconWithBadge(const gfx::ImageSkia& icon,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int tab_id,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const gfx::Size& spacing) const;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets a weak reference to the icon animation for a tab, if any. The
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reference will only have a value while the animation is running.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<IconAnimation> GetIconAnimation(int tab_id) const;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Runs an animation on a tab.
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunIconAnimation(int tab_id);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the icon animation is running on tab |tab_id|, applies it to
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |orig| and returns the result. Otherwise, just returns |orig|.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia ApplyIconAnimation(int tab_id,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const gfx::ImageSkia& orig) const;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns width of the current icon for tab_id.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(tbarzic): The icon selection is done in ExtensionActionIconFactory.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should probably move this there too.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetIconWidth(int tab_id) const;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <class T>
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ValueTraits {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static T CreateEmpty() {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return T();
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class T>
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetValue(std::map<int, T>* map, int tab_id, const T& val) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*map)[tab_id] = val;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template<class Map>
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const typename Map::mapped_type* FindOrNull(
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const Map* map,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const typename Map::key_type& key) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    typename Map::const_iterator iter = map->find(key);
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (iter == map->end())
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return &iter->second;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template<class T>
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T GetValue(const std::map<int, T>* map, int tab_id) const {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (const T* tab_value = FindOrNull(map, tab_id)) {
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return *tab_value;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (const T* default_value = FindOrNull(map, kDefaultTabId)) {
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return *default_value;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ValueTraits<T>::CreateEmpty();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gets the appearance of |tab_id|.  Returns the first of: a specific
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // appearance set on the tab; a declarative appearance set on the tab; the
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // default appearance set for all tabs; or INVISIBLE.  Don't return this
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // result to an extension's background page because the declarative state can
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // leak information about hosts the extension doesn't have permission to
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // access.
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Appearance GetAppearance(int tab_id) const {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (const Appearance* tab_appearance = FindOrNull(&appearance_, tab_id))
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return *tab_appearance;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ContainsKey(declarative_show_count_, tab_id))
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return ACTIVE;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (const Appearance* default_appearance =
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FindOrNull(&appearance_, kDefaultTabId))
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return *default_appearance;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return INVISIBLE;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The id for the extension this action belongs to (as defined in the
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // extension manifest).
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string extension_id_;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const extensions::ActionInfo::Type action_type_;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Each of these data items can have both a global state (stored with the key
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kDefaultTabId), or tab-specific state (stored with the tab_id as the key).
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, GURL> popup_url_;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, std::string> title_;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, gfx::ImageSkia> icon_;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, std::string> badge_text_;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SkColor> badge_background_color_;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, SkColor> badge_text_color_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<int, Appearance> appearance_;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Declarative state exists for two reasons: First, we need to hide it from
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the extension's background/event page to avoid leaking data from hosts the
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // extension doesn't have permission to access.  Second, the action's state
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // gets both reset and given its declarative values in response to a
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // WebContentsObserver::DidNavigateMainFrame event, and there's no way to set
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // those up to be called in the right order.
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Maps tab_id to the number of active (applied-but-not-reverted)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // declarativeContent.ShowPageAction actions.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::map<int, int> declarative_show_count_;
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IconAnimations are destroyed by a delayed task on the UI message loop so
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that even if the Extension and ExtensionAction are destroyed on a non-UI
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread, the animation will still only be touched from the UI thread.  This
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // causes the WeakPtr in this map to become NULL.  GetIconAnimation() removes
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NULLs to prevent the map from growing without bound.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable std::map<int, base::WeakPtr<IconAnimation> > icon_animation_;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionIconSet containing paths to bitmaps from which default icon's
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // image representations will be selected.
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<const ExtensionIconSet> default_icon_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The id for the ExtensionAction, for example: "RssPageAction". This is
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // needed for compat with an older version of the page actions API.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id_;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the ExtensionAction's settings have changed from what was
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified in the manifest.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_changed_;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionAction);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<>
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionAction::ValueTraits<int> {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int CreateEmpty() {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_H_
378