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 37class AppSyncUIState; 38class Browser; 39class BrowserLauncherItemControllerTest; 40class BrowserShortcutLauncherItemController; 41class ExtensionEnableFlow; 42class LauncherItemController; 43class Profile; 44class TabContents; 45 46namespace ash { 47class LauncherModel; 48} 49 50namespace aura { 51class Window; 52} 53 54namespace content { 55class WebContents; 56} 57 58namespace ui { 59class 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. 71class 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