1 // Copyright 2013 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.
5 #ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_H_
14 #include "ash/display/display_controller.h"
15 #include "ash/launcher/launcher_delegate.h"
16 #include "ash/launcher/launcher_item_delegate.h"
17 #include "ash/launcher/launcher_model_observer.h"
18 #include "ash/launcher/launcher_types.h"
19 #include "ash/shelf/shelf_layout_manager_observer.h"
20 #include "ash/shelf/shelf_types.h"
21 #include "ash/shell_observer.h"
22 #include "base/basictypes.h"
23 #include "base/compiler_specific.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/memory/scoped_vector.h"
26 #include "base/prefs/pref_change_registrar.h"
27 #include "chrome/browser/extensions/app_icon_loader.h"
28 #include "chrome/browser/extensions/extension_prefs.h"
29 #include "chrome/browser/prefs/pref_service_syncable_observer.h"
30 #include "chrome/browser/ui/ash/app_sync_ui_state_observer.h"
31 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
32 #include "chrome/browser/ui/ash/launcher/chrome_launcher_types.h"
33 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
34 #include "content/public/browser/notification_observer.h"
35 #include "ui/aura/window_observer.h"
39 class BrowserShortcutLauncherItemController;
40 class BrowserStatusMonitor;
41 class ExtensionEnableFlow;
43 class LauncherItemController;
45 class ShellWindowLauncherController;
49 class LauncherItemDelegateManager;
58 class NotificationRegistrar;
66 // A list of the elements which makes up a simple menu description.
67 typedef ScopedVector<ChromeLauncherAppMenuItem> ChromeLauncherAppMenuItems;
69 // A class which needs to be overwritten dependent on the used OS to moitor
71 class ChromeLauncherControllerUserSwitchObserver {
73 ChromeLauncherControllerUserSwitchObserver() {}
74 virtual ~ChromeLauncherControllerUserSwitchObserver() {}
78 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerUserSwitchObserver);
81 // ChromeLauncherController manages the launcher items needed for content
82 // windows. Launcher items have a type, an optional app id, and a controller.
83 // This incarnation groups running tabs/windows in application specific lists.
84 // * Browser app windows have BrowserLauncherItemController, owned by the
85 // BrowserView instance.
86 // * App shell windows have ShellWindowLauncherItemController, owned by
87 // ShellWindowLauncherController.
88 // * Shortcuts have no LauncherItemController.
89 class ChromeLauncherController : public ash::LauncherDelegate,
90 public ash::LauncherModelObserver,
91 public ash::ShellObserver,
92 public ash::DisplayController::Observer,
93 public content::NotificationObserver,
94 public extensions::AppIconLoader::Delegate,
95 public PrefServiceSyncableObserver,
96 public AppSyncUIStateObserver,
97 public ExtensionEnableFlowDelegate,
98 public ash::ShelfLayoutManagerObserver {
100 // Indicates if a launcher item is incognito or not.
101 enum IncognitoState {
106 // Used to update the state of non plaform apps, as web contents change.
109 APP_STATE_WINDOW_ACTIVE,
114 // Mockable interface to get app ids from tabs.
117 virtual ~AppTabHelper() {}
119 // Returns the app id of the specified tab, or an empty string if there is
120 // no app. All known profiles will be queried for this.
121 virtual std::string GetAppID(content::WebContents* tab) = 0;
123 // Returns true if |id| is valid for the currently active profile.
124 // Used during restore to ignore no longer valid extensions.
125 // Note that already running applications are ignored by the restore
127 virtual bool IsValidIDForCurrentUser(const std::string& id) = 0;
129 // Sets the currently active profile for the usage of |GetAppID|.
130 virtual void SetCurrentUser(Profile* profile) = 0;
133 ChromeLauncherController(Profile* profile, ash::LauncherModel* model);
134 virtual ~ChromeLauncherController();
136 // Initializes this ChromeLauncherController.
139 // Creates an instance.
140 static ChromeLauncherController* CreateInstance(Profile* profile,
141 ash::LauncherModel* model);
143 // Returns the single ChromeLauncherController instance.
144 static ChromeLauncherController* instance() { return instance_; }
146 // Creates a new app item on the launcher for |controller|.
147 ash::LauncherID CreateAppLauncherItem(LauncherItemController* controller,
148 const std::string& app_id,
149 ash::LauncherItemStatus status);
151 // Updates the running status of an item. It will also update the status of
152 // browsers launcher item if needed.
153 void SetItemStatus(ash::LauncherID id, ash::LauncherItemStatus status);
155 // Updates the controller associated with id (which should be a shortcut).
156 // |controller| remains owned by caller.
157 void SetItemController(ash::LauncherID id,
158 LauncherItemController* controller);
160 // Closes or unpins the launcher item.
161 void CloseLauncherItem(ash::LauncherID id);
163 // Pins the specified id. Currently only supports platform apps.
164 void Pin(ash::LauncherID id);
166 // Unpins the specified id, closing if not running.
167 void Unpin(ash::LauncherID id);
169 // Returns true if the item identified by |id| is pinned.
170 bool IsPinned(ash::LauncherID id);
172 // Pins/unpins the specified id.
173 void TogglePinned(ash::LauncherID id);
175 // Returns true if the specified item can be pinned or unpinned. Only apps can
177 bool IsPinnable(ash::LauncherID id) const;
179 // If there is no launcher item in the launcher for application |app_id|, one
180 // gets created. The (existing or created) launcher items get then locked
181 // against a users un-pinning removal.
182 void LockV1AppWithID(const std::string& app_id);
184 // A previously locked launcher item of type |app_id| gets unlocked. If the
185 // lock count reaches 0 and the item is not pinned it will go away.
186 void UnlockV1AppWithID(const std::string& app_id);
188 // Requests that the launcher item controller specified by |id| open a new
189 // instance of the app. |event_flags| holds the flags of the event which
190 // triggered this command.
191 void Launch(ash::LauncherID id, int event_flags);
193 // Closes the specified item.
194 void Close(ash::LauncherID id);
196 // Returns true if the specified item is open.
197 bool IsOpen(ash::LauncherID id);
199 // Returns true if the specified item is for a platform app.
200 bool IsPlatformApp(ash::LauncherID id);
202 // Opens a new instance of the application identified by |app_id|.
203 // Used by the app-list, and by pinned-app launcher items.
204 void LaunchApp(const std::string& app_id,
205 ash::LaunchSource source,
208 // If |app_id| is running, reactivates the app's most recently active window,
209 // otherwise launches and activates the app.
210 // Used by the app-list, and by pinned-app launcher items.
211 void ActivateApp(const std::string& app_id,
212 ash::LaunchSource source,
215 // Returns the launch type of app for the specified id.
216 extensions::ExtensionPrefs::LaunchType GetLaunchType(ash::LauncherID id);
218 // Set the image for a specific launcher item (e.g. when set by the app).
219 void SetLauncherItemImage(ash::LauncherID launcher_id,
220 const gfx::ImageSkia& image);
222 // Find out if the given application |id| is a windowed app item and not a
223 // pinned item in the launcher.
224 bool IsWindowedAppInLauncher(const std::string& app_id);
226 // Updates the launche type of the app for the specified id to |launch_type|.
227 void SetLaunchType(ash::LauncherID id,
228 extensions::ExtensionPrefs::LaunchType launch_type);
230 // Returns true if the user is currently logged in as a guest.
231 // Makes virtual for unittest in LauncherContextMenuTest.
232 virtual bool IsLoggedInAsGuest();
234 // Invoked when user clicks on button in the launcher and there is no last
235 // used window (or CTRL is held with the click).
236 void CreateNewWindow();
238 // Invoked when the user clicks on button in the launcher to create a new
240 void CreateNewIncognitoWindow();
242 // Updates the pinned pref state. The pinned state consists of a list pref.
243 // Each item of the list is a dictionary. The key |kAppIDPath| gives the
245 void PersistPinnedState();
247 ash::LauncherModel* model();
249 // Accessor to the currently loaded profile. Note that in multi profile use
250 // cases this might change over time.
253 // Gets the shelf auto-hide behavior on |root_window|.
254 ash::ShelfAutoHideBehavior GetShelfAutoHideBehavior(
255 aura::Window* root_window) const;
257 // Returns |true| if the user is allowed to modify the shelf auto-hide
258 // behavior on |root_window|.
259 bool CanUserModifyShelfAutoHideBehavior(aura::Window* root_window) const;
261 // Toggles the shelf auto-hide behavior on |root_window|. Does nothing if the
262 // user is not allowed to modify the auto-hide behavior.
263 void ToggleShelfAutoHideBehavior(aura::Window* root_window);
265 // The tab no longer represents its previously identified application.
266 void RemoveTabFromRunningApp(content::WebContents* tab,
267 const std::string& app_id);
269 // Notify the controller that the state of an non platform app's tabs
271 void UpdateAppState(content::WebContents* contents, AppState app_state);
273 // Limits application refocusing to urls that match |url| for |id|.
274 void SetRefocusURLPatternForTest(ash::LauncherID id, const GURL& url);
276 // Returns the extension identified by |app_id|.
277 const extensions::Extension* GetExtensionForAppID(
278 const std::string& app_id) const;
280 // Activates a |window|. If |allow_minimize| is true and the system allows
281 // it, the the window will get minimized instead.
282 void ActivateWindowOrMinimizeIfActive(ui::BaseWindow* window,
283 bool allow_minimize);
285 // ash::LauncherDelegate overrides:
286 virtual ash::LauncherID GetIDByWindow(aura::Window* window) OVERRIDE;
287 virtual void OnLauncherCreated(ash::Launcher* launcher) OVERRIDE;
288 virtual void OnLauncherDestroyed(ash::Launcher* launcher) OVERRIDE;
289 virtual ash::LauncherID GetLauncherIDForAppID(
290 const std::string& app_id) OVERRIDE;
291 virtual const std::string& GetAppIDForLauncherID(ash::LauncherID id) OVERRIDE;
292 virtual void PinAppWithID(const std::string& app_id) OVERRIDE;
293 virtual bool IsAppPinned(const std::string& app_id) OVERRIDE;
294 virtual bool CanPin() const OVERRIDE;
295 virtual void UnpinAppWithID(const std::string& app_id) OVERRIDE;
297 // ash::LauncherModelObserver overrides:
298 virtual void LauncherItemAdded(int index) OVERRIDE;
299 virtual void LauncherItemRemoved(int index, ash::LauncherID id) OVERRIDE;
300 virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
301 virtual void LauncherItemChanged(int index,
302 const ash::LauncherItem& old_item) OVERRIDE;
303 virtual void LauncherStatusChanged() OVERRIDE;
305 // content::NotificationObserver overrides:
306 virtual void Observe(int type,
307 const content::NotificationSource& source,
308 const content::NotificationDetails& details) OVERRIDE;
310 // ash::ShellObserver overrides:
311 virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE;
313 // ash::DisplayController::Observer overrides:
314 virtual void OnDisplayConfigurationChanging() OVERRIDE;
315 virtual void OnDisplayConfigurationChanged() OVERRIDE;
317 // PrefServiceSyncableObserver overrides:
318 virtual void OnIsSyncingChanged() OVERRIDE;
320 // AppSyncUIStateObserver overrides:
321 virtual void OnAppSyncUIStatusChanged() OVERRIDE;
323 // ExtensionEnableFlowDelegate overrides:
324 virtual void ExtensionEnableFlowFinished() OVERRIDE;
325 virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE;
327 // extensions::AppIconLoader overrides:
328 virtual void SetAppImage(const std::string& app_id,
329 const gfx::ImageSkia& image) OVERRIDE;
331 // ash::ShelfLayoutManagerObserver overrides:
332 virtual void OnAutoHideBehaviorChanged(
333 aura::Window* root_window,
334 ash::ShelfAutoHideBehavior new_behavior) OVERRIDE;
336 // Called when the active user has changed.
337 void ActiveUserChanged(const std::string& user_email);
339 // Called when a user got added to the session.
340 void AdditionalUserAddedToSession(Profile* profile);
342 // Get the list of all running incarnations of this item.
343 // |event_flags| specifies the flags which were set by the event which
344 // triggered this menu generation. It can be used to generate different lists.
345 ChromeLauncherAppMenuItems GetApplicationList(const ash::LauncherItem& item,
348 // Get the list of all tabs which belong to a certain application type.
349 std::vector<content::WebContents*> GetV1ApplicationsFromAppId(
352 // Activates a specified shell application.
353 void ActivateShellApp(const std::string& app_id, int index);
355 // Checks if a given |web_contents| is known to be associated with an
356 // application of type |app_id|.
357 bool IsWebContentHandledByApplication(content::WebContents* web_contents,
358 const std::string& app_id);
360 // Check if the gMail app is loaded and it can handle the given web content.
361 // This special treatment is required to address crbug.com/234268.
362 bool ContentCanBeHandledByGmailApp(content::WebContents* web_contents);
364 // Get the favicon for the application list entry for |web_contents|.
365 // Note that for incognito windows the incognito icon will be returned.
366 // If |web_contents| has not loaded, returns the default favicon.
367 gfx::Image GetAppListIcon(content::WebContents* web_contents) const;
369 // Get the title for the applicatoin list entry for |web_contents|.
370 // If |web_contents| has not loaded, returns "Net Tab".
371 string16 GetAppListTitle(content::WebContents* web_contents) const;
373 // Returns the LauncherItemController of BrowserShortcut.
374 BrowserShortcutLauncherItemController*
375 GetBrowserShortcutLauncherItemController();
377 LauncherItemController* GetLauncherItemController(const ash::LauncherID id);
379 // Returns true if |browser| is owned by the active user.
380 bool IsBrowserFromActiveUser(Browser* browser);
382 // Access to the BrowserStatusMonitor for tests.
383 BrowserStatusMonitor* browser_status_monitor_for_test() {
384 return browser_status_monitor_.get();
388 // Creates a new app shortcut item and controller on the launcher at |index|.
389 // Use kInsertItemAtEnd to add a shortcut as the last item.
390 ash::LauncherID CreateAppShortcutLauncherItem(const std::string& app_id,
393 // Sets the AppTabHelper/AppIconLoader, taking ownership of the helper class.
394 // These are intended for testing.
395 void SetAppTabHelperForTest(AppTabHelper* helper);
396 void SetAppIconLoaderForTest(extensions::AppIconLoader* loader);
397 const std::string& GetAppIdFromLauncherIdForTest(ash::LauncherID id);
399 // Sets the ash::LauncherItemDelegateManager only for unittests and doesn't
400 // take an ownership of it.
401 void SetLauncherItemDelegateManagerForTest(
402 ash::LauncherItemDelegateManager* manager);
405 friend class ChromeLauncherControllerTest;
406 friend class LauncherAppBrowserTest;
407 friend class LauncherPlatformAppBrowserTest;
409 typedef std::map<ash::LauncherID, LauncherItemController*>
410 IDToItemControllerMap;
411 typedef std::list<content::WebContents*> WebContentsList;
412 typedef std::map<std::string, WebContentsList> AppIDToWebContentsListMap;
413 typedef std::map<content::WebContents*, std::string> WebContentsToAppIDMap;
415 // Creates a new app shortcut item and controller on the launcher at |index|.
416 // Use kInsertItemAtEnd to add a shortcut as the last item.
417 ash::LauncherID CreateAppShortcutLauncherItemWithType(
418 const std::string& app_id,
420 ash::LauncherItemType launcher_item_type);
422 // Returns the profile used for new windows.
423 Profile* GetProfileForNewWindows();
425 // Invoked when the associated browser or app is closed.
426 void LauncherItemClosed(ash::LauncherID id);
428 // Internal helpers for pinning and unpinning that handle both
429 // client-triggered and internal pinning operations.
430 void DoPinAppWithID(const std::string& app_id);
431 void DoUnpinAppWithID(const std::string& app_id);
433 // Pin a running app with |launcher_id| internally to |index|. It returns
434 // the index where the item was pinned.
435 int PinRunningAppInternal(int index, ash::LauncherID launcher_id);
437 // Unpin a locked application. This is an internal call which converts the
438 // model type of the given app index from a shortcut into an unpinned running
440 void UnpinRunningAppInternal(int index);
442 // Re-syncs launcher model with prefs::kPinnedLauncherApps.
443 void UpdateAppLaunchersFromPref();
445 // Persists the shelf auto-hide behavior to prefs.
446 void SetShelfAutoHideBehaviorPrefs(ash::ShelfAutoHideBehavior behavior,
447 aura::Window* root_window);
449 // Sets the shelf auto-hide behavior from prefs.
450 void SetShelfAutoHideBehaviorFromPrefs();
452 // Sets the shelf alignment from prefs.
453 void SetShelfAlignmentFromPrefs();
455 // Sets both of auto-hide behavior and alignment from prefs.
456 void SetShelfBehaviorsFromPrefs();
458 // Returns the most recently active web contents for an app.
459 content::WebContents* GetLastActiveWebContents(const std::string& app_id);
461 // Creates an app launcher to insert at |index|. Note that |index| may be
462 // adjusted by the model to meet ordering constraints.
463 // The |launcher_item_type| will be set into the LauncherModel.
464 ash::LauncherID InsertAppLauncherItem(
465 LauncherItemController* controller,
466 const std::string& app_id,
467 ash::LauncherItemStatus status,
469 ash::LauncherItemType launcher_item_type);
471 bool HasItemController(ash::LauncherID id) const;
473 // Enumerate all Web contents which match a given shortcut |controller|.
474 std::vector<content::WebContents*> GetV1ApplicationsFromController(
475 LauncherItemController* controller);
477 // Create LauncherItem for Browser Shortcut.
478 ash::LauncherID CreateBrowserShortcutLauncherItem();
480 // Check if the given |web_contents| is in incognito mode.
481 bool IsIncognito(const content::WebContents* web_contents) const;
483 // Update browser shortcut's index.
484 void PersistChromeItemIndex(int index);
486 // Get browser shortcut's index from pref.
487 int GetChromeIconIndexFromPref() const;
489 // Depending on the provided flags, move either the chrome icon, the app icon
490 // or none to the given |target_index|. The provided |chrome_index| and
491 // |app_list_index| locations will get adjusted within this call to finalize
492 // the action and to make sure that the other item can still be moved
493 // afterwards (index adjustments).
494 void MoveChromeOrApplistToFinalPosition(
499 int* app_list_index);
501 // Finds the index of where to insert the next item.
502 int FindInsertionPoint(bool is_app_list);
504 // Get the browser shortcut's index in the shelf using the current's systems
505 // configuration of pinned and known (but not running) apps.
506 int GetChromeIconIndexForCreation();
508 // Get the list of pinned programs from the preferences.
509 std::vector<std::string> GetListOfPinnedAppsAndBrowser();
511 // Close all windowed V1 applications of a certain extension which was already
513 void CloseWindowedAppsFromRemovedExtension(const std::string& app_id);
515 // Set LauncherItemDelegate |item_delegate| for |id| and take an ownership.
516 // TODO(simon.hong81): Make this take a scoped_ptr of |item_delegate|.
517 void SetLauncherItemDelegate(ash::LauncherID id,
518 ash::LauncherItemDelegate* item_delegate);
520 // Attach to a specific profile.
521 void AttachProfile(Profile* proifile);
523 // Forget the current profile to allow attaching to a new one.
524 void ReleaseProfile();
526 // Update the state of all V1 shortcut launcher items after a user switch.
527 void UpdateV1AppStatesAfterUserSwitch();
529 static ChromeLauncherController* instance_;
531 ash::LauncherModel* model_;
533 ash::LauncherItemDelegateManager* item_delegate_manager_;
535 // Profile used for prefs and loading extensions. This is NOT necessarily the
536 // profile new windows are created with.
539 IDToItemControllerMap id_to_item_controller_map_;
541 // Maintains activation order of web contents for each app.
542 AppIDToWebContentsListMap app_id_to_web_contents_list_;
544 // Direct access to app_id for a web contents.
545 WebContentsToAppIDMap web_contents_to_app_id_;
547 // Used to track shell windows.
548 scoped_ptr<ShellWindowLauncherController> shell_window_controller_;
550 // Used to get app info for tabs.
551 scoped_ptr<AppTabHelper> app_tab_helper_;
553 // Used to load the image for an app item.
554 scoped_ptr<extensions::AppIconLoader> app_icon_loader_;
556 content::NotificationRegistrar notification_registrar_;
558 PrefChangeRegistrar pref_change_registrar_;
560 AppSyncUIState* app_sync_ui_state_;
562 scoped_ptr<ExtensionEnableFlow> extension_enable_flow_;
564 // Launchers that are currently being observed.
565 std::set<ash::Launcher*> launchers_;
567 // The owned browser status monitor.
568 scoped_ptr<BrowserStatusMonitor> browser_status_monitor_;
570 // A special observer class to detect user switches.
571 scoped_ptr<ChromeLauncherControllerUserSwitchObserver> user_switch_observer_;
573 // If true, incoming pinned state changes should be ignored.
574 bool ignore_persist_pinned_state_change_;
576 // True if each user has an own desktop.
577 bool multi_profile_desktop_separation_;
579 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherController);
582 #endif // CHROME_BROWSER_UI_ASH_LAUNCHER_CHROME_LAUNCHER_CONTROLLER_H_