Home | History | Annotate | Download | only in extensions
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
      6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
      7 
      8 #include "base/compiler_specific.h"
      9 #include "base/observer_list.h"
     10 #include "base/prefs/pref_change_registrar.h"
     11 #include "base/scoped_observer.h"
     12 #include "components/keyed_service/core/keyed_service.h"
     13 #include "content/public/browser/notification_observer.h"
     14 #include "content/public/browser/notification_registrar.h"
     15 #include "extensions/browser/extension_prefs.h"
     16 #include "extensions/browser/extension_registry_observer.h"
     17 #include "extensions/common/extension.h"
     18 
     19 class Browser;
     20 class PrefService;
     21 class Profile;
     22 
     23 namespace extensions {
     24 class ExtensionRegistry;
     25 class ExtensionSet;
     26 
     27 // Model for the browser actions toolbar.
     28 class ExtensionToolbarModel : public content::NotificationObserver,
     29                               public ExtensionRegistryObserver,
     30                               public KeyedService {
     31  public:
     32   ExtensionToolbarModel(Profile* profile, ExtensionPrefs* extension_prefs);
     33   virtual ~ExtensionToolbarModel();
     34 
     35   // The action that should be taken as a result of clicking a browser action.
     36   enum Action {
     37     ACTION_NONE,
     38     ACTION_SHOW_POPUP,
     39     // Unlike LocationBarController there is no ACTION_SHOW_CONTEXT_MENU,
     40     // because UI implementations tend to handle this themselves at a higher
     41     // level.
     42   };
     43 
     44   // A class which is informed of changes to the model; represents the view of
     45   // MVC. Also used for signaling view changes such as showing extension popups.
     46   class Observer {
     47    public:
     48     // An extension with a browser action button has been added, and should go
     49     // in the toolbar at |index|.
     50     virtual void BrowserActionAdded(const Extension* extension, int index) {}
     51 
     52     // The browser action button for |extension| should no longer show.
     53     virtual void BrowserActionRemoved(const Extension* extension) {}
     54 
     55     // The browser action button for |extension| has been moved to |index|.
     56     virtual void BrowserActionMoved(const Extension* extension, int index) {}
     57 
     58     // Signal the |extension| to show the popup now in the active window.
     59     // Returns true if a popup was slated to be shown.
     60     virtual bool BrowserActionShowPopup(const Extension* extension);
     61 
     62     // Signal when the container needs to be redrawn because of a size change,
     63     // and when the model has finished loading.
     64     virtual void VisibleCountChanged() {}
     65 
     66     // Signal that the model has entered or exited highlighting mode, or that
     67     // the extensions being highlighted have (probably*) changed. Highlighting
     68     // mode indicates that only a subset of the extensions are actively
     69     // displayed, and those extensions should be highlighted for extra emphasis.
     70     // * probably, because if we are in highlight mode and receive a call to
     71     //   highlight a new set of extensions, we do not compare the current set
     72     //   with the new set (and just assume the new set is different).
     73     virtual void HighlightModeChanged(bool is_highlighting) {}
     74 
     75    protected:
     76     virtual ~Observer() {}
     77   };
     78 
     79   // Convenience function to get the ExtensionToolbarModel for a Profile.
     80   static ExtensionToolbarModel* Get(Profile* profile);
     81 
     82   // Functions called by the view.
     83   void AddObserver(Observer* observer);
     84   void RemoveObserver(Observer* observer);
     85   void MoveBrowserAction(const Extension* extension, int index);
     86   // Executes the browser action for an extension and returns the action that
     87   // the UI should perform in response.
     88   // |popup_url_out| will be set if the extension should show a popup, with
     89   // the URL that should be shown, if non-NULL. |should_grant| controls whether
     90   // the extension should be granted page tab permissions, which is what happens
     91   // when the user clicks the browser action, but not, for example, when the
     92   // showPopup API is called.
     93   Action ExecuteBrowserAction(const Extension* extension,
     94                               Browser* browser,
     95                               GURL* popup_url_out,
     96                               bool should_grant);
     97   // If count == size(), this will set the visible icon count to -1, meaning
     98   // "show all actions".
     99   void SetVisibleIconCount(int count);
    100   // As above, a return value of -1 represents "show all actions".
    101   int GetVisibleIconCount() const { return visible_icon_count_; }
    102 
    103   bool extensions_initialized() const { return extensions_initialized_; }
    104 
    105   const ExtensionList& toolbar_items() const {
    106     return is_highlighting_ ? highlighted_items_ : toolbar_items_;
    107   }
    108 
    109   bool is_highlighting() const { return is_highlighting_; }
    110 
    111   // Utility functions for converting between an index into the list of
    112   // incognito-enabled browser actions, and the list of all browser actions.
    113   int IncognitoIndexToOriginal(int incognito_index);
    114   int OriginalIndexToIncognito(int original_index);
    115 
    116   void OnExtensionToolbarPrefChange();
    117 
    118   // Tells observers to display a popup without granting tab permissions and
    119   // returns whether the popup was slated to be shown.
    120   bool ShowBrowserActionPopup(const Extension* extension);
    121 
    122   // Ensures that the extensions in the |extension_ids| list are visible on the
    123   // toolbar. This might mean they need to be moved to the front (if they are in
    124   // the overflow bucket).
    125   void EnsureVisibility(const ExtensionIdList& extension_ids);
    126 
    127   // Highlight the extensions specified by |extension_ids|. This will cause
    128   // the ToolbarModel to only display those extensions.
    129   // Highlighting mode is only entered if there is at least one extension to
    130   // be shown.
    131   // Returns true if highlighting mode is entered, false otherwise.
    132   bool HighlightExtensions(const ExtensionIdList& extension_ids);
    133 
    134   // Stop highlighting extensions. All extensions can be shown again, and the
    135   // number of visible icons will be reset to what it was before highlighting.
    136   void StopHighlighting();
    137 
    138  private:
    139   // content::NotificationObserver implementation.
    140   virtual void Observe(int type,
    141                        const content::NotificationSource& source,
    142                        const content::NotificationDetails& details) OVERRIDE;
    143 
    144   // Callback when extensions are ready.
    145   void OnReady();
    146 
    147   // ExtensionRegistryObserver implementation.
    148   virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
    149                                  const Extension* extension) OVERRIDE;
    150   virtual void OnExtensionUnloaded(
    151       content::BrowserContext* browser_context,
    152       const Extension* extension,
    153       UnloadedExtensionInfo::Reason reason) OVERRIDE;
    154   virtual void OnExtensionUninstalled(content::BrowserContext* browser_context,
    155                                       const Extension* extension) OVERRIDE;
    156 
    157   // To be called after the extension service is ready; gets loaded extensions
    158   // from the extension service and their saved order from the pref service
    159   // and constructs |toolbar_items_| from these data.
    160   void InitializeExtensionList(const ExtensionSet& extensions);
    161   void Populate(const ExtensionIdList& positions,
    162                 const ExtensionSet& extensions);
    163 
    164   // Save the model to prefs.
    165   void UpdatePrefs();
    166 
    167   // Finds the last known visible position of the icon for an |extension|. The
    168   // value returned is a zero-based index into the vector of visible items.
    169   size_t FindNewPositionFromLastKnownGood(const Extension* extension);
    170 
    171   // Our observers.
    172   ObserverList<Observer> observers_;
    173 
    174   void AddExtension(const Extension* extension);
    175   void RemoveExtension(const Extension* extension);
    176 
    177   // The Profile this toolbar model is for.
    178   Profile* profile_;
    179 
    180   ExtensionPrefs* extension_prefs_;
    181   PrefService* prefs_;
    182 
    183   // True if we've handled the initial EXTENSIONS_READY notification.
    184   bool extensions_initialized_;
    185 
    186   // Ordered list of browser action buttons.
    187   ExtensionList toolbar_items_;
    188 
    189   // List of browser action buttons which should be highlighted.
    190   ExtensionList highlighted_items_;
    191 
    192   // Indication whether or not we are currently in highlight mode; typically,
    193   // this is equivalent to !highlighted_items_.empty(), but can be different
    194   // if we are exiting highlight mode due to no longer having highlighted items.
    195   bool is_highlighting_;
    196 
    197   // The number of icons which were visible before highlighting a subset, in
    198   // order to restore the count when finished.
    199   int old_visible_icon_count_;
    200 
    201   ExtensionIdList last_known_positions_;
    202 
    203   // The number of icons visible (the rest should be hidden in the overflow
    204   // chevron).
    205   int visible_icon_count_;
    206 
    207   content::NotificationRegistrar registrar_;
    208 
    209   // Listen to extension load, unloaded notifications.
    210   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
    211       extension_registry_observer_;
    212 
    213   // For observing change of toolbar order preference by external entity (sync).
    214   PrefChangeRegistrar pref_change_registrar_;
    215   base::Closure pref_change_callback_;
    216 
    217   base::WeakPtrFactory<ExtensionToolbarModel> weak_ptr_factory_;
    218 
    219   DISALLOW_COPY_AND_ASSIGN(ExtensionToolbarModel);
    220 };
    221 
    222 }  // namespace extensions
    223 
    224 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
    225