1 // Copyright 2015 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.
5 #include "base/command_line.h"
6 #include "base/files/file_path.h"
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
14 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
15 #include "chrome/browser/chromeos/login/ui/oobe_display.h"
16 #include "chrome/browser/chromeos/profiles/profile_helper.h"
17 #include "chrome/browser/signin/chrome_signin_client_factory.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "chromeos/chromeos_switches.h"
21 #include "components/signin/core/common/signin_pref_names.h"
22 #include "components/user_manager/remove_user_delegate.h"
23 #include "components/user_manager/user_manager.h"
27 char kRefreshToken1
[] = "refresh_token_1";
28 char kRefreshToken2
[] = "refresh_token_2";
29 const base::FilePath::CharType kRefreshTokenToDeviceIdMapFile
[] =
30 FILE_PATH_LITERAL("refrest_token_to_device_id.json");
32 char kSecondUserEmail
[] = "second_user@gmail.com";
33 char kSecondUserPassword
[] = "password";
34 char kSecondUserRefreshToken1
[] = "refresh_token_second_user_1";
35 char kSecondUserRefreshToken2
[] = "refresh_token_second_user_2";
41 class DeviceIDTest
: public OobeBaseTest
,
42 public user_manager::RemoveUserDelegate
{
44 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
45 OobeBaseTest::SetUpCommandLine(command_line
);
46 command_line
->AppendSwitch(switches::kOobeSkipPostLogin
);
49 void SetUpOnMainThread() override
{
50 OobeBaseTest::SetUpOnMainThread();
51 LoadRefreshTokenToDeviceIdMap();
54 void TearDownOnMainThread() override
{
55 SaveRefreshTokenToDeviceIdMap();
56 OobeBaseTest::TearDownOnMainThread();
59 std::string
GetDeviceId(const std::string
& user_id
) {
60 return user_manager::UserManager::Get()->GetKnownUserDeviceId(user_id
);
63 std::string
GetDeviceIdFromSigninClient(const std::string
& user_id
) {
64 return ChromeSigninClientFactory::GetForProfile(
65 ProfileHelper::Get()->GetProfileByUser(
66 user_manager::UserManager::Get()->FindUser(user_id
)))
67 ->GetSigninScopedDeviceId();
70 std::string
GetDeviceIdFromGAIA(const std::string
& refresh_token
) {
71 return fake_gaia_
->GetDeviceIdByRefreshToken(refresh_token
);
74 // Checks that user's device ID retrieved from UserManager and SigninClient
76 // If |refresh_token| is not empty, checks that device ID associated with the
77 // |refresh_token| in GAIA is the same as ID saved on device.
78 void CheckDeviceIDIsConsistent(const std::string
& user_id
,
79 const std::string
& refresh_token
) {
80 const std::string device_id_in_signin_client
=
81 GetDeviceIdFromSigninClient(user_id
);
82 const std::string device_id_in_local_state
= GetDeviceId(user_id
);
84 EXPECT_FALSE(device_id_in_signin_client
.empty());
85 EXPECT_EQ(device_id_in_signin_client
, device_id_in_local_state
);
87 if (!refresh_token
.empty()) {
88 const std::string device_id_in_gaia
= GetDeviceIdFromGAIA(refresh_token
);
89 EXPECT_EQ(device_id_in_signin_client
, device_id_in_gaia
);
93 void WaitForSessionStart() {
94 content::WindowedNotificationObserver(
95 chrome::NOTIFICATION_SESSION_STARTED
,
96 content::NotificationService::AllSources()).Wait();
99 void SignInOnline(const std::string
& user_id
,
100 const std::string
& password
,
101 const std::string
& refresh_token
) {
102 WaitForGaiaPageLoad();
104 FakeGaia::MergeSessionParams params
;
105 params
.email
= user_id
;
106 params
.refresh_token
= refresh_token
;
107 fake_gaia_
->UpdateMergeSessionParams(params
);
109 GetLoginDisplay()->ShowSigninScreenForCreds(user_id
, password
);
110 WaitForSessionStart();
113 void SignInOffline(const std::string
& user_id
, const std::string
& password
) {
114 WaitForSigninScreen();
117 base::StringPrintf("chrome.send('authenticateUser', ['%s', '%s'])",
118 user_id
.c_str(), password
.c_str()));
119 WaitForSessionStart();
122 void RemoveUser(const std::string
& user_id
) {
123 user_manager::UserManager::Get()->RemoveUser(user_id
, this);
124 user_removal_loop_
.Run();
128 // user_manager::RemoveUserDelegate:
129 void OnBeforeUserRemoved(const std::string
& username
) override
{}
131 void OnUserRemoved(const std::string
& username
) override
{
132 user_removal_loop_
.Quit();
135 base::FilePath
GetRefreshTokenToDeviceIdMapFilePath() const {
136 return base::CommandLine::ForCurrentProcess()
137 ->GetSwitchValuePath(::switches::kUserDataDir
)
138 .Append(kRefreshTokenToDeviceIdMapFile
);
141 void LoadRefreshTokenToDeviceIdMap() {
142 std::string file_contents
;
143 if (!base::ReadFileToString(GetRefreshTokenToDeviceIdMapFilePath(),
146 scoped_ptr
<base::Value
> value(base::JSONReader::Read(file_contents
));
147 base::DictionaryValue
* dictionary
;
148 EXPECT_TRUE(value
->GetAsDictionary(&dictionary
));
149 FakeGaia::RefreshTokenToDeviceIdMap map
;
150 for (base::DictionaryValue::Iterator
it(*dictionary
); !it
.IsAtEnd();
152 std::string device_id
;
153 EXPECT_TRUE(it
.value().GetAsString(&device_id
));
154 map
[it
.key()] = device_id
;
156 fake_gaia_
->SetRefreshTokenToDeviceIdMap(map
);
159 void SaveRefreshTokenToDeviceIdMap() {
160 base::DictionaryValue dictionary
;
161 for (const auto& kv
: fake_gaia_
->refresh_token_to_device_id_map())
162 dictionary
.SetStringWithoutPathExpansion(kv
.first
, kv
.second
);
164 EXPECT_TRUE(base::JSONWriter::Write(dictionary
, &json
));
165 EXPECT_TRUE(base::WriteFile(GetRefreshTokenToDeviceIdMapFilePath(),
166 json
.c_str(), json
.length()));
169 base::RunLoop user_removal_loop_
;
172 // Add the first user and check that device ID is consistent.
173 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_PRE_PRE_PRE_PRE_NewUsers
) {
174 SignInOnline(kFakeUserEmail
, kFakeUserPassword
, kRefreshToken1
);
175 CheckDeviceIDIsConsistent(kFakeUserEmail
, kRefreshToken1
);
178 // Authenticate the first user through GAIA and verify that device ID remains
180 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_PRE_PRE_PRE_NewUsers
) {
181 const std::string device_id
= GetDeviceId(kFakeUserEmail
);
182 EXPECT_FALSE(device_id
.empty());
183 EXPECT_EQ(device_id
, GetDeviceIdFromGAIA(kRefreshToken1
));
185 SignInOnline(kFakeUserEmail
, kFakeUserPassword
, kRefreshToken2
);
186 CheckDeviceIDIsConsistent(kFakeUserEmail
, kRefreshToken2
);
188 CHECK_EQ(device_id
, GetDeviceId(kFakeUserEmail
));
191 // Authenticate the first user offline and verify that device ID remains
193 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_PRE_PRE_NewUsers
) {
194 const std::string device_id
= GetDeviceId(kFakeUserEmail
);
195 EXPECT_FALSE(device_id
.empty());
197 SignInOffline(kFakeUserEmail
, kFakeUserPassword
);
198 CheckDeviceIDIsConsistent(kFakeUserEmail
, kRefreshToken2
);
200 // Verify that device ID remained the same after offline auth.
201 CHECK_EQ(device_id
, GetDeviceId(kFakeUserEmail
));
204 // Add the second user.
205 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_PRE_NewUsers
) {
206 WaitForSigninScreen();
207 JS().ExecuteAsync("chrome.send('showAddUser')");
208 SignInOnline(kSecondUserEmail
, kSecondUserPassword
, kSecondUserRefreshToken1
);
209 CheckDeviceIDIsConsistent(kSecondUserEmail
, kSecondUserRefreshToken1
);
212 // Remove the second user.
213 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_NewUsers
) {
214 WaitForSigninScreen();
215 RemoveUser(kSecondUserEmail
);
218 // Add the second user back. Verify that device ID has been changed.
219 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, NewUsers
) {
220 EXPECT_TRUE(GetDeviceId(kSecondUserEmail
).empty());
221 SignInOnline(kSecondUserEmail
, kSecondUserPassword
, kSecondUserRefreshToken2
);
222 CheckDeviceIDIsConsistent(kSecondUserEmail
, kSecondUserRefreshToken2
);
223 EXPECT_NE(GetDeviceIdFromGAIA(kSecondUserRefreshToken1
),
224 GetDeviceId(kSecondUserEmail
));
227 // Set up a user that has a device ID stored in preference only.
228 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_Migration
) {
229 SignInOnline(kFakeUserEmail
, kFakeUserPassword
, kRefreshToken1
);
231 // Simulate user that has device ID saved only in preferences (pre-M44).
234 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser())
236 prefs
->SetString(prefs::kGoogleServicesSigninScopedDeviceId
,
237 GetDeviceId(kFakeUserEmail
));
239 // Can't use SetKnownUserDeviceId here, because it forbids changing a device
241 user_manager::UserManager::Get()->SetKnownUserStringPref(
242 kFakeUserEmail
, "device_id", std::string());
245 // Tests that after the first sign in the device ID has been moved to the Local
247 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, Migration
) {
248 EXPECT_TRUE(GetDeviceId(kFakeUserEmail
).empty());
249 SignInOffline(kFakeUserEmail
, kFakeUserPassword
);
250 CheckDeviceIDIsConsistent(kFakeUserEmail
, kRefreshToken1
);
253 // Set up a user that doesn't have a device ID.
254 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, PRE_LegacyUsers
) {
255 SignInOnline(kFakeUserEmail
, kFakeUserPassword
, kRefreshToken1
);
259 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser())
262 prefs
->GetString(prefs::kGoogleServicesSigninScopedDeviceId
).empty());
264 // Can't use SetKnownUserDeviceId here, because it forbids changing a device
266 user_manager::UserManager::Get()->SetKnownUserStringPref(
267 kFakeUserEmail
, "device_id", std::string());
270 // Tests that device ID has been generated after the first sign in.
271 IN_PROC_BROWSER_TEST_F(DeviceIDTest
, LegacyUsers
) {
272 EXPECT_TRUE(GetDeviceId(kFakeUserEmail
).empty());
273 SignInOffline(kFakeUserEmail
, kFakeUserPassword
);
274 // Last param |auth_code| is empty, because we don't pass a device ID to GAIA
276 CheckDeviceIDIsConsistent(kFakeUserEmail
, std::string());
279 } // namespace chromeos