Chromium Code Reviews| 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 kRefreshTokenToDeviceIdMapPath[] = | |
|
achuithb
2015/05/26 06:28:20
kRefreshTokenToDeviceIdMapFile or kRefreshTokenToD
dzhioev (left Google)
2015/05/26 21:18:15
Done.
| |
| 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 std::string device_id_in_signin_client = | |
|
achuithb
2015/05/26 06:28:20
nit: const
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 81 GetDeviceIdFromSigninClient(user_id); | |
| 82 std::string device_id_in_local_state = GetDeviceId(user_id); | |
|
achuithb
2015/05/26 06:28:20
nit: const
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 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 std::string device_id_in_gaia = GetDeviceIdFromGAIA(refresh_token); | |
|
achuithb
2015/05/26 06:28:20
nit: const
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 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 CheckDeviceIDIsConsistent(user_id, refresh_token); | |
|
achuithb
2015/05/26 06:28:20
I feel you should pull this function out and expli
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 113 } | |
| 114 | |
| 115 void SignInOffline(const std::string& user_id, | |
| 116 const std::string& password, | |
| 117 const std::string& refresh_token) { | |
| 118 WaitForSigninScreen(); | |
| 119 | |
| 120 JS().Execute( | |
| 121 base::StringPrintf("chrome.send('authenticateUser', ['%s', '%s'])", | |
| 122 user_id.c_str(), password.c_str())); | |
| 123 WaitForSessionStart(); | |
| 124 | |
| 125 CheckDeviceIDIsConsistent(user_id, refresh_token); | |
|
achuithb
2015/05/26 06:28:20
Same
dzhioev (left Google)
2015/05/26 21:18:15
Done.
| |
| 126 } | |
| 127 | |
| 128 void RemoveUser(const std::string& user_id) { | |
| 129 user_manager::UserManager::Get()->RemoveUser(user_id, this); | |
| 130 user_removal_loop_.Run(); | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 void OnBeforeUserRemoved(const std::string& username) override {} | |
|
achuithb
2015/05/26 06:28:19
// RemoveUserDelegate:
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 135 | |
| 136 void OnUserRemoved(const std::string& username) override { | |
| 137 user_removal_loop_.Quit(); | |
| 138 } | |
| 139 | |
| 140 void LoadRefreshTokenToDeviceIdMap() { | |
| 141 base::FilePath path = base::CommandLine::ForCurrentProcess() | |
|
achuithb
2015/05/26 06:28:20
nit: const, also a slightly more descriptive name
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 142 ->GetSwitchValuePath(::switches::kUserDataDir) | |
| 143 .Append(kRefreshTokenToDeviceIdMapPath); | |
| 144 std::string file_contents; | |
| 145 if (!base::ReadFileToString(path, &file_contents)) | |
| 146 return; | |
|
achuithb
2015/05/26 06:28:20
When is this a valid outcome?
dzhioev (left Google)
2015/05/26 21:18:15
When the file doesn't exist. This happens in the v
| |
| 147 scoped_ptr<base::Value> value(base::JSONReader::Read(file_contents)); | |
| 148 base::DictionaryValue* dictionary; | |
| 149 EXPECT_TRUE(value->GetAsDictionary(&dictionary)); | |
| 150 FakeGaia::RefreshTokenToDeviceIdMap map; | |
| 151 for (base::DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); | |
|
achuithb
2015/05/26 06:28:20
Why not auto here?
dzhioev (left Google)
2015/05/26 21:18:14
base::Dictionary doesn't have begin() method retur
| |
| 152 it.Advance()) { | |
| 153 std::string device_id; | |
| 154 EXPECT_TRUE(it.value().GetAsString(&device_id)); | |
| 155 map[it.key()] = device_id; | |
| 156 } | |
| 157 fake_gaia_->SetRefreshTokenToDeviceIdMap(map); | |
| 158 } | |
| 159 | |
| 160 void SaveRefreshTokenToDeviceIdMap() const { | |
| 161 base::DictionaryValue dictionary; | |
| 162 for (const auto& kv : fake_gaia_->refresh_token_to_device_id_map()) | |
| 163 dictionary.SetStringWithoutPathExpansion(kv.first, kv.second); | |
| 164 std::string json; | |
| 165 EXPECT_TRUE(base::JSONWriter::Write(dictionary, &json)); | |
| 166 base::FilePath path = base::CommandLine::ForCurrentProcess() | |
|
achuithb
2015/05/26 06:28:20
nit: const, also more descriptive name.
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 167 ->GetSwitchValuePath(::switches::kUserDataDir) | |
| 168 .Append(kRefreshTokenToDeviceIdMapPath); | |
| 169 EXPECT_TRUE(base::WriteFile(path, json.c_str(), json.length())); | |
| 170 } | |
| 171 | |
| 172 base::RunLoop user_removal_loop_; | |
| 173 }; | |
| 174 | |
| 175 // Add the first user and check that device ID is consistent. | |
| 176 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_PRE_PRE_NewUsers) { | |
| 177 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
| 178 } | |
| 179 | |
| 180 // Authenticate the first user through GAIA and verify that device ID remains | |
| 181 // the same. | |
| 182 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_PRE_NewUsers) { | |
| 183 std::string device_id = GetDeviceId(kFakeUserEmail); | |
|
achuithb
2015/05/26 06:28:20
nit: const
dzhioev (left Google)
2015/05/26 21:18:15
Done.
| |
| 184 EXPECT_FALSE(device_id.empty()); | |
| 185 EXPECT_EQ(device_id, GetDeviceIdFromGAIA(kRefreshToken1)); | |
| 186 | |
| 187 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken2); | |
| 188 | |
| 189 CHECK_EQ(device_id, GetDeviceId(kFakeUserEmail)); | |
| 190 } | |
| 191 | |
| 192 // Authenticate the first user online and verify that device ID remains | |
| 193 // the same. | |
| 194 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_NewUsers) { | |
| 195 std::string device_id = GetDeviceId(kFakeUserEmail); | |
|
achuithb
2015/05/26 06:28:20
nit:const
dzhioev (left Google)
2015/05/26 21:18:14
Done.
| |
| 196 EXPECT_FALSE(device_id.empty()); | |
| 197 | |
| 198 SignInOffline(kFakeUserEmail, kFakeUserPassword, 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 } | |
| 210 | |
| 211 // Remove the second user. | |
| 212 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_NewUsers) { | |
| 213 WaitForSigninScreen(); | |
| 214 RemoveUser(kSecondUserEmail); | |
| 215 } | |
| 216 | |
| 217 // Add the second user back. Verify that device ID has been changed. | |
| 218 IN_PROC_BROWSER_TEST_F(DeviceIDTest, NewUsers) { | |
| 219 EXPECT_TRUE(GetDeviceId(kSecondUserEmail).empty()); | |
| 220 SignInOnline(kSecondUserEmail, kSecondUserPassword, kSecondUserRefreshToken2); | |
| 221 EXPECT_NE(GetDeviceIdFromGAIA(kSecondUserRefreshToken1), | |
| 222 GetDeviceId(kSecondUserEmail)); | |
| 223 } | |
| 224 | |
| 225 // Tests migration process from the old way of storing device ID (in | |
| 226 // preference), to the new one (in Local State). | |
| 227 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_Migration) { | |
|
achuithb
2015/05/26 06:28:20
This "test" isn't testing anything, is it?
If it'
dzhioev (left Google)
2015/05/26 21:18:15
Yes, that is PRE test case where we set up the sta
| |
| 228 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
| 229 | |
| 230 // Simulate user that has device ID saved only in preferences (pre-M44). | |
| 231 PrefService* prefs = | |
| 232 ProfileHelper::Get() | |
| 233 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser()) | |
| 234 ->GetPrefs(); | |
| 235 prefs->SetString(prefs::kGoogleServicesSigninScopedDeviceId, | |
| 236 GetDeviceId(kFakeUserEmail)); | |
| 237 | |
| 238 // Can't use SetKnownUserDeviceId here, because it forbids changing a device | |
| 239 // ID. | |
| 240 user_manager::UserManager::Get()->SetKnownUserStringPref( | |
| 241 kFakeUserEmail, "device_id", std::string()); | |
| 242 } | |
| 243 | |
| 244 IN_PROC_BROWSER_TEST_F(DeviceIDTest, Migration) { | |
| 245 EXPECT_TRUE(GetDeviceId(kFakeUserEmail).empty()); | |
| 246 SignInOffline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
| 247 } | |
| 248 | |
| 249 // Tests that device ID is generated for users that has device ID stored neither | |
| 250 // in preference, nor in Local State. | |
| 251 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_LegacyUsers) { | |
| 252 SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1); | |
| 253 | |
| 254 PrefService* prefs = | |
| 255 ProfileHelper::Get() | |
| 256 ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser()) | |
| 257 ->GetPrefs(); | |
| 258 EXPECT_TRUE( | |
| 259 prefs->GetString(prefs::kGoogleServicesSigninScopedDeviceId).empty()); | |
| 260 | |
| 261 // Can't use SetKnownUserDeviceId here, because it forbids changing a device | |
| 262 // ID. | |
| 263 user_manager::UserManager::Get()->SetKnownUserStringPref( | |
| 264 kFakeUserEmail, "device_id", std::string()); | |
| 265 } | |
| 266 | |
| 267 IN_PROC_BROWSER_TEST_F(DeviceIDTest, LegacyUsers) { | |
| 268 EXPECT_TRUE(GetDeviceId(kFakeUserEmail).empty()); | |
| 269 // Last param |auth_code| is empty, because we don't pass a device ID to GAIA | |
| 270 // in this case. | |
| 271 SignInOffline(kFakeUserEmail, kFakeUserPassword, std::string()); | |
| 272 } | |
| 273 | |
| 274 } // namespace chromeos | |
| OLD | NEW |