blob: bff9762e26f598491c02071a46f6eedc549c7aba [file] [log] [blame]
// 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 <map>
#include <string>
#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();
// 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<aura::Window*, WindowEntry*> WindowToEntryMap;
typedef std::map<std::string, AppObserver*> 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_