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