// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_WINDOW_MANAGER_H_ #define CHROME_BROWSER_UI_ASH_MULTI_USER_WINDOW_MANAGER_H_ #include #include #include "ash/session_state_observer.h" #include "ash/wm/window_state_observer.h" #include "base/compiler_specific.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ui/aura/window_observer.h" class Browser; class Profile; namespace aura { class Window; class WindowObserver; } namespace ash { namespace test { class MultiUserWindowManagerTest; } } namespace chrome { class AppObserver; // The MultiUserWindowManager allows to show only windows of a particular user // when the user is active. To achieve this all windows need to be registered // to a user and upon user switch windows which belong to that (or no) user // get shown while the others get hidden. In addition, each window visibility // change gets inspected and - if incorrectly called - stays hidden. // Browser as well as shell (app) window creations get automatically tracked // and associated with the user in question. // Other windows can explicitly made into a user specific window by calling // |SetWindowOwner|. If a window should get shown on another user's desktop, // the function |ShowWindowForUser| can be invoked. // Note: // - There is no need to "unregister" a window from an owner. The class will // clean automatically all references of that window upon destruction. // - User changes will be tracked via observer. No need to call. // - All child windows will be owned by the same owner as its parent. class MultiUserWindowManager : public ash::SessionStateObserver, public aura::WindowObserver, public content::NotificationObserver, public ash::wm::WindowStateObserver { public: // Gets the instance of the object. If the multi profile mode is not enabled // this will return NULL. If it wasn't created yet, it will create an instance // using the currently active user as the active user - otherwise it will // return the previously created instance. static MultiUserWindowManager* GetInstance(); // Removes the instance. static void DeleteInstance(); // Get the user id from a given profile. static std::string GetUserIDFromProfile(Profile* profile); // Assigns an owner to a passed window. Note that this window's parent should // be a direct child of the root window. // A user switch will automatically change the visibility - and - if the // current user is not the owner it will immediately hidden. If the window // had already be registered this function will run into a DCHECK violation. void SetWindowOwner(aura::Window* window, const std::string& user_id); // See who owns this window. The return value is the user id or an empty // string if not assigned yet. const std::string& GetWindowOwner(aura::Window* window); // Allows to show an owned window for another users. If the window is not // owned, this call will return immediately. (The FileManager for example // might be available for every user and not belong explicitly to one). // Note that a window can only be shown on one desktop at a time. Note that // when the window gets minimized, it will automatically fall back to the // owner's desktop. void ShowWindowForUser(aura::Window* window, const std::string& user_id); // Returns true when windows are shared among users. bool AreWindowsSharedAmongUsers(); // A query call for a given window to see if it is on the given user's // desktop. bool IsWindowOnDesktopOfUser(aura::Window* window, const std::string& user_id); // Get the user on which the window is currently shown. If an empty string is // passed back the window will be presented for every user. const std::string& GetUserPresentingWindow(aura::Window* window); // SessionStateObserver overrides: virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE; virtual void UserAddedToSession(const std::string& user_id) OVERRIDE; // WindowObserver overrides: virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE; virtual void OnWindowVisibilityChanging(aura::Window* window, bool visible) OVERRIDE; virtual void OnWindowVisibilityChanged(aura::Window* window, bool visible) OVERRIDE; // Window .. overrides: virtual void OnWindowShowTypeChanged( ash::wm::WindowState* state, ash::wm::WindowShowType old_type) OVERRIDE; // content::NotificationObserver overrides: virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; protected: friend class ash::test::MultiUserWindowManagerTest; // Create an instance for and pass the |active_user_id| to it. static MultiUserWindowManager* CreateInstanceInternal( std::string active_user_id); private: class WindowEntry { public: explicit WindowEntry(const std::string& user_id) : owner_(user_id), show_for_user_(user_id), show_(true) {} virtual ~WindowEntry() {} // Returns the owner of this window. This cannot be changed. const std::string& owner() const { return owner_; } // Returns the user for which this should be shown. const std::string& show_for_user() const { return show_for_user_; } // Returns if the window should be shown for the "show user" or not. bool show() const { return show_; } // Set the user which will display the window on the owned desktop. If // an empty user id gets passed the owner will be used. void set_show_for_user(const std::string& user_id) { show_for_user_ = user_id.empty() ? owner_ : user_id; } // Sets if the window gets shown for the active user or not. void set_show(bool show) { show_ = show; } private: // The user id of the owner of this window. const std::string owner_; // The user id of the user on which desktop the window gets shown. std::string show_for_user_; // True if the window should be visible for the user which shows the window. bool show_; DISALLOW_COPY_AND_ASSIGN(WindowEntry); }; typedef std::map WindowToEntryMap; typedef std::map UserIDToShellWindowObserver; // Create the manager and use |active_user_id| as the active user. explicit MultiUserWindowManager(const std::string& active_user_id); virtual ~MultiUserWindowManager(); // Adds user to monitor for application windows. Returns immediately if the // user is already known to the system. Otherwise it will make sure that // application windows from that user will get properly tracked. void AddUser(const std::string& user_id); // Add a browser window to the system so that the owner can be remembered. void AddBrowserWindow(Browser* browser); // Show / hide the given window. Note: By not doing this within the functions, // this allows to either switching to different ways to show/hide and / or to // distinguish state changes performed by this class vs. state changes // performed by the others. void SetWindowVisibility(aura::Window* window, bool visible); // Get a profile for a given user id. Profile* GetProfileFromUserID(const std::string& user_id); // A lookup to see to which user the given window belongs to, where and if it // should get shown. WindowToEntryMap window_to_entry_; // A list of all known users and their shell window observers. UserIDToShellWindowObserver user_id_to_app_observer_; // The currently selected active user. It is used to find the proper // visibility state in various cases. The state is stored here instead of // being read from the user manager to be in sync while a switch occurs. std::string current_user_id_; // The notification registrar to track the creation of browser windows. content::NotificationRegistrar registrar_; // Suppress changes to the visibility flag while we are changing it ourselves. bool suppress_visibility_changes_; DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManager); }; } // namespace chrome #endif // CHROME_BROWSER_UI_ASH_MULTI_USER_WINDOW_MANAGER_H_