OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
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" | |
24 | |
25 namespace { | |
26 | |
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"); | |
31 | |
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"; | |
36 | |
37 } // namespace | |
38 | |
39 namespace chromeos { | |
40 | |
41 class DeviceIDTest : public OobeBaseTest, | |
42 public user_manager::RemoveUserDelegate { | |
43 public: | |
44 void SetUpCommandLine(base::CommandLine* command_line) override { | |
45 OobeBaseTest::SetUpCommandLine(command_line); | |
46 command_line->AppendSwitch(switches::kOobeSkipPostLogin); | |
47 } | |
48 | |
49 void SetUpOnMainThread() override { | |
50 OobeBaseTest::SetUpOnMainThread(); | |
51 LoadRefreshTokenToDeviceIdMap(); | |
52 } | |
53 | |
54 void TearDownOnMainThread() override { | |
55 SaveRefreshTokenToDeviceIdMap(); | |
56 OobeBaseTest::TearDownOnMainThread(); | |
57 } | |
58 | |
59 std::string GetDeviceId(const std::string& user_id) { | |
60 return user_manager::UserManager::Get()->GetKnownUserDeviceId(user_id); | |
61 } | |
62 | |
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(); | |
68 } | |
69 | |
70 std::string GetDeviceIdFromGAIA(const std::string& refresh_token) { | |
71 return fake_gaia_->GetDeviceIdByRefreshToken(refresh_token); | |
72 } | |
73 | |
74 // Checks that user's device ID retrieved from UserManager and SigninClient | |
75 // are the same. | |
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); | |
83 | |
84 EXPECT_FALSE(device_id_in_signin_client.empty()); | |
85 EXPECT_EQ(device_id_in_signin_client, device_id_in_local_state); | |
86 | |
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); | |
90 } | |
91 } | |
92 | |
93 void WaitForSessionStart() { | |
94 content::WindowedNotificationObserver( | |
95 chrome::NOTIFICATION_SESSION_STARTED, | |
96 content::NotificationService::AllSources()).Wait(); | |
97 } | |
98 | |
99 void SignInOnline(const std::string& user_id, | |
100 const std::string& password, | |
101 const std::string& refresh_token) { | |
102 WaitForGaiaPageLoad(); | |
103 | |
104 FakeGaia::MergeSessionParams params; | |
105 params.email = user_id; | |
106 params.refresh_token = refresh_token; | |
107 fake_gaia_->UpdateMergeSessionParams(params); | |
108 | |
109 GetLoginDisplay()->ShowSigninScreenForCreds(user_id, password); | |
110 WaitForSessionStart(); | |
111 } | |
112 | |
113 void SignInOffline(const std::string& user_id, const std::string& password) { | |
114 WaitForSigninScreen(); | |
115 | |
116 JS().Execute( | |
117 base::StringPrintf("chrome.send('authenticateUser', ['%s', '%s'])", | |
118 user_id.c_str(), password.c_str())); | |
119 WaitForSessionStart(); | |
120 } | |
121 | |
122 void RemoveUser(const std::string& user_id) { | |
123 user_manager::UserManager::Get()->RemoveUser(user_id, this); | |
124 user_removal_loop_.Run(); | |
125 } | |
126 | |
127 private: | |
128 // user_manager::RemoveUserDelegate: | |
129 void OnBeforeUserRemoved(const std::string& username) override {} | |
130 | |
131 void OnUserRemoved(const std::string& username) override { | |
132 user_removal_loop_.Quit(); | |
133 } | |
134 | |
135 base::FilePath GetRefreshTokenToDeviceIdMapFilePath() const { | |
136 return base::CommandLine::ForCurrentProcess() | |
137 ->GetSwitchValuePath(::switches::kUserDataDir) | |
138 .Append(kRefreshTokenToDeviceIdMapFile); | |
139 } | |
140 | |
141 void LoadRefreshTokenToDeviceIdMap() { | |
142 std::string file_contents; | |
143 if (!base::ReadFileToString(GetRefreshTokenToDeviceIdMapFilePath(), | |
144 &file_contents)) | |
145 return; | |
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(); | |
151 it.Advance()) { | |
152 std::string device_id; | |
153 EXPECT_TRUE(it.value().GetAsString(&device_id)); | |
154 map[it.key()] = device_id; | |
155 } | |
156 fake_gaia_->SetRefreshTokenToDeviceIdMap(map); | |
157 } | |
158 | |
159 void SaveRefreshTokenToDeviceIdMap() const { | |
achuithb
2015/05/28 00:18:57
nit: I'd remove the const here; the function is no
dzhioev (left Google)
2015/05/28 02:21:42
Done.
| |
160 base::DictionaryValue dictionary; | |
161 for (const auto& kv : fake_gaia_->refresh_token_to_device_id_map()) | |
162 dictionary.SetStringWithoutPathExpansion(kv.first, kv.second); | |
163 std::string json; | |
164 EXPECT_TRUE(base::JSONWriter::Write(dictionary, &json)); | |
165 EXPECT_TRUE(base::WriteFile(GetRefreshTokenToDeviceIdMapFilePath(), | |
166 json.c_str(), json.length())); | |
167 } | |
168 | |
169 base::RunLoop user_removal_loop_; | |
170 }; | |
171 | |
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); | |
176 } | |
177 | |
178 // Authenticate the first user through GAIA and verify that device ID remains | |
179 // the same. | |
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)); | |
184 | |
185 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken2); | |
186 CheckDeviceIDIsConsistent(kFakeUserEmail, kRefreshToken2); | |
187 | |
188 CHECK_EQ(device_id, GetDeviceId(kFakeUserEmail)); | |
189 } | |
190 | |
191 // Authenticate the first user offline and verify that device ID remains | |
192 // the same. | |
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()); | |
196 | |
197 SignInOffline(kFakeUserEmail, kFakeUserPassword); | |
198 CheckDeviceIDIsConsistent(kFakeUserEmail, kRefreshToken2); | |
199 | |
200 // Verify that device ID remained the same after offline auth. | |
201 CHECK_EQ(device_id, GetDeviceId(kFakeUserEmail)); | |
202 } | |
203 | |
204 // Add the second user. | |
205 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_NewUsers) { | |
206 WaitForSigninScreen(); | |
207 JS().Execute("chrome.send('showAddUser')"); | |
208 SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken1); | |
209 CheckDeviceIDIsConsistent(kSecondUserEmail, kSecondUserRefreshToken1); | |
210 } | |
211 | |
212 // Remove the second user. | |
213 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_NewUsers) { | |
214 WaitForSigninScreen(); | |
215 RemoveUser(kSecondUserEmail); | |
216 } | |
217 | |
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)); | |
225 } | |
226 | |
227 // Set up an user that has device ID stored in preference only. | |
achuithb
2015/05/28 00:18:57
// Set up a user that has a device ID stored in pr
dzhioev (left Google)
2015/05/28 02:21:42
Done.
| |
228 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_Migration) { | |
229 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
230 | |
231 // Simulate user that has device ID saved only in preferences (pre-M44). | |
232 PrefService* prefs = | |
233 ProfileHelper::Get() | |
234 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser()) | |
235 ->GetPrefs(); | |
236 prefs->SetString(prefs::kGoogleServicesSigninScopedDeviceId, | |
237 GetDeviceId(kFakeUserEmail)); | |
238 | |
239 // Can't use SetKnownUserDeviceId here, because it forbids changing a device | |
240 // ID. | |
241 user_manager::UserManager::Get()->SetKnownUserStringPref( | |
242 kFakeUserEmail, "device_id", std::string()); | |
243 } | |
244 | |
245 // Tests that after the first sign in the device ID has been moved to the Local | |
246 // state. | |
247 IN_PROC_BROWSER_TEST_F(DeviceIDTest, Migration) { | |
248 EXPECT_TRUE(GetDeviceId(kFakeUserEmail).empty()); | |
249 SignInOffline(kFakeUserEmail, kFakeUserPassword); | |
250 CheckDeviceIDIsConsistent(kFakeUserEmail, kRefreshToken1); | |
251 } | |
252 | |
253 // Set up an user that doesn't have device ID. | |
achuithb
2015/05/28 00:18:57
// Set up a user that doesn't have a device ID.
dzhioev (left Google)
2015/05/28 02:21:42
Done.
| |
254 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_LegacyUsers) { | |
255 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
256 | |
257 PrefService* prefs = | |
258 ProfileHelper::Get() | |
259 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser()) | |
260 ->GetPrefs(); | |
261 EXPECT_TRUE( | |
262 prefs->GetString(prefs::kGoogleServicesSigninScopedDeviceId).empty()); | |
263 | |
264 // Can't use SetKnownUserDeviceId here, because it forbids changing a device | |
265 // ID. | |
266 user_manager::UserManager::Get()->SetKnownUserStringPref( | |
267 kFakeUserEmail, "device_id", std::string()); | |
268 } | |
269 | |
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 | |
275 // in this case. | |
276 CheckDeviceIDIsConsistent(kFakeUserEmail, std::string()); | |
277 } | |
278 | |
279 } // namespace chromeos | |
OLD | NEW |