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