Home | History | Annotate | Download | only in multi_user
      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