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