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