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() { |
| 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 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); |
| 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 a user that doesn't have a device ID. |
| 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 |