diff options
author | xdai <xdai@chromium.org> | 2015-04-15 09:28:35 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-15 16:28:54 +0000 |
commit | 13beb501975bbc13f07cd8a1915a8a51310cecec (patch) | |
tree | f41b85fca7f13f14b3ae05f6ab6fb20f51ce888f | |
parent | 907b409a46af8efb63d83c46f8901d6f0d01c8fe (diff) | |
download | chromium_src-13beb501975bbc13f07cd8a1915a8a51310cecec.zip chromium_src-13beb501975bbc13f07cd8a1915a8a51310cecec.tar.gz chromium_src-13beb501975bbc13f07cd8a1915a8a51310cecec.tar.bz2 |
Fix the following two cases in multiprofile scenario:
1) Window A belongs to user1 and is shown for user1. Minimizes window A.
Switch to user2, window A can not be activated by user2.
2) Window A belongs to user1 and is shown for user2. Then windowA can be activated
by user2 but cannot be activated by user1.
Also add unit tests for these two cases.
BUG=471858
TEST=manually tested
Review URL: https://codereview.chromium.org/1053013007
Cr-Commit-Position: refs/heads/master@{#325259}
-rw-r--r-- | ash/session/session_state_delegate.h | 5 | ||||
-rw-r--r-- | ash/shell/shell_delegate_impl.cc | 4 | ||||
-rw-r--r-- | ash/test/test_session_state_delegate.cc | 7 | ||||
-rw-r--r-- | ash/test/test_session_state_delegate.h | 2 | ||||
-rw-r--r-- | ash/wm/ash_focus_rules.cc | 21 | ||||
-rw-r--r-- | chrome/browser/apps/app_browsertest.cc | 3 | ||||
-rw-r--r-- | chrome/browser/chromeos/profiles/profile_helper.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc | 157 | ||||
-rw-r--r-- | chrome/browser/ui/ash/session_state_delegate_chromeos.cc | 17 | ||||
-rw-r--r-- | chrome/browser/ui/ash/session_state_delegate_chromeos.h | 2 | ||||
-rw-r--r-- | chrome/browser/ui/ash/session_state_delegate_views.cc | 6 | ||||
-rw-r--r-- | chrome/browser/ui/ash/session_state_delegate_views.h | 2 |
13 files changed, 225 insertions, 15 deletions
diff --git a/ash/session/session_state_delegate.h b/ash/session/session_state_delegate.h index e3b2dc4..5e73e58 100644 --- a/ash/session/session_state_delegate.h +++ b/ash/session/session_state_delegate.h @@ -81,6 +81,11 @@ class ASH_EXPORT SessionStateDelegate { virtual content::BrowserContext* GetBrowserContextForWindow( aura::Window* window) = 0; + // Returns the browser context on which the window is currently shown. NULL + // means the window will be shown for every user. + virtual content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) = 0; + // Returns the maximum possible number of logged in users. virtual int GetMaximumNumberOfLoggedInUsers() const = 0; diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 4af993a..ce07345 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc @@ -89,6 +89,10 @@ class SessionStateDelegateImpl : public SessionStateDelegate { aura::Window* window) override { return Shell::GetInstance()->delegate()->GetActiveBrowserContext(); } + content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) override { + return NULL; + } int GetMaximumNumberOfLoggedInUsers() const override { return 3; } int NumberOfLoggedInUsers() const override { // ash_shell has 2 users. diff --git a/ash/test/test_session_state_delegate.cc b/ash/test/test_session_state_delegate.cc index 0d31d45..c28c4973 100644 --- a/ash/test/test_session_state_delegate.cc +++ b/ash/test/test_session_state_delegate.cc @@ -99,8 +99,13 @@ TestSessionStateDelegate::GetBrowserContextByIndex( return NULL; } +content::BrowserContext* TestSessionStateDelegate::GetBrowserContextForWindow( + aura::Window* window) { + return NULL; +} + content::BrowserContext* -TestSessionStateDelegate::GetBrowserContextForWindow( +TestSessionStateDelegate::GetUserPresentingBrowserContextForWindow( aura::Window* window) { return NULL; } diff --git a/ash/test/test_session_state_delegate.h b/ash/test/test_session_state_delegate.h index b35f864..337ebf8 100644 --- a/ash/test/test_session_state_delegate.h +++ b/ash/test/test_session_state_delegate.h @@ -34,6 +34,8 @@ class TestSessionStateDelegate : public SessionStateDelegate { MultiProfileIndex index) override; content::BrowserContext* GetBrowserContextForWindow( aura::Window* window) override; + content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) override; int GetMaximumNumberOfLoggedInUsers() const override; int NumberOfLoggedInUsers() const override; bool IsActiveUserSessionStarted() const override; diff --git a/ash/wm/ash_focus_rules.cc b/ash/wm/ash_focus_rules.cc index 66fe0b2..12b301a 100644 --- a/ash/wm/ash_focus_rules.cc +++ b/ash/wm/ash_focus_rules.cc @@ -4,7 +4,9 @@ #include "ash/wm/ash_focus_rules.h" +#include "ash/session/session_state_delegate.h" #include "ash/shell.h" +#include "ash/shell_delegate.h" #include "ash/shell_window_ids.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/window_state.h" @@ -84,6 +86,25 @@ bool AshFocusRules::SupportsChildActivation(aura::Window* window) const { bool AshFocusRules::IsWindowConsideredVisibleForActivation( aura::Window* window) const { + // If the |window| doesn't belong to the current active user and also doesn't + // show for the current active user, then it should not be activated. + SessionStateDelegate* delegate = + Shell::GetInstance()->session_state_delegate(); + if (delegate->NumberOfLoggedInUsers() > 1) { + content::BrowserContext* active_browser_context = + Shell::GetInstance()->delegate()->GetActiveBrowserContext(); + content::BrowserContext* owner_browser_context = + delegate->GetBrowserContextForWindow(window); + content::BrowserContext* shown_browser_context = + delegate->GetUserPresentingBrowserContextForWindow(window); + + if (owner_browser_context && active_browser_context && + owner_browser_context != active_browser_context && + shown_browser_context != active_browser_context) { + return false; + } + } + if (BaseFocusRules::IsWindowConsideredVisibleForActivation(window)) return true; diff --git a/chrome/browser/apps/app_browsertest.cc b/chrome/browser/apps/app_browsertest.cc index 8140449..422c547 100644 --- a/chrome/browser/apps/app_browsertest.cc +++ b/chrome/browser/apps/app_browsertest.cc @@ -1241,6 +1241,9 @@ class RestartDeviceTest : public PlatformAppBrowserTest { .WillRepeatedly(testing::Return(true)); EXPECT_CALL(*mock_user_manager_, IsLoggedInAsKioskApp()) .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*mock_user_manager_, GetLoggedInUsers()) + .WillRepeatedly(testing::Invoke(mock_user_manager_, + &chromeos::MockUserManager::GetUsers)); } void TearDownOnMainThread() override { diff --git a/chrome/browser/chromeos/profiles/profile_helper.h b/chrome/browser/chromeos/profiles/profile_helper.h index 18a0239..cee6b9c 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.h +++ b/chrome/browser/chromeos/profiles/profile_helper.h @@ -26,6 +26,12 @@ namespace extensions { class ExtensionGarbageCollectorChromeOSUnitTest; } +namespace ash { +namespace test { +class MultiUserWindowManagerChromeOSTest; +} // namespace test +} // namespace ash + namespace chromeos { // This helper class is used on Chrome OS to keep track of currently @@ -139,6 +145,7 @@ class ProfileHelper friend class ProfileListChromeOSTest; friend class SessionStateDelegateChromeOSTest; friend class SystemTrayDelegateChromeOSTest; + friend class ash::test::MultiUserWindowManagerChromeOSTest; // Called when signin profile is cleared. void OnSigninProfileCleared(); diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc index e220452..1b61714 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc @@ -42,7 +42,7 @@ namespace { -void InitAfterSessionStart() { +void InitAfterFirstSessionStart() { // Restore focus after the user session is started. It's needed because some // windows can be opened in background while login UI is still active because // we currently restore browser windows before login UI is deleted. @@ -263,7 +263,10 @@ void ChromeShellDelegate::Observe(int type, break; } case chrome::NOTIFICATION_SESSION_STARTED: - InitAfterSessionStart(); + // InitAfterFirstSessionStart() should only be called once upon system + // start. + if (user_manager::UserManager::Get()->GetLoggedInUsers().size() < 2) + InitAfterFirstSessionStart(); ash::Shell::GetInstance()->ShowShelf(); break; default: diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc index 2cf7498..12e3284 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc @@ -7,6 +7,7 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_helper.h" #include "ash/test/test_session_state_delegate.h" #include "ash/test/test_shell_delegate.h" #include "ash/wm/maximize_mode/maximize_mode_controller.h" @@ -18,13 +19,17 @@ #include "base/logging.h" #include "base/strings/string_util.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" +#include "chrome/browser/chromeos/profiles/profile_helper.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 "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h" #include "chrome/browser/ui/ash/multi_user/user_switch_animator_chromeos.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" -#include "components/user_manager/fake_user_manager.h" +#include "chrome/test/base/testing_profile_manager.h" #include "components/user_manager/user_info.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window_event_dispatcher.h" @@ -36,6 +41,54 @@ namespace ash { namespace test { +class TestSessionStateDelegateChromeOS + : public ash::test::TestSessionStateDelegate { + public: + TestSessionStateDelegateChromeOS() {} + + // TestSessionStateDelegate override: + content::BrowserContext* GetBrowserContextForWindow( + aura::Window* window) override { + const std::string& user_id = + chrome::MultiUserWindowManager::GetInstance()->GetWindowOwner(window); + return user_id.empty() ? NULL + : multi_user_util::GetProfileFromUserID(user_id); + } + + content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) override { + const std::string& user_id = + chrome::MultiUserWindowManager::GetInstance()->GetUserPresentingWindow( + window); + return user_id.empty() ? NULL + : multi_user_util::GetProfileFromUserID(user_id); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestSessionStateDelegateChromeOS); +}; + +class TestShellDelegateChromeOS : public test::TestShellDelegate { + public: + TestShellDelegateChromeOS() {} + + TestSessionStateDelegate* CreateSessionStateDelegate() override { + return new TestSessionStateDelegateChromeOS(); + } + + content::BrowserContext* GetActiveBrowserContext() override { + const user_manager::UserManager* user_manager = + user_manager::UserManager::Get(); + const user_manager::User* active_user = user_manager->GetActiveUser(); + return active_user + ? multi_user_util::GetProfileFromUserID(active_user->GetUserID()) + : NULL; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestShellDelegateChromeOS); +}; + // A test class for preparing the chrome::MultiUserWindowManager. It creates // various windows and instantiates the chrome::MultiUserWindowManager. class MultiUserWindowManagerChromeOSTest : public AshTestBase { @@ -43,7 +96,7 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase { MultiUserWindowManagerChromeOSTest() : multi_user_window_manager_(NULL), session_state_delegate_(NULL), - fake_user_manager_(new user_manager::FakeUserManager), + fake_user_manager_(new chromeos::FakeChromeUserManager), user_manager_enabler_(fake_user_manager_) {} void SetUp() override; @@ -81,6 +134,21 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase { return multi_user_window_manager_; } + chromeos::FakeChromeUserManager* user_manager() { return fake_user_manager_; } + + TestingProfileManager* profile_manager() { return profile_manager_.get(); } + + const user_manager::User* AddTestUser(const std::string& user_email) { + const user_manager::User* user = fake_user_manager_->AddUser(user_email); + fake_user_manager_->LoginUser(user_email); + session_state_delegate_->AddUser(user_email); + TestingProfile* profile = + profile_manager()->CreateTestingProfile(user_email); + chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, + profile); + return user; + } + // Returns a list of all open windows in the following form: // "<H(idden)/S(hown)/D(eleted)>[<Owner>[,<shownForUser>]], .." // Like: "S[B], .." would mean that window#0 is shown and belongs to user B. @@ -91,7 +159,7 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase { // Returns a test-friendly string format of GetOwnersOfVisibleWindows(). std::string GetOwnersOfVisibleWindowsAsString(); - TestSessionStateDelegate* session_state_delegate() { + TestSessionStateDelegateChromeOS* session_state_delegate() { return session_state_delegate_; } @@ -160,9 +228,11 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase { chrome::MultiUserWindowManagerChromeOS* multi_user_window_manager_; // The session state delegate. - ash::test::TestSessionStateDelegate* session_state_delegate_; + TestSessionStateDelegateChromeOS* session_state_delegate_; + + chromeos::FakeChromeUserManager* fake_user_manager_; // Not owned. - user_manager::FakeUserManager* fake_user_manager_; // Not owned. + scoped_ptr<TestingProfileManager> profile_manager_; chromeos::ScopedUserManagerEnabler user_manager_enabler_; @@ -173,10 +243,13 @@ class MultiUserWindowManagerChromeOSTest : public AshTestBase { }; void MultiUserWindowManagerChromeOSTest::SetUp() { + ash_test_helper()->set_test_shell_delegate(new TestShellDelegateChromeOS); AshTestBase::SetUp(); - session_state_delegate_ = - static_cast<TestSessionStateDelegate*> ( - ash::Shell::GetInstance()->session_state_delegate()); + session_state_delegate_ = static_cast<TestSessionStateDelegateChromeOS*>( + ash::Shell::GetInstance()->session_state_delegate()); + profile_manager_.reset( + new TestingProfileManager(TestingBrowserProcess::GetGlobal())); + ASSERT_TRUE(profile_manager_.get()->SetUp()); session_state_delegate_->AddUser("a"); session_state_delegate_->AddUser("b"); session_state_delegate_->AddUser("c"); @@ -209,6 +282,7 @@ void MultiUserWindowManagerChromeOSTest::TearDown() { chrome::MultiUserWindowManager::DeleteInstance(); AshTestBase::TearDown(); chromeos::WallpaperManager::Shutdown(); + profile_manager_.reset(); } std::string MultiUserWindowManagerChromeOSTest::GetStatus() { @@ -1183,5 +1257,72 @@ TEST_F(MultiUserWindowManagerChromeOSTest, TransientWindowActivationTest) { ::wm::RemoveTransientChild(window(1), window(2)); } +// Test that minimized window on one desktop can't be activated on another +// desktop. +TEST_F(MultiUserWindowManagerChromeOSTest, MinimizedWindowActivatableTests) { + SetUpForThisManyWindows(4); + + const std::string user1 = "a@test.com"; + const std::string user2 = "b@test.com"; + AddTestUser(user1); + AddTestUser(user2); + session_state_delegate()->set_logged_in_users(2); + + multi_user_window_manager()->SetWindowOwner(window(0), user1); + multi_user_window_manager()->SetWindowOwner(window(1), user1); + multi_user_window_manager()->SetWindowOwner(window(2), user2); + multi_user_window_manager()->SetWindowOwner(window(3), user2); + + // Minimizes window #0 and window #2. + wm::GetWindowState(window(0))->Minimize(); + wm::GetWindowState(window(2))->Minimize(); + + // Windows belonging to user2 (window #2 and #3) can't be activated by user1. + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged(user1); + EXPECT_TRUE(::wm::CanActivateWindow(window(0))); + EXPECT_TRUE(::wm::CanActivateWindow(window(1))); + EXPECT_FALSE(::wm::CanActivateWindow(window(2))); + EXPECT_FALSE(::wm::CanActivateWindow(window(3))); + + // Windows belonging to user1 (window #0 and #1) can't be activated by user2. + user_manager()->SwitchActiveUser(user2); + multi_user_window_manager()->ActiveUserChanged(user2); + EXPECT_FALSE(::wm::CanActivateWindow(window(0))); + EXPECT_FALSE(::wm::CanActivateWindow(window(1))); + EXPECT_TRUE(::wm::CanActivateWindow(window(2))); + EXPECT_TRUE(::wm::CanActivateWindow(window(3))); +} + +// Test that teleported window can be activated by the presenting user. +TEST_F(MultiUserWindowManagerChromeOSTest, TeleportedWindowActivatableTests) { + SetUpForThisManyWindows(2); + + const std::string user1 = "a@test.com"; + const std::string user2 = "b@test.com"; + AddTestUser(user1); + AddTestUser(user2); + session_state_delegate()->set_logged_in_users(2); + + multi_user_window_manager()->SetWindowOwner(window(0), user1); + multi_user_window_manager()->SetWindowOwner(window(1), user2); + + user_manager()->SwitchActiveUser(user1); + multi_user_window_manager()->ActiveUserChanged(user1); + EXPECT_TRUE(::wm::CanActivateWindow(window(0))); + EXPECT_FALSE(::wm::CanActivateWindow(window(1))); + + // Teleports window #0 to user2 desktop. Then window #0 can't be activated by + // user 1. + multi_user_window_manager()->ShowWindowForUser(window(0), user2); + EXPECT_FALSE(::wm::CanActivateWindow(window(0))); + + // Test that window #0 can be activated by user2. + user_manager()->SwitchActiveUser(user2); + multi_user_window_manager()->ActiveUserChanged(user2); + EXPECT_TRUE(::wm::CanActivateWindow(window(0))); + EXPECT_TRUE(::wm::CanActivateWindow(window(1))); +} + } // namespace test } // namespace ash diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc index 9b1edd27..f7dcc0a 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc @@ -18,6 +18,7 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.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 "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" @@ -64,10 +65,18 @@ SessionStateDelegateChromeos::GetBrowserContextForWindow( aura::Window* window) { const std::string& user_id = chrome::MultiUserWindowManager::GetInstance()->GetWindowOwner(window); - const user_manager::User* user = - user_manager::UserManager::Get()->FindUser(user_id); - DCHECK(user); - return chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); + return user_id.empty() ? NULL + : multi_user_util::GetProfileFromUserID(user_id); +} + +content::BrowserContext* +SessionStateDelegateChromeos::GetUserPresentingBrowserContextForWindow( + aura::Window* window) { + const std::string& user_id = + chrome::MultiUserWindowManager::GetInstance()->GetUserPresentingWindow( + window); + return user_id.empty() ? NULL + : multi_user_util::GetProfileFromUserID(user_id); } int SessionStateDelegateChromeos::GetMaximumNumberOfLoggedInUsers() const { diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.h b/chrome/browser/ui/ash/session_state_delegate_chromeos.h index 9e7847f..2b26148 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos.h +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.h @@ -31,6 +31,8 @@ class SessionStateDelegateChromeos ash::MultiProfileIndex index) override; content::BrowserContext* GetBrowserContextForWindow( aura::Window* window) override; + content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) override; int GetMaximumNumberOfLoggedInUsers() const override; int NumberOfLoggedInUsers() const override; bool CanAddUserToMultiProfile(AddUserError* error) const override; diff --git a/chrome/browser/ui/ash/session_state_delegate_views.cc b/chrome/browser/ui/ash/session_state_delegate_views.cc index de814bd..49a116f 100644 --- a/chrome/browser/ui/ash/session_state_delegate_views.cc +++ b/chrome/browser/ui/ash/session_state_delegate_views.cc @@ -28,6 +28,12 @@ content::BrowserContext* SessionStateDelegate::GetBrowserContextForWindow( return NULL; } +content::BrowserContext* +SessionStateDelegate::GetUserPresentingBrowserContextForWindow( + aura::Window* window) { + return NULL; +} + int SessionStateDelegate::GetMaximumNumberOfLoggedInUsers() const { return 3; } diff --git a/chrome/browser/ui/ash/session_state_delegate_views.h b/chrome/browser/ui/ash/session_state_delegate_views.h index 89a3c2f..269b9eb3 100644 --- a/chrome/browser/ui/ash/session_state_delegate_views.h +++ b/chrome/browser/ui/ash/session_state_delegate_views.h @@ -25,6 +25,8 @@ class SessionStateDelegate : public ash::SessionStateDelegate { ash::MultiProfileIndex index) override; content::BrowserContext* GetBrowserContextForWindow( aura::Window* window) override; + content::BrowserContext* GetUserPresentingBrowserContextForWindow( + aura::Window* window) override; int GetMaximumNumberOfLoggedInUsers() const override; int NumberOfLoggedInUsers() const override; bool IsActiveUserSessionStarted() const override; |