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_TOOLBAR_MODEL_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_change_registrar.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Browser;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionService;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrefService;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Model for the browser actions toolbar.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionToolbarModel : public content::NotificationObserver {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ExtensionToolbarModel(ExtensionService* service);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionToolbarModel();
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The action that should be taken as a result of clicking a browser action.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Action {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACTION_NONE,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACTION_SHOW_POPUP,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Unlike LocationBarController there is no ACTION_SHOW_CONTEXT_MENU,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because UI implementations tend to handle this themselves at a higher
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // level.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A class which is informed of changes to the model; represents the view of
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MVC.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Observer {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // An extension with a browser action button has been added, and should go
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the toolbar at |index|.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void BrowserActionAdded(const extensions::Extension* extension,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int index) {}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The browser action button for |extension| should no longer show.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void BrowserActionRemoved(const extensions::Extension* extension) {}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The browser action button for |extension| has been moved to |index|.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void BrowserActionMoved(const extensions::Extension* extension,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    int index) {}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Called when the model has finished loading.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void ModelLoaded() {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~Observer() {}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Functions called by the view.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddObserver(Observer* observer);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveObserver(Observer* observer);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MoveBrowserAction(const extensions::Extension* extension, int index);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Executes the browser action for an extension and returns the action that
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the UI should perform in response.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |popup_url_out| will be set if the extension should show a popup, with
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the URL that should be shown, if non-NULL.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Action ExecuteBrowserAction(const extensions::Extension* extension,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              Browser* browser,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              GURL* popup_url_out);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If count == size(), this will set the visible icon count to -1, meaning
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "show all actions".
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetVisibleIconCount(int count);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As above, a return value of -1 represents "show all actions".
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int GetVisibleIconCount() const { return visible_icon_count_; }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool extensions_initialized() const { return extensions_initialized_; }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const extensions::ExtensionList& toolbar_items() const {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return toolbar_items_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Utility functions for converting between an index into the list of
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // incognito-enabled browser actions, and the list of all browser actions.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int IncognitoIndexToOriginal(int incognito_index);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int OriginalIndexToIncognito(int original_index);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnExtensionToolbarPrefChange();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::NotificationObserver implementation.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To be called after the extension service is ready; gets loaded extensions
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from the extension service and their saved order from the pref service
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and constructs |toolbar_items_| from these data.
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void InitializeExtensionList();
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Populate(const extensions::ExtensionIdList& positions);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fills |list| with extensions based on provided |order|.
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void FillExtensionList(const extensions::ExtensionIdList& order);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the model to prefs.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdatePrefs();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Finds the last known visible position of the icon for an |extension|. The
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // value returned is a zero-based index into the vector of visible items.
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t FindNewPositionFromLastKnownGood(
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const extensions::Extension* extension);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our observers.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObserverList<Observer> observers_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddExtension(const extensions::Extension* extension);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RemoveExtension(const extensions::Extension* extension);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UninstalledExtension(const extensions::Extension* extension);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our ExtensionService, guaranteed to outlive us.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService* service_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if we've handled the initial EXTENSIONS_READY notification.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool extensions_initialized_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ordered list of browser action buttons.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extensions::ExtensionList toolbar_items_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::ExtensionIdList last_known_positions_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of icons visible (the rest should be hidden in the overflow
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chevron).
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int visible_icon_count_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // For observing change of toolbar order preference by external entity (sync).
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PrefChangeRegistrar pref_change_registrar_;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::Closure pref_change_callback_;
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WeakPtrFactory<ExtensionToolbarModel> weak_ptr_factory_;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionToolbarModel);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
147