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