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 #include <string> 6 #include <vector> 7 8 #include "base/command_line.h" 9 #include "base/memory/ref_counted.h" 10 #include "base/run_loop.h" 11 #include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" 12 #include "chrome/browser/chromeos/login/user.h" 13 #include "chrome/browser/chromeos/login/user_manager.h" 14 #include "chrome/common/chrome_switches.h" 15 #include "chromeos/chromeos_switches.h" 16 #include "chromeos/dbus/cryptohome_client.h" 17 #include "chromeos/dbus/fake_session_manager_client.h" 18 #include "chromeos/dbus/mock_dbus_thread_manager_without_gmock.h" 19 #include "chromeos/dbus/session_manager_client.h" 20 #include "content/public/test/test_utils.h" 21 #include "testing/gmock/include/gmock/gmock.h" 22 #include "third_party/cros_system_api/dbus/service_constants.h" 23 24 namespace chromeos { 25 26 namespace { 27 28 const char kUserId1[] = "user1 (at) example.com"; 29 const char kUserId2[] = "user2 (at) example.com"; 30 const char kUserId3[] = "user3 (at) example.com"; 31 32 } // namespace 33 34 class CrashRestoreSimpleTest : public CrosInProcessBrowserTest { 35 protected: 36 CrashRestoreSimpleTest() {} 37 38 virtual ~CrashRestoreSimpleTest() {} 39 40 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 41 command_line->AppendSwitch(::switches::kMultiProfiles); 42 command_line->AppendSwitchASCII(switches::kLoginUser, kUserId1); 43 command_line->AppendSwitchASCII( 44 switches::kLoginProfile, 45 CryptohomeClient::GetStubSanitizedUsername(kUserId1)); 46 } 47 48 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 49 // Redirect session_manager DBus calls to FakeSessionManagerClient. 50 MockDBusThreadManagerWithoutGMock* dbus_thread_manager = 51 new MockDBusThreadManagerWithoutGMock(); 52 session_manager_client_ = 53 dbus_thread_manager->fake_session_manager_client(); 54 DBusThreadManager::InitializeForTesting(dbus_thread_manager); 55 session_manager_client_->StartSession(kUserId1); 56 } 57 58 FakeSessionManagerClient* session_manager_client_; 59 }; 60 61 IN_PROC_BROWSER_TEST_F(CrashRestoreSimpleTest, RestoreSessionForOneUser) { 62 UserManager* user_manager = UserManager::Get(); 63 User* user = user_manager->GetActiveUser(); 64 ASSERT_TRUE(user); 65 EXPECT_EQ(kUserId1, user->email()); 66 EXPECT_EQ(CryptohomeClient::GetStubSanitizedUsername(kUserId1), 67 user->username_hash()); 68 EXPECT_EQ(1UL, user_manager->GetLoggedInUsers().size()); 69 } 70 71 // Observer that keeps track of user sessions restore event. 72 class UserSessionRestoreObserver : 73 public UserManager::UserSessionStateObserver { 74 public: 75 UserSessionRestoreObserver() 76 : running_loop_(false), 77 user_sessions_restored_(UserManager::Get()->UserSessionsRestored()) { 78 if (!user_sessions_restored_) 79 UserManager::Get()->AddSessionStateObserver(this); 80 } 81 virtual ~UserSessionRestoreObserver() {} 82 83 virtual void PendingUserSessionsRestoreFinished() OVERRIDE { 84 user_sessions_restored_ = true; 85 UserManager::Get()->RemoveSessionStateObserver(this); 86 if (!running_loop_) 87 return; 88 89 message_loop_runner_->Quit(); 90 running_loop_ = false; 91 } 92 93 // Wait until the user sessions are restored. If that happened between the 94 // construction of this object and this call or even before it was created 95 // then it returns immediately. 96 void Wait() { 97 if (user_sessions_restored_) 98 return; 99 100 running_loop_ = true; 101 message_loop_runner_ = new content::MessageLoopRunner(); 102 message_loop_runner_->Run(); 103 } 104 105 private: 106 bool running_loop_; 107 bool user_sessions_restored_; 108 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 109 110 DISALLOW_COPY_AND_ASSIGN(UserSessionRestoreObserver); 111 }; 112 113 class CrashRestoreComplexTest : public CrashRestoreSimpleTest { 114 protected: 115 CrashRestoreComplexTest() {} 116 virtual ~CrashRestoreComplexTest() {} 117 118 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 119 CrashRestoreSimpleTest::SetUpInProcessBrowserTestFixture(); 120 session_manager_client_->StartSession(kUserId2); 121 session_manager_client_->StartSession(kUserId3); 122 } 123 }; 124 125 IN_PROC_BROWSER_TEST_F(CrashRestoreComplexTest, RestoreSessionForThreeUsers) { 126 { 127 UserSessionRestoreObserver restore_observer; 128 restore_observer.Wait(); 129 } 130 131 UserManager* user_manager = UserManager::Get(); 132 DCHECK(user_manager->UserSessionsRestored()); 133 134 // User that is last in the user sessions map becomes active. This behavior 135 // will become better defined once each user gets a separate user desktop. 136 User* user = user_manager->GetActiveUser(); 137 ASSERT_TRUE(user); 138 EXPECT_EQ(kUserId3, user->email()); 139 EXPECT_EQ(CryptohomeClient::GetStubSanitizedUsername(kUserId3), 140 user->username_hash()); 141 const UserList& users = user_manager->GetLoggedInUsers(); 142 ASSERT_EQ(3UL, users.size()); 143 144 // User that becomes active moves to the beginning of the list. 145 EXPECT_EQ(kUserId3, users[0]->email()); 146 EXPECT_EQ(CryptohomeClient::GetStubSanitizedUsername(kUserId3), 147 users[0]->username_hash()); 148 EXPECT_EQ(kUserId2, users[1]->email()); 149 EXPECT_EQ(CryptohomeClient::GetStubSanitizedUsername(kUserId2), 150 users[1]->username_hash()); 151 EXPECT_EQ(kUserId1, users[2]->email()); 152 EXPECT_EQ(CryptohomeClient::GetStubSanitizedUsername(kUserId1), 153 users[2]->username_hash()); 154 } 155 156 } // namespace chromeos 157