blob: 42ad000ecebd0fbee1754eb6164cc1ca7fedfb12 [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_MULTI_USER_WINDOW_MANAGER_CLIENT_IMPL_H_
#define CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_CLIENT_IMPL_H_
#include <map>
#include <memory>
#include "ash/multi_user/multi_user_window_manager_delegate_classic.h"
#include "ash/public/interfaces/multi_user_window_manager.mojom.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_client.h"
#include "components/account_id/account_id.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/ws/common/types.h"
#include "ui/aura/window_observer.h"
class AppObserver;
class Browser;
namespace ash {
class MultiUserWindowManager;
class MultiUserWindowManagerClientImplTest;
} // namespace ash
namespace content {
class BrowserContext;
}
namespace aura {
class Window;
} // namespace aura
// Real implementation of MultiUserWindowManagerClient, see it for details.
class MultiUserWindowManagerClientImpl
: public MultiUserWindowManagerClient,
public ash::MultiUserWindowManagerDelegateClassic,
public ash::mojom::MultiUserWindowManagerClient,
public aura::WindowObserver,
public content::NotificationObserver {
public:
// Create the manager and use |active_account_id| as the active user.
explicit MultiUserWindowManagerClientImpl(const AccountId& active_account_id);
~MultiUserWindowManagerClientImpl() override;
// Initializes the manager after its creation. Should only be called once.
void Init();
// MultiUserWindowManager overrides:
void SetWindowOwner(aura::Window* window,
const AccountId& account_id) override;
const AccountId& GetWindowOwner(aura::Window* window) const override;
void ShowWindowForUser(aura::Window* window,
const AccountId& account_id) override;
bool AreWindowsSharedAmongUsers() const override;
void GetOwnersOfVisibleWindows(
std::set<AccountId>* account_ids) const override;
bool IsWindowOnDesktopOfUser(aura::Window* window,
const AccountId& account_id) const override;
const AccountId& GetUserPresentingWindow(aura::Window* window) const override;
void AddUser(content::BrowserContext* context) override;
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
// WindowObserver overrides:
void OnWindowDestroyed(aura::Window* window) override;
// content::NotificationObserver overrides:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// ash::MultiUserWindowManagerDelegateClassic overrides:
void OnOwnerEntryChanged(aura::Window* window,
const AccountId& account_id,
bool was_minimized,
bool teleported) override;
// Returns the current user for unit tests.
const AccountId& GetCurrentUserForTest() const;
private:
friend class ash::MultiUserWindowManagerClientImplTest;
friend class MultiUserWindowManagerClientImplTestHelper;
// Used only in classic mode. In classic mode a mojo Binding is used that
// results in the delegate being notified async. Doing this gives the same
// async delay seen when the WindowService is used.
struct ClassicSupport {
explicit ClassicSupport(MultiUserWindowManagerClientImpl* host);
~ClassicSupport();
ash::mojom::MultiUserWindowManagerClientPtr client_ptr;
mojo::Binding<ash::mojom::MultiUserWindowManagerClient> binding;
};
class WindowEntry {
public:
explicit WindowEntry(const AccountId& account_id)
: owner_(account_id), show_for_user_(account_id) {}
~WindowEntry() {}
// Returns the owner of this window. This cannot be changed.
const AccountId& owner() const { return owner_; }
// Returns the user for which this should be shown.
const AccountId& show_for_user() const { return show_for_user_; }
// 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 AccountId& account_id) {
show_for_user_ = account_id.is_valid() ? account_id : owner_;
}
private:
// The user id of the owner of this window.
const AccountId owner_;
// The user id of the user on which desktop the window gets shown.
AccountId show_for_user_;
DISALLOW_COPY_AND_ASSIGN(WindowEntry);
};
// ash::mojom::MultiUserWindowManagerClient:
void OnWindowOwnerEntryChanged(ws::Id window_id,
const AccountId& account_id,
bool was_minimized,
bool teleported) override;
void OnWillSwitchActiveAccount(const AccountId& account_id) override;
void OnTransitionUserShelfToNewAccount() override;
void OnDidSwitchActiveAccount() override;
// Add a browser window to the system so that the owner can be remembered.
void AddBrowserWindow(Browser* browser);
// The single instance of MultiUserWindowManagerClientImpl, tracked solely for
// tests.
static MultiUserWindowManagerClientImpl* instance_;
std::unique_ptr<ClassicSupport> classic_support_;
using WindowToEntryMap =
std::map<aura::Window*, std::unique_ptr<WindowEntry>>;
// A lookup to see to which user the given window belongs to, where and if it
// should get shown.
WindowToEntryMap window_to_entry_;
using AccountIdToAppWindowObserver = std::map<AccountId, AppObserver*>;
// A list of all known users and their app window observers.
AccountIdToAppWindowObserver account_id_to_app_observer_;
// An observer list to be notified upon window owner changes.
base::ObserverList<Observer>::Unchecked observers_;
// 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.
AccountId current_account_id_;
// The notification registrar to track the creation of browser windows.
content::NotificationRegistrar registrar_;
// This is *only* created in classic and single-process mash cases. In
// multi-process mash Ash creates the MultiUserWindowManager.
std::unique_ptr<ash::MultiUserWindowManager> ash_multi_user_window_manager_;
// Only used for windows created for the window-service. For example,
// Browser windows when running in mash.
ash::mojom::MultiUserWindowManagerAssociatedPtr
multi_user_window_manager_mojom_;
mojo::AssociatedBinding<ash::mojom::MultiUserWindowManagerClient>
client_binding_{this};
DISALLOW_COPY_AND_ASSIGN(MultiUserWindowManagerClientImpl);
};
#endif // CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_CLIENT_IMPL_H_