Commit 3afb8de3 authored by mukai@chromium.org's avatar mukai@chromium.org

Supports window teleports for notifications.

MultiUserNotificationBlockerChromeOS now supports visiting windows.
Due to the dependency from MultiUserWindowManagerChromeOS, it would
be beter to be in c/b/ui/ash/multi_user rather than notification.

Because now this blocker is turned on only when multi-user feature
is enabled, the test for single-user mode has been removed.

BUG=321679
R=dewittj@chromium.org, skuhne@chromium.org, sky@chromium.org
TBR=bshe@chromium.org
TEST=unit_tests / manually

Review URL: https://codereview.chromium.org/127423002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244058 0039d316-1c4b-4281-b951-d872f2087c98
parent 648252b0
......@@ -218,8 +218,8 @@ void WallpaperPrivateApiMultiUserUnittest::SetUp() {
}
void WallpaperPrivateApiMultiUserUnittest::TearDown() {
AshTestBase::TearDown();
chrome::MultiUserWindowManager::DeleteInstance();
AshTestBase::TearDown();
}
void WallpaperPrivateApiMultiUserUnittest::SetUpMultiUserWindowManager(
......
......@@ -33,7 +33,6 @@
#if defined(OS_CHROMEOS)
#include "chrome/browser/notifications/login_state_notification_blocker_chromeos.h"
#include "chrome/browser/notifications/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#endif
......@@ -66,7 +65,6 @@ MessageCenterNotificationManager::MessageCenterNotificationManager(
#if defined(OS_CHROMEOS)
blockers_.push_back(
new LoginStateNotificationBlockerChromeOS(message_center));
blockers_.push_back(new MultiUserNotificationBlockerChromeOS(message_center));
#else
blockers_.push_back(new ScreenLockNotificationBlocker(message_center));
#endif
......
......@@ -69,8 +69,8 @@ void MultiUserContextMenuChromeOSTest::SetUp() {
void MultiUserContextMenuChromeOSTest::TearDown() {
delete window_;
AshTestBase::TearDown();
chrome::MultiUserWindowManager::DeleteInstance();
AshTestBase::TearDown();
}
// Check that an unowned window will never create a menu.
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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.
#include "chrome/browser/notifications/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/system/system_notifier.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "ui/aura/window.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notifier_settings.h"
MultiUserNotificationBlockerChromeOS::MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter* message_center)
message_center::MessageCenter* message_center,
chrome::MultiUserWindowManager* multi_user_window_manager)
: NotificationBlocker(message_center),
observing_(false) {
// UserManager may not be initialized in unit tests.
if (!chromeos::UserManager::IsInitialized())
return;
// This class is created in the ctor of NotificationUIManager which is created
// when a notification is created, so ash::Shell should be initialized.
ash::Shell::GetInstance()->AddShellObserver(this);
chromeos::UserManager::Get()->AddSessionStateObserver(this);
observing_ = true;
multi_user_window_manager_(multi_user_window_manager) {
UpdateWindowOwners();
}
MultiUserNotificationBlockerChromeOS::~MultiUserNotificationBlockerChromeOS() {
if (observing_) {
if (ash::Shell::HasInstance())
ash::Shell::GetInstance()->RemoveShellObserver(this);
chromeos::UserManager::Get()->RemoveSessionStateObserver(this);
}
void MultiUserNotificationBlockerChromeOS::UpdateWindowOwners() {
std::set<std::string> new_ids;
multi_user_window_manager_->GetOwnersOfVisibleWindows(&new_ids);
if (current_user_ids_ != new_ids) {
current_user_ids_.swap(new_ids);
NotifyBlockingStateChanged();
}
}
......@@ -47,33 +47,29 @@ bool MultiUserNotificationBlockerChromeOS::ShouldShowNotification(
bool MultiUserNotificationBlockerChromeOS::ShouldShowNotificationAsPopup(
const message_center::NotifierId& notifier_id) const {
return ShouldShowNotification(notifier_id);
}
void MultiUserNotificationBlockerChromeOS::OnAppTerminating() {
ash::Shell::GetInstance()->RemoveShellObserver(this);
chromeos::UserManager::Get()->RemoveSessionStateObserver(this);
observing_ = false;
return (current_user_ids_.find(notifier_id.profile_id) !=
current_user_ids_.end()) ||
ShouldShowNotification(notifier_id);
}
void MultiUserNotificationBlockerChromeOS::ActiveUserChanged(
const chromeos::User* active_user) {
const std::string& new_user_id = active_user->email();
if (active_user_id_ == new_user_id)
const std::string& user_id) {
if (active_user_id_ == user_id)
return;
quiet_modes_[active_user_id_] = message_center()->IsQuietMode();
active_user_id_ = active_user->email();
active_user_id_ = user_id;
std::map<std::string, bool>::const_iterator iter =
quiet_modes_.find(active_user_id_);
if (iter != quiet_modes_.end() &&
iter->second != message_center()->IsQuietMode()) {
message_center()->SetQuietMode(iter->second);
}
UpdateWindowOwners();
NotifyBlockingStateChanged();
}
bool MultiUserNotificationBlockerChromeOS::IsActive() const {
return observing_ && chrome::MultiUserWindowManager::GetMultiProfileMode() ==
return chrome::MultiUserWindowManager::GetMultiProfileMode() ==
chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED;
}
// Copyright 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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_NOTIFICATIONS_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
#define CHROME_BROWSER_NOTIFICATIONS_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
#ifndef CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
#define CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
#include <map>
#include <set>
#include <string>
#include "ash/shell_observer.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chromeos/login/login_state.h"
#include "ui/message_center/notification_blocker.h"
// A notification blocker for per-profile stream switching.
namespace chrome {
class MultiUserWindowManager;
}
// A notification blocker for per-profile stream switching. Owned and controlled
// by MultiUserWindowManagerChromeOS.
class MultiUserNotificationBlockerChromeOS
: public message_center::NotificationBlocker,
public ash::ShellObserver,
public chromeos::UserManager::UserSessionStateObserver {
: public message_center::NotificationBlocker {
public:
explicit MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter* message_center);
MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter* message_center,
chrome::MultiUserWindowManager* multi_user_window_manager);
virtual ~MultiUserNotificationBlockerChromeOS();
// Checks the current desktop and update the list of users which owns windows
// on the current desktop.
void UpdateWindowOwners();
// Called by MultiUserWindowManager when the active user has changed.
void ActiveUserChanged(const std::string& user_id);
// message_center::NotificationBlocker overrides:
virtual bool ShouldShowNotification(
const message_center::NotifierId& notifier_id) const OVERRIDE;
virtual bool ShouldShowNotificationAsPopup(
const message_center::NotifierId& notifier_id) const OVERRIDE;
// ash::ShellObserver overrides:
virtual void OnAppTerminating() OVERRIDE;
// chromeos::UserManager::UserSessionStateObserver overrides:
virtual void ActiveUserChanged(const chromeos::User* active_user) OVERRIDE;
private:
// Returns true if this blocker is actively working.
bool IsActive() const;
chrome::MultiUserWindowManager* multi_user_window_manager_; // Weak.
std::string active_user_id_;
bool observing_;
std::map<std::string, bool> quiet_modes_;
std::set<std::string> current_user_ids_;
DISALLOW_COPY_AND_ASSIGN(MultiUserNotificationBlockerChromeOS);
};
#endif // CHROME_BROWSER_NOTIFICATIONS_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
#endif // CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_NOTIFICATION_BLOCKER_CHROMEOS_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Copyright 2014 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.
#include "ash/session_state_delegate.h"
#include "ash/shell.h"
#include "ash/system/system_notifier.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/test_shell_delegate.h"
#include "chrome/browser/chromeos/login/fake_user_manager.h"
#include "chrome/browser/notifications/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "ash/wm/window_state.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notification.h"
namespace {
// This value should be same as the one in fake_user_manager.cc
static const char kUserIdHashSuffix[] = "-hash";
}
class MultiUserNotificationBlockerChromeOSTest
: public ash::test::AshTestBase,
public message_center::NotificationBlocker::Observer {
......@@ -28,7 +22,8 @@ class MultiUserNotificationBlockerChromeOSTest
MultiUserNotificationBlockerChromeOSTest()
: state_changed_count_(0),
is_logged_in_(false),
testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {}
testing_profile_manager_(TestingBrowserProcess::GetGlobal()),
window_id_(0) {}
virtual ~MultiUserNotificationBlockerChromeOSTest() {}
// ash::test::AshTestBase overrides:
......@@ -36,17 +31,17 @@ class MultiUserNotificationBlockerChromeOSTest
ash::test::AshTestBase::SetUp();
ASSERT_TRUE(testing_profile_manager_.SetUp());
// Initialize the UserManager singleton to a fresh FakeUserManager instance.
user_manager_enabler_.reset(
new chromeos::ScopedUserManagerEnabler(new chromeos::FakeUserManager));
blocker_.reset(new MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter::Get()));
blocker_->AddObserver(this);
ash::test::TestShellDelegate* shell_delegate =
static_cast<ash::test::TestShellDelegate*>(
ash::Shell::GetInstance()->delegate());
shell_delegate->set_multi_profiles_enabled(true);
chrome::MultiUserWindowManager::CreateInstance();
GetMultiUserWindowManager()->notification_blocker_->AddObserver(this);
}
virtual void TearDown() OVERRIDE {
blocker_->RemoveObserver(this);
blocker_.reset();
GetMultiUserWindowManager()->notification_blocker_->RemoveObserver(this);
if (chrome::MultiUserWindowManager::GetInstance())
chrome::MultiUserWindowManager::DeleteInstance();
ash::test::AshTestBase::TearDown();
......@@ -59,18 +54,17 @@ class MultiUserNotificationBlockerChromeOSTest
}
protected:
void SetupMultiUserMode(bool enabled) {
ash::test::TestShellDelegate* shell_delegate =
static_cast<ash::test::TestShellDelegate*>(
ash::Shell::GetInstance()->delegate());
shell_delegate->set_multi_profiles_enabled(enabled);
chrome::MultiUserWindowManager::CreateInstance();
chrome::MultiUserWindowManagerChromeOS* GetMultiUserWindowManager() {
return static_cast<chrome::MultiUserWindowManagerChromeOS*>(
chrome::MultiUserWindowManager::GetInstance());
}
const message_center::NotificationBlocker* blocker() {
return GetMultiUserWindowManager()->notification_blocker_.get();
}
void CreateProfile(const std::string& name) {
testing_profile_manager_.CreateTestingProfile(name);
GetFakeUserManager()->AddUser(name);
GetFakeUserManager()->UserLoggedIn(name, name + kUserIdHashSuffix, false);
if (!is_logged_in_) {
SwitchActiveUser(name);
is_logged_in_ = true;
......@@ -78,8 +72,13 @@ class MultiUserNotificationBlockerChromeOSTest
}
void SwitchActiveUser(const std::string& name) {
GetFakeUserManager()->SwitchActiveUser(name);
blocker_->ActiveUserChanged(GetFakeUserManager()->GetActiveUser());
ash::Shell::GetInstance()->session_state_delegate()->SwitchActiveUser(name);
if (chrome::MultiUserWindowManager::GetMultiProfileMode() ==
chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) {
static_cast<chrome::MultiUserWindowManagerChromeOS*>(
chrome::MultiUserWindowManager::GetInstance())->ActiveUserChanged(
name);
}
}
int GetStateChangedCountAndReset() {
......@@ -93,7 +92,7 @@ class MultiUserNotificationBlockerChromeOSTest
const std::string profile_id) {
message_center::NotifierId id_with_profile = notifier_id;
id_with_profile.profile_id = profile_id;
return blocker_->ShouldShowNotificationAsPopup(id_with_profile);
return blocker()->ShouldShowNotificationAsPopup(id_with_profile);
}
bool ShouldShowNotification(
......@@ -101,26 +100,25 @@ class MultiUserNotificationBlockerChromeOSTest
const std::string profile_id) {
message_center::NotifierId id_with_profile = notifier_id;
id_with_profile.profile_id = profile_id;
return blocker_->ShouldShowNotification(id_with_profile);
return blocker()->ShouldShowNotification(id_with_profile);
}
private:
chromeos::FakeUserManager* GetFakeUserManager() {
return static_cast<chromeos::FakeUserManager*>(
chromeos::UserManager::Get());
aura::Window* CreateWindowForProfile(const std::string& name) {
aura::Window* window = CreateTestWindowInShellWithId(window_id_++);
chrome::MultiUserWindowManager::GetInstance()->SetWindowOwner(window, name);
return window;
}
private:
int state_changed_count_;
bool is_logged_in_;
TestingProfileManager testing_profile_manager_;
scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
scoped_ptr<MultiUserNotificationBlockerChromeOS> blocker_;
int window_id_;
DISALLOW_COPY_AND_ASSIGN(MultiUserNotificationBlockerChromeOSTest);
};
TEST_F(MultiUserNotificationBlockerChromeOSTest, Basic) {
SetupMultiUserMode(true);
ASSERT_EQ(chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED,
chrome::MultiUserWindowManager::GetMultiProfileMode());
......@@ -217,41 +215,87 @@ TEST_F(MultiUserNotificationBlockerChromeOSTest, Basic) {
"test2@example.com"));
}
TEST_F(MultiUserNotificationBlockerChromeOSTest, SingleUser) {
SetupMultiUserMode(false);
ASSERT_EQ(chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_OFF,
TEST_F(MultiUserNotificationBlockerChromeOSTest, TeleportedWindows) {
ASSERT_EQ(chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED,
chrome::MultiUserWindowManager::GetMultiProfileMode());
std::string u1 = "test@example.com";
std::string u2 = "test2@example.com";
std::string u3 = "test3@example.com";
CreateProfile(u1);
CreateProfile(u2);
CreateProfile(u3);
chrome::MultiUserWindowManager* multi_user_window_manager =
chrome::MultiUserWindowManager::GetInstance();
message_center::NotifierId notifier_id(
message_center::NotifierId::APPLICATION, "test-app");
// Only allowed the system notifier.
message_center::NotifierId ash_system_notifier(
message_center::NotifierId::SYSTEM_COMPONENT,
ash::system_notifier::kNotifierDisplay);
// Other system notifiers should be treated as same as a normal notifier.
message_center::NotifierId random_system_notifier(
message_center::NotifierId::SYSTEM_COMPONENT, "random_system_component");
// Nothing is created, active_user_id_ should be empty.
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, ""));
EXPECT_TRUE(ShouldShowNotificationAsPopup(ash_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotificationAsPopup(random_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotification(notifier_id, ""));
EXPECT_TRUE(ShouldShowNotification(ash_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotification(random_system_notifier, ""));
// Initial status: only notifications for u1 should be shown.
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
CreateProfile("test@example.com");
// Create a new window in u2.
SwitchActiveUser(u2);
scoped_ptr<aura::Window> w2(CreateWindowForProfile(u2));
EXPECT_EQ(2, GetStateChangedCountAndReset());
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
// Moves w2 to u1 desktop.
multi_user_window_manager->ShowWindowForUser(w2.get(), u1);
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, ""));
EXPECT_TRUE(ShouldShowNotificationAsPopup(ash_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotificationAsPopup(random_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, "test@example.com"));
EXPECT_TRUE(ShouldShowNotificationAsPopup(random_system_notifier,
"test@example.com"));
EXPECT_TRUE(ShouldShowNotification(notifier_id, ""));
EXPECT_TRUE(ShouldShowNotification(ash_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotification(random_system_notifier, ""));
EXPECT_TRUE(ShouldShowNotification(notifier_id, "test@example.com"));
EXPECT_TRUE(ShouldShowNotification(random_system_notifier,
"test@example.com"));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
// Switch back to u1 desktop. Notification for u2 should be shown as a popup
// because w2 is visiting to u1.
SwitchActiveUser(u1);
EXPECT_EQ(2, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
// Notifications for u2 is not shown in the center.
EXPECT_TRUE(ShouldShowNotification(notifier_id, u1));
EXPECT_FALSE(ShouldShowNotification(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotification(notifier_id, u3));
// Moves w2 back.
multi_user_window_manager->ShowWindowForUser(w2.get(), u2);
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
// Close/remove the visiting window.
scoped_ptr<aura::Window> w22(CreateWindowForProfile(u2));
multi_user_window_manager->ShowWindowForUser(w22.get(), u1);
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
w22.reset();
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
// Minimize the visiting window.
scoped_ptr<aura::Window> w23(CreateWindowForProfile(u2));
multi_user_window_manager->ShowWindowForUser(w23.get(), u1);
EXPECT_EQ(1, GetStateChangedCountAndReset());
ash::wm::GetWindowState(w23.get())->Minimize();
EXPECT_EQ(u2, multi_user_window_manager->GetUserPresentingWindow(w23.get()));
EXPECT_EQ(1, GetStateChangedCountAndReset());
EXPECT_TRUE(ShouldShowNotificationAsPopup(notifier_id, u1));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u2));
EXPECT_FALSE(ShouldShowNotificationAsPopup(notifier_id, u3));
}
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_ASH_MULTI_USER_MULTI_USER_WINDOW_MANAGER_H_
#include <map>
#include <set>
#include <string>
class Browser;
......@@ -90,6 +91,9 @@ class MultiUserWindowManager {
// Returns true when windows are shared among users.
virtual bool AreWindowsSharedAmongUsers() = 0;
// Get the owners for the visible windows and set them to |user_ids|.
virtual void GetOwnersOfVisibleWindows(std::set<std::string>* user_ids) = 0;
// A query call for a given window to see if it is on the given user's
// desktop.
virtual bool IsWindowOnDesktopOfUser(aura::Window* window,
......
......@@ -23,6 +23,7 @@
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
......@@ -36,6 +37,7 @@
#include "ui/aura/window.h"
#include "ui/base/ui_base_types.h"
#include "ui/events/event.h"
#include "ui/message_center/message_center.h"
#include "ui/views/corewm/window_util.h"
namespace {
......@@ -177,6 +179,8 @@ class AppObserver : public apps::ShellWindowRegistry::Observer {
MultiUserWindowManagerChromeOS::MultiUserWindowManagerChromeOS(
const std::string& current_user_id)
: current_user_id_(current_user_id),
notification_blocker_(new MultiUserNotificationBlockerChromeOS(
message_center::MessageCenter::Get(), this)),
suppress_visibility_changes_(false) {
// Add a session state observer to be able to monitor session changes.
if (ash::Shell::HasInstance())
......@@ -248,6 +252,11 @@ void MultiUserWindowManagerChromeOS::SetWindowOwner(
// will add the children but not the owner to the transient children map.
AddTransientOwnerRecursive(window, window);
// Right now only |notification_blocker_| needs to know when the list of
// owners may change.
// TODO(skuhne): replace this by observer when another one needs this event.
notification_blocker_->UpdateWindowOwners();
if (!IsWindowOnDesktopOfUser(window, current_user_id_))
SetWindowVisibility(window, false);
}
......@@ -295,6 +304,9 @@ void MultiUserWindowManagerChromeOS::ShowWindowForUser(
} else {
SetWindowVisibility(window, false);
}
// TODO(skuhne): replace this by observer when another one needs this event.
notification_blocker_->UpdateWindowOwners();
}
bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() {
......@@ -306,6 +318,15 @@ bool MultiUserWindowManagerChromeOS::AreWindowsSharedAmongUsers() {
return false;
}
void MultiUserWindowManagerChromeOS::GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) {
for (WindowToEntryMap::iterator it = window_to_entry_.begin();
it != window_to_entry_.end(); ++it) {
if (it->first->IsVisible())
user_ids->insert(it->second->owner());
}
}
bool MultiUserWindowManagerChromeOS::IsWindowOnDesktopOfUser(
aura::Window* window,
const std::string& user_id) {
......@@ -406,6 +427,10 @@ void MultiUserWindowManagerChromeOS::ActiveUserChanged(
client->ActivateWindow(window);
}
}
// This is called directly here to make sure notification_blocker will see the
// new window status.
notification_blocker_->ActiveUserChanged(user_id);
}
void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
......@@ -420,6 +445,8 @@ void MultiUserWindowManagerChromeOS::OnWindowDestroyed(aura::Window* window) {
// Remove the window from the owners list.
delete window_to_entry_[window];
window_to_entry_.erase(window);
// TODO(skuhne): replace this by observer when another one needs this event.
notification_blocker_->UpdateWindowOwners();
}
void MultiUserWindowManagerChromeOS::OnWindowVisibilityChanging(
......
......@@ -11,12 +11,15 @@
#include "ash/session_state_observer.h"
#include "ash/wm/window_state_observer.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/aura/window_observer.h"
class Browser;
class MultiUserNotificationBlockerChromeOS;
class MultiUserNotificationBlockerChromeOSTest;
class Profile;
namespace aura {
......@@ -58,6 +61,8 @@ class MultiUserWindowManagerChromeOS : public MultiUserWindowManager,
virtual void ShowWindowForUser(
aura::Window* window, const std::string& user_id) OVERRIDE;
virtual bool AreWindowsSharedAmongUsers() OVERRIDE;
virtual void GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) OVERRIDE;
virtual bool IsWindowOnDesktopOfUser(aura::Window* window,
const std::string& user_id) OVERRIDE;
virtual const std::string& GetUserPresentingWindow(
......@@ -89,6 +94,8 @@ class MultiUserWindowManagerChromeOS : public MultiUserWindowManager,
const content::NotificationDetails& details) OVERRIDE;
private:
friend class ::MultiUserNotificationBlockerChromeOSTest;
class WindowEntry {
public:
explicit WindowEntry(const std::string& user_id)
......@@ -175,6 +182,10 @@ class MultiUserWindowManagerChromeOS : public MultiUserWindowManager,
// being read from the user manager to be in sync while a switch occurs.
std::string current_user_id_;
// The blocker which controls the desktop notification visibility based on the
// current multi-user status.
scoped_ptr<MultiUserNotificationBlockerChromeOS> notification_blocker_;
// The notification registrar to track the creation of browser windows.
content::NotificationRegistrar registrar_;
......
......@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
#include "chrome/common/chrome_switches.h"
......@@ -63,6 +64,9 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase {
// shown by A, and "D,..." would mean that window#0 is deleted.
std::string GetStatus();
// Returns a test-friendly string format of GetOwnersOfVisibleWindows().
std::string GetOwnersOfVisibleWindowsAsString();
TestSessionStateDelegate* session_state_delegate() {
return session_state_delegate_;
}
......@@ -116,8 +120,8 @@ void MultiUserWindowManagerChromeOSTest::TearDown() {
window_.erase(window_.begin());
}
AshTestBase::TearDown();
chrome::MultiUserWindowManager::DeleteInstance();
AshTestBase::TearDown();
}
std::string MultiUserWindowManagerChromeOSTest::GetStatus() {
......@@ -144,6 +148,16 @@ std::string MultiUserWindowManagerChromeOSTest::GetStatus() {
return s;
}
std::string
MultiUserWindowManagerChromeOSTest::GetOwnersOfVisibleWindowsAsString() {
std::set<std::string> owners;
multi_user_window_manager_->GetOwnersOfVisibleWindows(&owners);
std::vector<std::string> owner_list;
owner_list.insert(owner_list.begin(), owners.begin(), owners.end());
return JoinString(owner_list, ' ');
}
// Testing basic assumptions like default state and existence of manager.
TEST_F(MultiUserWindowManagerChromeOSTest, BasicTests) {
SetUpForThisManyWindows(3);
......@@ -226,6 +240,7 @@ TEST_F(MultiUserWindowManagerChromeOSTest, CloseWindowTests) {
multi_user_window_manager()->ShowWindowForUser(window(0), "A");
EXPECT_EQ("S[B,A]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("B", GetOwnersOfVisibleWindowsAsString());
aura::Window* to_be_deleted = window(0);
......@@ -240,6 +255,7 @@ TEST_F(MultiUserWindowManagerChromeOSTest, CloseWindowTests) {
delete_window_at(0);
EXPECT_EQ("D", GetStatus());
EXPECT_EQ("", GetOwnersOfVisibleWindowsAsString());
// There should be no owner anymore for that window and the shared windows
// should be gone as well.
EXPECT_EQ(std::string(),
......@@ -260,6 +276,7 @@ TEST_F(MultiUserWindowManagerChromeOSTest, SharedWindowTests) {
multi_user_window_manager()->SetWindowOwner(window(4), "C");
EXPECT_EQ("S[A], S[A], H[B], H[B], H[C]", GetStatus());
EXPECT_FALSE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
// For all following tests we override window 2 to be shown by user B.
multi_user_window_manager()->ShowWindowForUser(window(1), "B");
......@@ -269,31 +286,39 @@ TEST_F(MultiUserWindowManagerChromeOSTest, SharedWindowTests) {
multi_user_window_manager()->ShowWindowForUser(window(2), "A");
EXPECT_EQ("S[A], H[A,B], S[B,A], H[B], H[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("A B", GetOwnersOfVisibleWindowsAsString());
multi_user_window_manager()->ShowWindowForUser(window(2), "C");
EXPECT_EQ("S[A], H[A,B], H[B,C], H[B], H[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("A", GetOwnersOfVisibleWindowsAsString());
// Switch the users and see that the results are correct.
multi_user_window_manager()->ActiveUserChanged("B");
EXPECT_EQ("H[A], S[A,B], H[B,C], S[B], H[C]", GetStatus());
EXPECT_EQ("A B", GetOwnersOfVisibleWindowsAsString());
multi_user_window_manager()->ActiveUserChanged("C");
EXPECT_EQ("H[A], H[A,B], S[B,C], H[B], S[C]", GetStatus());
EXPECT_EQ("B C", GetOwnersOfVisibleWindowsAsString());
// Showing on the desktop of the already owning user should have no impact.
multi_user_window_manager()->ShowWindowForUser(window(4), "C");
EXPECT_EQ("H[A], H[A,B], S[B,C], H[B], S[C]", GetStatus());
EXPECT_EQ("B C", GetOwnersOfVisibleWindowsAsString());
// Changing however a shown window back to the original owner should hide it.
multi_user_window_manager()->ShowWindowForUser(window(2), "B");
EXPECT_EQ("H[A], H[A,B], H[B], H[B], S[C]", GetStatus());
EXPECT_TRUE(multi_user_window_manager()->AreWindowsSharedAmongUsers());
EXPECT_EQ("C", GetOwnersOfVisibleWindowsAsString());
// And the change should be "permanent" - switching somewhere else and coming
// back.
multi_user_window_manager()->ActiveUserChanged("B");
EXPECT_EQ("H[A], S[A,B], S[B], S[B], H[C]", GetStatus());
EXPECT_EQ("A B", GetOwnersOfVisibleWindowsAsString());
multi_user_window_manager()->ActiveUserChanged("C");
EXPECT_EQ("H[A], H[A,B], H[B], H[B], S[C]", GetStatus());
EXPECT_EQ("C", GetOwnersOfVisibleWindowsAsString());
// After switching window 2 back to its original desktop, all desktops should
// be "clean" again.
......
......@@ -28,6 +28,10 @@ bool MultiUserWindowManagerStub::AreWindowsSharedAmongUsers() {
return false;
}
void MultiUserWindowManagerStub::GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) {
}
bool MultiUserWindowManagerStub::IsWindowOnDesktopOfUser(
aura::Window* window,
const std::string& user_id) {
......
......@@ -34,6 +34,8 @@ class MultiUserWindowManagerStub : public MultiUserWindowManager {
virtual void ShowWindowForUser(
aura::Window* window, const std::string& user_id) OVERRIDE;
virtual bool AreWindowsSharedAmongUsers() OVERRIDE;
virtual void GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) OVERRIDE;
virtual bool IsWindowOnDesktopOfUser(aura::Window* window,
const std::string& user_id) OVERRIDE;
virtual const std::string& GetUserPresentingWindow(
......
......@@ -43,6 +43,8 @@ class TestMultiUserWindowManager : public chrome::MultiUserWindowManager {
virtual void ShowWindowForUser(
aura::Window* window, const std::string& user_id) OVERRIDE;
virtual bool AreWindowsSharedAmongUsers() OVERRIDE;
virtual void GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) OVERRIDE;
virtual bool IsWindowOnDesktopOfUser(aura::Window* window,
const std::string& user_id) OVERRIDE;
virtual const std::string& GetUserPresentingWindow(
......@@ -112,6 +114,10 @@ bool TestMultiUserWindowManager::AreWindowsSharedAmongUsers() {
return browser_owner_ != desktop_owner_;
}
void TestMultiUserWindowManager::GetOwnersOfVisibleWindows(
std::set<std::string>* user_ids) {
}
bool TestMultiUserWindowManager::IsWindowOnDesktopOfUser(
aura::Window* window,
const std::string& user_id) {
......
......@@ -1338,8 +1338,6 @@
'browser/notifications/fullscreen_notification_blocker.h',
'browser/notifications/login_state_notification_blocker_chromeos.cc',
'browser/notifications/login_state_notification_blocker_chromeos.h',
'browser/notifications/multi_user_notification_blocker_chromeos.cc',
'browser/notifications/multi_user_notification_blocker_chromeos.h',
'browser/notifications/notification_delegate.cc',
'browser/notifications/notification_delegate.h',
'browser/notifications/notification_object_proxy.cc',
......
......@@ -324,6 +324,8 @@
'browser/ui/ash/multi_user/multi_user_context_menu.cc',
'browser/ui/ash/multi_user/multi_user_context_menu.h',
'browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc',
'browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.cc',
'browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos.h',
'browser/ui/ash/multi_user/multi_user_util.cc',
'browser/ui/ash/multi_user/multi_user_util.h',
'browser/ui/ash/multi_user/multi_user_window_manager.cc',
......
......@@ -1068,7 +1068,6 @@
'browser/notifications/login_state_notification_blocker_chromeos_unittest.cc',
'browser/notifications/message_center_notifications_unittest_win.cc',
'browser/notifications/message_center_settings_controller_unittest.cc',
'browser/notifications/multi_user_notification_blocker_chromeos_unittest.cc',
'browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc',
'browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc',
'browser/notifications/sync_notifier/synced_notification_unittest.cc',
......@@ -1417,6 +1416,7 @@
'browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc',
'browser/ui/ash/launcher/launcher_context_menu_unittest.cc',
'browser/ui/ash/multi_user/multi_user_context_menu_chromeos_unittest.cc',
'browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc',
'browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc',
'browser/ui/ash/screenshot_taker_unittest.cc',
'browser/ui/ash/session_state_delegate_chromeos_unittest.cc',
......@@ -2307,7 +2307,6 @@
'browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc',
'browser/net/gaia/gaia_oauth_fetcher_unittest.cc',
'browser/notifications/login_state_notification_blocker_chromeos_unittest.cc',
'browser/notifications/multi_user_notification_blocker_chromeos_unittest.cc',
'browser/extensions/api/log_private/syslog_parser_unittest.cc',
],
}],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment