Home | History | Annotate | Download | only in launcher
      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_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_PER_BROWSER_H_
      6 #define CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_PER_BROWSER_H_
      7 
      8 #include <list>
      9 #include <map>
     10 #include <string>
     11 
     12 #include "ash/display/display_controller.h"
     13 #include "ash/launcher/launcher_delegate.h"
     14 #include "ash/launcher/launcher_model_observer.h"
     15 #include "ash/launcher/launcher_types.h"
     16 #include "ash/shelf/shelf_layout_manager_observer.h"
     17 #include "ash/shelf/shelf_types.h"
     18 #include "ash/shell_observer.h"
     19 #include "base/basictypes.h"
     20 #include "base/compiler_specific.h"
     21 #include "base/memory/scoped_ptr.h"
     22 #include "base/prefs/pref_change_registrar.h"
     23 #include "chrome/browser/extensions/extension_prefs.h"
     24 #include "chrome/browser/prefs/pref_service_syncable_observer.h"
     25 #include "chrome/browser/ui/ash/app_sync_ui_state_observer.h"
     26 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
     27 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
     28 #include "content/public/browser/notification_observer.h"
     29 #include "content/public/browser/notification_registrar.h"
     30 #include "ui/aura/window_observer.h"
     31 
     32 class AppSyncUIState;
     33 class Browser;
     34 class BrowserLauncherItemControllerTest;
     35 class ExtensionEnableFlow;
     36 class LauncherItemController;
     37 class Profile;
     38 class ShellWindowLauncherController;
     39 
     40 namespace ash {
     41 class LauncherModel;
     42 }
     43 
     44 namespace aura {
     45 class Window;
     46 }
     47 
     48 namespace content {
     49 class WebContents;
     50 }
     51 
     52 namespace ui {
     53 class BaseWindow;
     54 }
     55 
     56 // ChromeLauncherControllerPerBrowser manages the launcher items needed for
     57 // content windows. Launcher items have a type, an optional app id, and a
     58 // controller. This incarnation manages the items on a per browser base using
     59 // browser proxies and application icons.
     60 // * Tabbed browsers and browser app windows have BrowserLauncherItemController,
     61 //   owned by the BrowserView instance.
     62 // * App shell windows have ShellWindowLauncherItemController, owned by
     63 //   ShellWindowLauncherController.
     64 // * Shortcuts have no LauncherItemController.
     65 class ChromeLauncherControllerPerBrowser
     66     : public ash::LauncherModelObserver,
     67       public ash::ShellObserver,
     68       public ash::DisplayController::Observer,
     69       public ChromeLauncherController,
     70       public content::NotificationObserver,
     71       public PrefServiceSyncableObserver,
     72       public AppSyncUIStateObserver,
     73       public ExtensionEnableFlowDelegate,
     74       public ash::ShelfLayoutManagerObserver {
     75  public:
     76   ChromeLauncherControllerPerBrowser(Profile* profile,
     77                                      ash::LauncherModel* model);
     78   virtual ~ChromeLauncherControllerPerBrowser();
     79 
     80   // ChromeLauncherController overrides:
     81 
     82   // Initializes this ChromeLauncherControllerPerBrowser.
     83   virtual void Init() OVERRIDE;
     84 
     85   // Returns the new per application interface of the given launcher. If it is
     86   // a per browser (old) controller, it will return NULL;
     87   // TODO(skuhne): Remove when we rip out the old launcher.
     88   virtual ChromeLauncherControllerPerApp* GetPerAppInterface() OVERRIDE;
     89 
     90   // Creates a new tabbed item on the launcher for |controller|.
     91   virtual ash::LauncherID CreateTabbedLauncherItem(
     92       LauncherItemController* controller,
     93       IncognitoState is_incognito,
     94       ash::LauncherItemStatus status) OVERRIDE;
     95 
     96   // Creates a new app item on the launcher for |controller|.
     97   virtual ash::LauncherID CreateAppLauncherItem(
     98       LauncherItemController* controller,
     99       const std::string& app_id,
    100       ash::LauncherItemStatus status) OVERRIDE;
    101 
    102   // Updates the running status of an item.
    103   virtual void SetItemStatus(ash::LauncherID id,
    104                              ash::LauncherItemStatus status) OVERRIDE;
    105 
    106   // Updates the controller associated with id (which should be a shortcut).
    107   // |controller| remains owned by caller.
    108   virtual void SetItemController(ash::LauncherID id,
    109                                  LauncherItemController* controller) OVERRIDE;
    110 
    111   // Closes or unpins the launcher item.
    112   virtual void CloseLauncherItem(ash::LauncherID id) OVERRIDE;
    113 
    114   // Pins the specified id. Currently only supports platform apps.
    115   virtual void Pin(ash::LauncherID id) OVERRIDE;
    116 
    117   // Unpins the specified id, closing if not running.
    118   virtual void Unpin(ash::LauncherID id) OVERRIDE;
    119 
    120   // Returns true if the item identified by |id| is pinned.
    121   virtual bool IsPinned(ash::LauncherID id) OVERRIDE;
    122 
    123   // Pins/unpins the specified id.
    124   virtual void TogglePinned(ash::LauncherID id) OVERRIDE;
    125 
    126   // Returns true if the specified item can be pinned or unpinned. Only apps can
    127   // be pinned.
    128   virtual bool IsPinnable(ash::LauncherID id) const OVERRIDE;
    129 
    130   // If there is no launcher item in the launcher for application |app_id|, one
    131   // gets created. The (existing or created) launcher items get then locked
    132   // against a users un-pinning removal.
    133   virtual void LockV1AppWithID(const std::string& app_id) OVERRIDE;
    134 
    135   // A previously locked launcher item of type |app_id| gets unlocked. If the
    136   // lock count reaches 0 and the item is not pinned it will go away.
    137   virtual void UnlockV1AppWithID(const std::string& app_id) OVERRIDE;
    138 
    139   // Requests that the launcher item controller specified by |id| open a new
    140   // instance of the app.  |event_flags| holds the flags of the event which
    141   // triggered this command.
    142   virtual void Launch(ash::LauncherID id, int event_flags) OVERRIDE;
    143 
    144   // Closes the specified item.
    145   virtual void Close(ash::LauncherID id) OVERRIDE;
    146 
    147   // Returns true if the specified item is open.
    148   virtual bool IsOpen(ash::LauncherID id) OVERRIDE;
    149 
    150   // Returns true if the specified item is for a platform app.
    151   virtual bool IsPlatformApp(ash::LauncherID id) OVERRIDE;
    152 
    153   // Opens a new instance of the application identified by |app_id|.
    154   // Used by the app-list, and by pinned-app launcher items.
    155   virtual void LaunchApp(const std::string& app_id, int event_flags) OVERRIDE;
    156 
    157   // If |app_id| is running, reactivates the app's most recently active window,
    158   // otherwise launches and activates the app.
    159   // Used by the app-list, and by pinned-app launcher items.
    160   virtual void ActivateApp(const std::string& app_id, int event_flags) OVERRIDE;
    161 
    162   // Returns the launch type of app for the specified id.
    163   virtual extensions::ExtensionPrefs::LaunchType GetLaunchType(
    164       ash::LauncherID id) OVERRIDE;
    165 
    166   // Returns the id of the app for the specified tab.
    167   virtual std::string GetAppID(content::WebContents* tab) OVERRIDE;
    168 
    169   virtual ash::LauncherID GetLauncherIDForAppID(
    170       const std::string& app_id) OVERRIDE;
    171   virtual std::string GetAppIDForLauncherID(ash::LauncherID id) OVERRIDE;
    172 
    173   // Set the image for a specific launcher item (e.g. when set by the app).
    174   virtual void SetLauncherItemImage(ash::LauncherID launcher_id,
    175                                     const gfx::ImageSkia& image) OVERRIDE;
    176 
    177   // Returns true if a pinned launcher item with given |app_id| could be found.
    178   virtual bool IsAppPinned(const std::string& app_id) OVERRIDE;
    179 
    180   // Pins an app with |app_id| to launcher. If there is a running instance in
    181   // launcher, the running instance is pinned. If there is no running instance,
    182   // a new launcher item is created and pinned.
    183   virtual void PinAppWithID(const std::string& app_id) OVERRIDE;
    184 
    185   // Updates the launche type of the app for the specified id to |launch_type|.
    186   virtual void SetLaunchType(
    187       ash::LauncherID id,
    188       extensions::ExtensionPrefs::LaunchType launch_type) OVERRIDE;
    189 
    190   // Unpins any app items whose id is |app_id|.
    191   virtual void UnpinAppsWithID(const std::string& app_id) OVERRIDE;
    192 
    193   // Returns true if the user is currently logged in as a guest.
    194   virtual bool IsLoggedInAsGuest() OVERRIDE;
    195 
    196   // Invoked when user clicks on button in the launcher and there is no last
    197   // used window (or CTRL is held with the click).
    198   virtual void CreateNewWindow() OVERRIDE;
    199 
    200   // Invoked when the user clicks on button in the launcher to create a new
    201   // incognito window.
    202   virtual void CreateNewIncognitoWindow() OVERRIDE;
    203 
    204   // Checks whether the user is allowed to pin apps. Pinning may be disallowed
    205   // by policy in case there is a pre-defined set of pinned apps.
    206   virtual bool CanPin() const OVERRIDE;
    207 
    208   // Updates the pinned pref state. The pinned state consists of a list pref.
    209   // Each item of the list is a dictionary. The key |kAppIDPath| gives the
    210   // id of the app.
    211   virtual void PersistPinnedState() OVERRIDE;
    212 
    213   virtual ash::LauncherModel* model() OVERRIDE;
    214 
    215   virtual Profile* profile() OVERRIDE;
    216 
    217   // Gets the shelf auto-hide behavior on |root_window|.
    218   virtual ash::ShelfAutoHideBehavior GetShelfAutoHideBehavior(
    219       aura::RootWindow* root_window) const OVERRIDE;
    220 
    221   // Returns |true| if the user is allowed to modify the shelf auto-hide
    222   // behavior on |root_window|.
    223   virtual bool CanUserModifyShelfAutoHideBehavior(
    224       aura::RootWindow* root_window) const OVERRIDE;
    225 
    226   // Toggles the shelf auto-hide behavior on |root_window|. Does nothing if the
    227   // user is not allowed to modify the auto-hide behavior.
    228   virtual void ToggleShelfAutoHideBehavior(
    229       aura::RootWindow* root_window) OVERRIDE;
    230 
    231   // The tab no longer represents its previously identified application.
    232   virtual void RemoveTabFromRunningApp(content::WebContents* tab,
    233                                        const std::string& app_id) OVERRIDE;
    234 
    235   // Notify the controller that the state of an non platform app's tabs
    236   // have changed,
    237   virtual void UpdateAppState(content::WebContents* contents,
    238                               AppState app_state) OVERRIDE;
    239 
    240   // Limits application refocusing to urls that match |url| for |id|.
    241   virtual void SetRefocusURLPatternForTest(ash::LauncherID id,
    242                                            const GURL& url) OVERRIDE;
    243 
    244   // Returns the extension identified by |app_id|.
    245   virtual const extensions::Extension* GetExtensionForAppID(
    246       const std::string& app_id) const OVERRIDE;
    247 
    248   // Activates a |window|. If |allow_minimize| is true and the system allows
    249   // it, the the window will get minimized instead.
    250   virtual void ActivateWindowOrMinimizeIfActive(ui::BaseWindow* window,
    251                                                 bool allow_minimize) OVERRIDE;
    252 
    253   // ash::LauncherDelegate overrides:
    254   virtual void ItemSelected(const ash::LauncherItem& item,
    255                            const ui::Event& event) OVERRIDE;
    256   virtual string16 GetTitle(const ash::LauncherItem& item) OVERRIDE;
    257   virtual ui::MenuModel* CreateContextMenu(
    258       const ash::LauncherItem& item, aura::RootWindow* root) OVERRIDE;
    259   virtual ash::LauncherMenuModel* CreateApplicationMenu(
    260       const ash::LauncherItem& item,
    261       int event_flags) OVERRIDE;
    262   virtual ash::LauncherID GetIDByWindow(aura::Window* window) OVERRIDE;
    263   virtual bool IsDraggable(const ash::LauncherItem& item) OVERRIDE;
    264   virtual bool ShouldShowTooltip(const ash::LauncherItem& item) OVERRIDE;
    265   virtual void OnLauncherCreated(ash::Launcher* launcher) OVERRIDE;
    266   virtual void OnLauncherDestroyed(ash::Launcher* launcher) OVERRIDE;
    267 
    268   // ash::LauncherModelObserver overrides:
    269   virtual void LauncherItemAdded(int index) OVERRIDE;
    270   virtual void LauncherItemRemoved(int index, ash::LauncherID id) OVERRIDE;
    271   virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
    272   virtual void LauncherItemChanged(int index,
    273                                    const ash::LauncherItem& old_item) OVERRIDE;
    274   virtual void LauncherStatusChanged() OVERRIDE;
    275 
    276   // content::NotificationObserver overrides:
    277   virtual void Observe(int type,
    278                        const content::NotificationSource& source,
    279                        const content::NotificationDetails& details) OVERRIDE;
    280 
    281   // ash::ShellObserver overrides:
    282   virtual void OnShelfAlignmentChanged(aura::RootWindow* root_window) OVERRIDE;
    283 
    284   // ash::DisplayController::Observer overrides:
    285   virtual void OnDisplayConfigurationChanging() OVERRIDE;
    286   virtual void OnDisplayConfigurationChanged() OVERRIDE;
    287 
    288   // PrefServiceSyncableObserver overrides:
    289   virtual void OnIsSyncingChanged() OVERRIDE;
    290 
    291   // AppSyncUIStateObserver overrides:
    292   virtual void OnAppSyncUIStatusChanged() OVERRIDE;
    293 
    294   // ExtensionEnableFlowDelegate overrides:
    295   virtual void ExtensionEnableFlowFinished() OVERRIDE;
    296   virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE;
    297 
    298   // extensions::AppIconLoader overrides:
    299   virtual void SetAppImage(const std::string& app_id,
    300                            const gfx::ImageSkia& image) OVERRIDE;
    301 
    302   // ash::ShelfLayoutManagerObserver overrides:
    303   virtual void OnAutoHideBehaviorChanged(
    304       aura::RootWindow* root_window,
    305       ash::ShelfAutoHideBehavior new_behavior) OVERRIDE;
    306 
    307  protected:
    308   // ChromeLauncherController overrides:
    309 
    310   // Creates a new app shortcut item and controller on the launcher at |index|.
    311   // Use kInsertItemAtEnd to add a shortcut as the last item.
    312   virtual ash::LauncherID CreateAppShortcutLauncherItem(
    313       const std::string& app_id,
    314       int index) OVERRIDE;
    315 
    316   // Sets the AppTabHelper/AppIconLoader, taking ownership of the helper class.
    317   // These are intended for testing.
    318   virtual void SetAppTabHelperForTest(AppTabHelper* helper) OVERRIDE;
    319   virtual void SetAppIconLoaderForTest(
    320       extensions::AppIconLoader* loader) OVERRIDE;
    321   virtual const std::string& GetAppIdFromLauncherIdForTest(
    322       ash::LauncherID id) OVERRIDE;
    323 
    324  private:
    325   friend class ChromeLauncherControllerPerBrowserTest;
    326 
    327   typedef std::map<ash::LauncherID, LauncherItemController*>
    328           IDToItemControllerMap;
    329   typedef std::list<content::WebContents*> WebContentsList;
    330   typedef std::map<std::string, WebContentsList> AppIDToWebContentsListMap;
    331   typedef std::map<content::WebContents*, std::string> WebContentsToAppIDMap;
    332 
    333   // Returns the profile used for new windows.
    334   Profile* GetProfileForNewWindows();
    335 
    336   // Invoked when the associated browser or app is closed.
    337   void LauncherItemClosed(ash::LauncherID id);
    338 
    339   // Internal helpers for pinning and unpinning that handle both
    340   // client-triggered and internal pinning operations.
    341   void DoPinAppWithID(const std::string& app_id);
    342   void DoUnpinAppsWithID(const std::string& app_id);
    343 
    344   // Re-syncs launcher model with prefs::kPinnedLauncherApps.
    345   void UpdateAppLaunchersFromPref();
    346 
    347   // Persists the shelf auto-hide behavior to prefs.
    348   void SetShelfAutoHideBehaviorPrefs(ash::ShelfAutoHideBehavior behavior,
    349                                      aura::RootWindow* root_window);
    350 
    351   // Sets the shelf auto-hide behavior from prefs.
    352   void SetShelfAutoHideBehaviorFromPrefs();
    353 
    354   // Sets the shelf alignment from prefs.
    355   void SetShelfAlignmentFromPrefs();
    356 
    357   // Sets both of auto-hide behavior and alignment from prefs.
    358   void SetShelfBehaviorsFromPrefs();
    359 
    360   // Returns the most recently active WebContents for an app.
    361   content::WebContents* GetLastActiveWebContents(const std::string& app_id);
    362 
    363   // Creates an app launcher to insert at |index|. Note that |index| may be
    364   // adjusted by the model to meet ordering constraints.
    365   ash::LauncherID InsertAppLauncherItem(
    366       LauncherItemController* controller,
    367       const std::string& app_id,
    368       ash::LauncherItemStatus status,
    369       int index);
    370 
    371   bool HasItemController(ash::LauncherID id) const;
    372 
    373   // Create LauncherItem for Browser Shortcut.
    374   ash::LauncherID CreateBrowserShortcutLauncherItem();
    375 
    376   // Update browser shortcut's index.
    377   void SetChromeIconIndexToPref(int index);
    378 
    379   // Get browser shortcut's index from pref.
    380   int GetChromeIconIndexFromPref() const;
    381 
    382   // Invoked when browser shortcut is clicked.
    383   void BrowserShortcutClicked(int event_flags);
    384 
    385   // Move an item internally (ignoring pinned state changes) from |index| to
    386   // |target_index|.
    387   void MoveItemWithoutPinnedStateChangeNotification(int source_index,
    388                                                     int target_index);
    389 
    390   ash::LauncherModel* model_;
    391 
    392   // Profile used for prefs and loading extensions. This is NOT necessarily the
    393   // profile new windows are created with.
    394   Profile* profile_;
    395 
    396   IDToItemControllerMap id_to_item_controller_map_;
    397 
    398   // Maintains activation order of web contents for each app.
    399   AppIDToWebContentsListMap app_id_to_web_contents_list_;
    400 
    401   // Direct access to app_id for a web contents.
    402   WebContentsToAppIDMap web_contents_to_app_id_;
    403 
    404   // Used to track shell windows.
    405   scoped_ptr<ShellWindowLauncherController> shell_window_controller_;
    406 
    407   // Used to get app info for tabs.
    408   scoped_ptr<AppTabHelper> app_tab_helper_;
    409 
    410   // Used to load the image for an app item.
    411   scoped_ptr<extensions::AppIconLoader> app_icon_loader_;
    412 
    413   content::NotificationRegistrar notification_registrar_;
    414 
    415   PrefChangeRegistrar pref_change_registrar_;
    416 
    417   AppSyncUIState* app_sync_ui_state_;
    418 
    419   scoped_ptr<ExtensionEnableFlow> extension_enable_flow_;
    420 
    421   // Launchers that are currently being observed.
    422   std::set<ash::Launcher*> launchers_;
    423 
    424   // If true, incoming pinned state changes should be ignored.
    425   bool ignore_persist_pinned_state_change_;
    426 
    427   DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerPerBrowser);
    428 };
    429 
    430 #endif  // CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_PER_BROWSER_H_
    431