• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "chrome/browser/extensions/api/extension_action/extension_action_api.h"
13 #include "chrome/browser/extensions/extension_action.h"
14 #include "components/keyed_service/core/keyed_service.h"
15 #include "content/public/browser/notification_observer.h"
16 #include "content/public/browser/notification_registrar.h"
17 #include "extensions/browser/extension_prefs.h"
18 #include "extensions/browser/extension_registry_observer.h"
19 #include "extensions/common/extension.h"
20 
21 class Browser;
22 class PrefService;
23 class Profile;
24 
25 namespace extensions {
26 class ExtensionRegistry;
27 class ExtensionSet;
28 
29 // Model for the browser actions toolbar.
30 class ExtensionToolbarModel : public content::NotificationObserver,
31                               public ExtensionActionAPI::Observer,
32                               public ExtensionRegistryObserver,
33                               public KeyedService {
34  public:
35   ExtensionToolbarModel(Profile* profile, ExtensionPrefs* extension_prefs);
36   virtual ~ExtensionToolbarModel();
37 
38   // A class which is informed of changes to the model; represents the view of
39   // MVC. Also used for signaling view changes such as showing extension popups.
40   // TODO(devlin): Should this really be an observer? It acts more like a
41   // delegate.
42   class Observer {
43    public:
44     // An extension has been added to the toolbar and should go at |index|.
45     virtual void ToolbarExtensionAdded(const Extension* extension,
46                                        int index) = 0;
47 
48     // The given |extension| should be removed from the toolbar.
49     virtual void ToolbarExtensionRemoved(const Extension* extension) = 0;
50 
51     // The given |extension| has been moved to |index|. |index| is the desired
52     // *final* index of the extension (that is, in the adjusted order, extension
53     // should be at |index|).
54     virtual void ToolbarExtensionMoved(const Extension* extension,
55                                        int index) = 0;
56 
57     // Signals that the browser action for the given |extension| has been
58     // updated.
59     virtual void ToolbarExtensionUpdated(const Extension* extension) = 0;
60 
61     // Signal the |extension| to show the popup now in the active window.
62     // If |grant_active_tab| is true, then active tab permissions should be
63     // given to the extension (only do this if this is through a user action).
64     // Returns true if a popup was slated to be shown.
65     virtual bool ShowExtensionActionPopup(const Extension* extension,
66                                           bool grant_active_tab) = 0;
67 
68     // Signal when the container needs to be redrawn because of a size change,
69     // and when the model has finished loading.
70     virtual void ToolbarVisibleCountChanged() = 0;
71 
72     // Signal that the model has entered or exited highlighting mode, or that
73     // the extensions being highlighted have (probably*) changed. Highlighting
74     // mode indicates that only a subset of the extensions are actively
75     // displayed, and those extensions should be highlighted for extra emphasis.
76     // * probably, because if we are in highlight mode and receive a call to
77     //   highlight a new set of extensions, we do not compare the current set
78     //   with the new set (and just assume the new set is different).
79     virtual void ToolbarHighlightModeChanged(bool is_highlighting) = 0;
80 
81     // Returns the browser associated with the Observer.
82     virtual Browser* GetBrowser() = 0;
83 
84    protected:
~Observer()85     virtual ~Observer() {}
86   };
87 
88   // Convenience function to get the ExtensionToolbarModel for a Profile.
89   static ExtensionToolbarModel* Get(Profile* profile);
90 
91   // Add or remove an observer.
92   void AddObserver(Observer* observer);
93   void RemoveObserver(Observer* observer);
94 
95   // Moves the given |extension|'s icon to the given |index|.
96   void MoveExtensionIcon(const Extension* extension, int index);
97 
98   // Sets the number of extension icons that should be visible.
99   // If count == size(), this will set the visible icon count to -1, meaning
100   // "show all actions".
101   void SetVisibleIconCount(int count);
102 
103   // As above, a return value of -1 represents "show all actions".
GetVisibleIconCount()104   int GetVisibleIconCount() const { return visible_icon_count_; }
105 
extensions_initialized()106   bool extensions_initialized() const { return extensions_initialized_; }
107 
toolbar_items()108   const ExtensionList& toolbar_items() const {
109     return is_highlighting_ ? highlighted_items_ : toolbar_items_;
110   }
111 
is_highlighting()112   bool is_highlighting() const { return is_highlighting_; }
113 
114   // Utility functions for converting between an index into the list of
115   // incognito-enabled browser actions, and the list of all browser actions.
116   int IncognitoIndexToOriginal(int incognito_index);
117   int OriginalIndexToIncognito(int original_index);
118 
119   void OnExtensionToolbarPrefChange();
120 
121   // Finds the Observer associated with |browser| and tells it to display a
122   // popup for the given |extension|. If |grant_active_tab| is true, this
123   // grants active tab permissions to the |extension|; only do this because of
124   // a direct user action.
125   bool ShowExtensionActionPopup(const Extension* extension,
126                                 Browser* browser,
127                                 bool grant_active_tab);
128 
129   // Ensures that the extensions in the |extension_ids| list are visible on the
130   // toolbar. This might mean they need to be moved to the front (if they are in
131   // the overflow bucket).
132   void EnsureVisibility(const ExtensionIdList& extension_ids);
133 
134   // Highlight the extensions specified by |extension_ids|. This will cause
135   // the ToolbarModel to only display those extensions.
136   // Highlighting mode is only entered if there is at least one extension to
137   // be shown.
138   // Returns true if highlighting mode is entered, false otherwise.
139   bool HighlightExtensions(const ExtensionIdList& extension_ids);
140 
141   // Stop highlighting extensions. All extensions can be shown again, and the
142   // number of visible icons will be reset to what it was before highlighting.
143   void StopHighlighting();
144 
145   // Sets the number of visible icons and notifies all observers of the change.
146   void SetVisibleIconCountForTest(size_t visible_icons);
147 
148  private:
149   // content::NotificationObserver:
150   virtual void Observe(int type,
151                        const content::NotificationSource& source,
152                        const content::NotificationDetails& details) OVERRIDE;
153 
154   // Callback when extensions are ready.
155   void OnReady();
156 
157   // ExtensionRegistryObserver:
158   virtual void OnExtensionLoaded(content::BrowserContext* browser_context,
159                                  const Extension* extension) OVERRIDE;
160   virtual void OnExtensionUnloaded(
161       content::BrowserContext* browser_context,
162       const Extension* extension,
163       UnloadedExtensionInfo::Reason reason) OVERRIDE;
164   virtual void OnExtensionUninstalled(
165       content::BrowserContext* browser_context,
166       const Extension* extension,
167       extensions::UninstallReason reason) OVERRIDE;
168 
169   // ExtensionActionAPI::Observer:
170   virtual void OnExtensionActionUpdated(
171       ExtensionAction* extension_action,
172       content::WebContents* web_contents,
173       content::BrowserContext* browser_context) OVERRIDE;
174 
175   // To be called after the extension service is ready; gets loaded extensions
176   // from the extension service and their saved order from the pref service
177   // and constructs |toolbar_items_| from these data.
178   void InitializeExtensionList(const ExtensionSet& extensions);
179   void Populate(const ExtensionIdList& positions,
180                 const ExtensionSet& extensions);
181 
182   // Save the model to prefs.
183   void UpdatePrefs();
184 
185   // Updates |extension|'s browser action visibility pref if the browser action
186   // is in the overflow menu and should be considered hidden.
187   void MaybeUpdateVisibilityPref(const Extension* extension, int index);
188 
189   // Calls MaybeUpdateVisibilityPref() for each extension in |toolbar_items|.
190   void MaybeUpdateVisibilityPrefs();
191 
192   // Finds the last known visible position of the icon for an |extension|. The
193   // value returned is a zero-based index into the vector of visible items.
194   size_t FindNewPositionFromLastKnownGood(const Extension* extension);
195 
196   // Returns true if the given |extension| should be added to the toolbar.
197   bool ShouldAddExtension(const Extension* extension);
198 
199   // Adds or removes the given |extension| from the toolbar model.
200   void AddExtension(const Extension* extension);
201   void RemoveExtension(const Extension* extension);
202 
203   // Our observers.
204   ObserverList<Observer> observers_;
205 
206   // The Profile this toolbar model is for.
207   Profile* profile_;
208 
209   ExtensionPrefs* extension_prefs_;
210   PrefService* prefs_;
211 
212   // True if we've handled the initial EXTENSIONS_READY notification.
213   bool extensions_initialized_;
214 
215   // If true, we include all extensions in the toolbar model. If false, we only
216   // include browser actions.
217   bool include_all_extensions_;
218 
219   // Ordered list of browser action buttons.
220   ExtensionList toolbar_items_;
221 
222   // List of browser action buttons which should be highlighted.
223   ExtensionList highlighted_items_;
224 
225   // Indication whether or not we are currently in highlight mode; typically,
226   // this is equivalent to !highlighted_items_.empty(), but can be different
227   // if we are exiting highlight mode due to no longer having highlighted items.
228   bool is_highlighting_;
229 
230   // The number of icons which were visible before highlighting a subset, in
231   // order to restore the count when finished.
232   int old_visible_icon_count_;
233 
234   ExtensionIdList last_known_positions_;
235 
236   // The number of icons visible (the rest should be hidden in the overflow
237   // chevron).
238   int visible_icon_count_;
239 
240   content::NotificationRegistrar registrar_;
241 
242   ScopedObserver<ExtensionActionAPI, ExtensionActionAPI::Observer>
243       extension_action_observer_;
244 
245   // Listen to extension load, unloaded notifications.
246   ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
247       extension_registry_observer_;
248 
249   // For observing change of toolbar order preference by external entity (sync).
250   PrefChangeRegistrar pref_change_registrar_;
251   base::Closure pref_change_callback_;
252 
253   base::WeakPtrFactory<ExtensionToolbarModel> weak_ptr_factory_;
254 
255   DISALLOW_COPY_AND_ASSIGN(ExtensionToolbarModel);
256 };
257 
258 }  // namespace extensions
259 
260 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
261