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