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. 4 5 #ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_CHROMEOS_H_ 6 #define CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_CHROMEOS_H_ 7 8 #include <map> 9 #include <string> 10 11 #include "ash/session/session_state_observer.h" 12 #include "base/compiler_specific.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/observer_list.h" 15 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" 16 #include "content/public/browser/notification_observer.h" 17 #include "content/public/browser/notification_registrar.h" 18 #include "ui/aura/window_observer.h" 19 #include "ui/wm/core/transient_window_observer.h" 20 21 class Browser; 22 class MultiUserNotificationBlockerChromeOS; 23 class MultiUserNotificationBlockerChromeOSTest; 24 25 namespace content { 26 class BrowserContext; 27 } 28 29 namespace aura { 30 class Window; 31 } // namespace aura 32 33 namespace ash { 34 namespace test { 35 class MultiUserWindowManagerChromeOSTest; 36 } // namespace test 37 } // namespace ash 38 39 namespace chrome { 40 41 class AppObserver; 42 class UserSwichAnimatorChromeOS; 43 44 // This ChromeOS implementation of the MultiUserWindowManager interface is 45 // detecting app and browser creations, tagging their windows automatically and 46 // using (currently) show and hide to make the owned windows visible - or not. 47 // If it becomes necessary, the function |SetWindowVisibility| can be 48 // overwritten to match new ways of doing this. 49 // Note: 50 // - aura::Window::Hide() is currently hiding the window and all owned transient 51 // children. However aura::Window::Show() is only showing the window itself. 52 // To address that, all transient children (and their children) are remembered 53 // in |transient_window_to_visibility_| and monitored to keep track of the 54 // visibility changes from the owning user. This way the visibility can be 55 // changed back to its requested state upon showing by us - or when the window 56 // gets detached from its current owning parent. 57 class MultiUserWindowManagerChromeOS 58 : public MultiUserWindowManager, 59 public ash::SessionStateObserver, 60 public aura::WindowObserver, 61 public content::NotificationObserver, 62 public wm::TransientWindowObserver { 63 public: 64 // The speed which should be used to perform animations. 65 enum AnimationSpeed { 66 ANIMATION_SPEED_NORMAL, // The normal animation speed. 67 ANIMATION_SPEED_FAST, // Unit test speed which test animations. 68 ANIMATION_SPEED_DISABLED // Unit tests which do not require animations. 69 }; 70 71 // Create the manager and use |active_user_id| as the active user. 72 explicit MultiUserWindowManagerChromeOS(const std::string& active_user_id); 73 virtual ~MultiUserWindowManagerChromeOS(); 74 75 // MultiUserWindowManager overrides: 76 virtual void SetWindowOwner( 77 aura::Window* window, const std::string& user_id) OVERRIDE; 78 virtual const std::string& GetWindowOwner( 79 aura::Window* window) const OVERRIDE; 80 virtual void ShowWindowForUser( 81 aura::Window* window, const std::string& user_id) OVERRIDE; 82 virtual bool AreWindowsSharedAmongUsers() const OVERRIDE; 83 virtual void GetOwnersOfVisibleWindows( 84 std::set<std::string>* user_ids) const OVERRIDE; 85 virtual bool IsWindowOnDesktopOfUser( 86 aura::Window* window, 87 const std::string& user_id) const OVERRIDE; 88 virtual const std::string& GetUserPresentingWindow( 89 aura::Window* window) const OVERRIDE; 90 virtual void AddUser(content::BrowserContext* context) OVERRIDE; 91 virtual void AddObserver(Observer* observer) OVERRIDE; 92 virtual void RemoveObserver(Observer* observer) OVERRIDE; 93 94 // SessionStateObserver overrides: 95 virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE; 96 97 // WindowObserver overrides: 98 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; 99 virtual void OnWindowVisibilityChanging(aura::Window* window, 100 bool visible) OVERRIDE; 101 virtual void OnWindowVisibilityChanged(aura::Window* window, 102 bool visible) OVERRIDE; 103 104 // TransientWindowObserver overrides: 105 virtual void OnTransientChildAdded(aura::Window* window, 106 aura::Window* transient) OVERRIDE; 107 virtual void OnTransientChildRemoved(aura::Window* window, 108 aura::Window* transient) OVERRIDE; 109 110 // content::NotificationObserver overrides: 111 virtual void Observe(int type, 112 const content::NotificationSource& source, 113 const content::NotificationDetails& details) OVERRIDE; 114 115 // Disable any animations for unit tests. 116 void SetAnimationSpeedForTest(AnimationSpeed speed); 117 118 // Returns true when a user switch animation is running. For unit tests. 119 bool IsAnimationRunningForTest(); 120 121 // Returns the current user for unit tests. 122 const std::string& GetCurrentUserForTest() const; 123 124 protected: 125 friend class UserSwichAnimatorChromeOS; 126 127 class WindowEntry { 128 public: 129 explicit WindowEntry(const std::string& user_id) 130 : owner_(user_id), 131 show_for_user_(user_id), 132 show_(true) {} 133 virtual ~WindowEntry() {} 134 135 // Returns the owner of this window. This cannot be changed. 136 const std::string& owner() const { return owner_; } 137 138 // Returns the user for which this should be shown. 139 const std::string& show_for_user() const { return show_for_user_; } 140 141 // Returns if the window should be shown for the "show user" or not. 142 bool show() const { return show_; } 143 144 // Set the user which will display the window on the owned desktop. If 145 // an empty user id gets passed the owner will be used. 146 void set_show_for_user(const std::string& user_id) { 147 show_for_user_ = user_id.empty() ? owner_ : user_id; 148 } 149 150 // Sets if the window gets shown for the active user or not. 151 void set_show(bool show) { show_ = show; } 152 153 private: 154 // The user id of the owner of this window. 155 const std::string owner_; 156 157 // The user id of the user on which desktop the window gets shown. 158 std::string show_for_user_; 159 160 // True if the window should be visible for the user which shows the window. 161 bool show_; 162 163 DISALLOW_COPY_AND_ASSIGN(WindowEntry); 164 }; 165 166 typedef std::map<aura::Window*, WindowEntry*> WindowToEntryMap; 167 168 // Show a window for a user without switching the user. 169 // Returns true when the window moved to a new desktop. 170 bool ShowWindowForUserIntern(aura::Window* window, 171 const std::string& user_id); 172 173 // Show / hide the given window. Note: By not doing this within the functions, 174 // this allows to either switching to different ways to show/hide and / or to 175 // distinguish state changes performed by this class vs. state changes 176 // performed by the others. Note furthermore that system modal dialogs will 177 // not get hidden. We will switch instead to the owners desktop. 178 // The |animation_time_in_ms| is the time the animation should take. Set to 0 179 // if it should get set instantly. 180 void SetWindowVisibility(aura::Window* window, 181 bool visible, 182 int animation_time_in_ms); 183 184 const WindowToEntryMap& window_to_entry() { return window_to_entry_; } 185 MultiUserNotificationBlockerChromeOS* notification_blocker() { 186 return notification_blocker_.get(); 187 } 188 189 private: 190 friend class ::MultiUserNotificationBlockerChromeOSTest; 191 friend class ash::test::MultiUserWindowManagerChromeOSTest; 192 193 typedef std::map<std::string, AppObserver*> UserIDToAppWindowObserver; 194 typedef std::map<aura::Window*, bool> TransientWindowToVisibility; 195 196 // Add a browser window to the system so that the owner can be remembered. 197 void AddBrowserWindow(Browser* browser); 198 199 // Show the window and its transient children. However - if a transient child 200 // was turned invisible by some other operation, it will stay invisible. 201 // Use the given |animation_time_in_ms| for transitioning. 202 void ShowWithTransientChildrenRecursive(aura::Window* window, 203 int animation_time_in_ms); 204 205 // Find the first owned window in the chain. 206 // Returns NULL when the window itself is owned. 207 aura::Window* GetOwningWindowInTransientChain(aura::Window* window) const; 208 209 // A |window| and its children were attached as transient children to an 210 // |owning_parent| and need to be registered. Note that the |owning_parent| 211 // itself will not be registered, but its children will. 212 void AddTransientOwnerRecursive(aura::Window* window, 213 aura::Window* owning_parent); 214 215 // A window and its children were removed from its parent and can be 216 // unregistered. 217 void RemoveTransientOwnerRecursive(aura::Window* window); 218 219 // Animate a |window| to be |visible| in |animation_time_in_ms|. 220 void SetWindowVisible(aura::Window* window, 221 bool visible, 222 int aimation_time_in_ms); 223 224 // Get the animation time in milliseconds dependent on the |AnimationSpeed| 225 // from the passed |default_time_in_ms|. 226 int GetAdjustedAnimationTimeInMS(int default_time_in_ms) const; 227 228 // A lookup to see to which user the given window belongs to, where and if it 229 // should get shown. 230 WindowToEntryMap window_to_entry_; 231 232 // A list of all known users and their app window observers. 233 UserIDToAppWindowObserver user_id_to_app_observer_; 234 235 // An observer list to be notified upon window owner changes. 236 ObserverList<Observer> observers_; 237 238 // A map which remembers for owned transient windows their own visibility. 239 TransientWindowToVisibility transient_window_to_visibility_; 240 241 // The currently selected active user. It is used to find the proper 242 // visibility state in various cases. The state is stored here instead of 243 // being read from the user manager to be in sync while a switch occurs. 244 std::string current_user_id_; 245 246 // The blocker which controls the desktop notification visibility based on the 247 // current multi-user status. 248 scoped_ptr<MultiUserNotificationBlockerChromeOS> notification_blocker_; 249 250 // The notification registrar to track the creation of browser windows. 251 content::NotificationRegistrar registrar_; 252 253 // Suppress changes to the visibility flag while we are changing it ourselves. 254 bool suppress_visibility_changes_; 255 256 // Caching the current multi profile mode since the detection which mode is 257 // used is quite expensive. 258 static MultiProfileMode multi_user_mode_; 259 260 // The speed which is used to perform any animations. 261 AnimationSpeed animation_speed_; 262 263 // The animation between users. 264 scoped_ptr<UserSwichAnimatorChromeOS> animation_; 265 266 DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerChromeOS); 267 }; 268 269 } // namespace chrome 270 271 #endif // CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_CHROMEOS_H_ 272