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 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 |