mutable_profile_oauth2_token_service_unittest.cc revision 4ad1aa43a48567659193a298fad74f55e00b3dd9
1// Copyright 2014 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 "components/signin/core/browser/mutable_profile_oauth2_token_service.h" 6 7#include "base/run_loop.h" 8#include "components/signin/core/browser/profile_oauth2_token_service.h" 9#include "components/signin/core/browser/signin_error_controller.h" 10#include "components/signin/core/browser/test_signin_client.h" 11#include "components/signin/core/browser/webdata/token_web_data.h" 12#include "google_apis/gaia/gaia_constants.h" 13#include "google_apis/gaia/gaia_urls.h" 14#include "google_apis/gaia/oauth2_token_service_test_util.h" 15#include "net/http/http_status_code.h" 16#include "net/url_request/test_url_fetcher_factory.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19#if defined(OS_MACOSX) 20#include "components/os_crypt/os_crypt.h" 21#endif 22 23// Defining constant here to handle backward compatiblity tests, but this 24// constant is no longer used in current versions of chrome. 25static const char kLSOService[] = "lso"; 26static const char kEmail[] = "user@gmail.com"; 27 28class MutableProfileOAuth2TokenServiceTest 29 : public testing::Test, 30 public OAuth2TokenService::Observer { 31 public: 32 MutableProfileOAuth2TokenServiceTest() 33 : factory_(NULL), 34 token_available_count_(0), 35 token_revoked_count_(0), 36 tokens_loaded_count_(0) {} 37 38 virtual void SetUp() OVERRIDE { 39#if defined(OS_MACOSX) 40 OSCrypt::UseMockKeychain(true); 41#endif 42 43 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(), 44 "", 45 net::HTTP_OK, 46 net::URLRequestStatus::SUCCESS); 47 oauth2_service_.Initialize(&client_); 48 // Make sure PO2TS has a chance to load itself before continuing. 49 base::RunLoop().RunUntilIdle(); 50 oauth2_service_.AddObserver(this); 51 } 52 53 virtual void TearDown() OVERRIDE { 54 oauth2_service_.RemoveObserver(this); 55 oauth2_service_.Shutdown(); 56 } 57 58 void AddAuthTokenManually(const std::string& service, 59 const std::string& value) { 60 scoped_refptr<TokenWebData> token_web_data = client_.GetDatabase(); 61 if (token_web_data.get()) 62 token_web_data->SetTokenForService(service, value); 63 } 64 65 // OAuth2TokenService::Observer implementation. 66 virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE { 67 ++token_available_count_; 68 } 69 virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE { 70 ++token_revoked_count_; 71 } 72 virtual void OnRefreshTokensLoaded() OVERRIDE { ++tokens_loaded_count_; } 73 74 void ResetObserverCounts() { 75 token_available_count_ = 0; 76 token_revoked_count_ = 0; 77 tokens_loaded_count_ = 0; 78 } 79 80 void ExpectNoNotifications() { 81 EXPECT_EQ(0, token_available_count_); 82 EXPECT_EQ(0, token_revoked_count_); 83 EXPECT_EQ(0, tokens_loaded_count_); 84 ResetObserverCounts(); 85 } 86 87 void ExpectOneTokenAvailableNotification() { 88 EXPECT_EQ(1, token_available_count_); 89 EXPECT_EQ(0, token_revoked_count_); 90 EXPECT_EQ(0, tokens_loaded_count_); 91 ResetObserverCounts(); 92 } 93 94 void ExpectOneTokenRevokedNotification() { 95 EXPECT_EQ(0, token_available_count_); 96 EXPECT_EQ(1, token_revoked_count_); 97 EXPECT_EQ(0, tokens_loaded_count_); 98 ResetObserverCounts(); 99 } 100 101 void ExpectOneTokensLoadedNotification() { 102 EXPECT_EQ(0, token_available_count_); 103 EXPECT_EQ(0, token_revoked_count_); 104 EXPECT_EQ(1, tokens_loaded_count_); 105 ResetObserverCounts(); 106 } 107 108 protected: 109 base::MessageLoop message_loop_; 110 net::FakeURLFetcherFactory factory_; 111 TestSigninClient client_; 112 MutableProfileOAuth2TokenService oauth2_service_; 113 TestingOAuth2TokenServiceConsumer consumer_; 114 int token_available_count_; 115 int token_revoked_count_; 116 int tokens_loaded_count_; 117}; 118 119TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) { 120 std::string main_account_id(kEmail); 121 std::string main_refresh_token("old_refresh_token"); 122 123 // Populate DB with legacy tokens. 124 AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken"); 125 AddAuthTokenManually(kLSOService, "lsoToken"); 126 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken, 127 main_refresh_token); 128 129 // Force LoadCredentials. 130 oauth2_service_.LoadCredentials(main_account_id); 131 base::RunLoop().RunUntilIdle(); 132 133 // Legacy tokens get discarded, but the old refresh token is kept. 134 EXPECT_EQ(1, tokens_loaded_count_); 135 EXPECT_EQ(1, token_available_count_); 136 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id)); 137 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size()); 138 EXPECT_EQ(main_refresh_token, 139 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token()); 140 141 // Add an old legacy token to the DB, to ensure it will not overwrite existing 142 // credentials for main account. 143 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken, 144 "secondOldRefreshToken"); 145 // Add some other legacy token. (Expected to get discarded). 146 AddAuthTokenManually(kLSOService, "lsoToken"); 147 // Also add a token using PO2TS.UpdateCredentials and make sure upgrade does 148 // not wipe it. 149 std::string other_account_id("other_account_id"); 150 std::string other_refresh_token("other_refresh_token"); 151 oauth2_service_.UpdateCredentials(other_account_id, other_refresh_token); 152 ResetObserverCounts(); 153 154 // Force LoadCredentials. 155 oauth2_service_.LoadCredentials(main_account_id); 156 base::RunLoop().RunUntilIdle(); 157 158 // Again legacy tokens get discarded, but since the main porfile account 159 // token is present it is not overwritten. 160 EXPECT_EQ(2, token_available_count_); 161 EXPECT_EQ(1, tokens_loaded_count_); 162 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id)); 163 // TODO(fgorski): cover both using RefreshTokenIsAvailable() and then get the 164 // tokens using GetRefreshToken() 165 EXPECT_EQ(2U, oauth2_service_.refresh_tokens().size()); 166 EXPECT_EQ(main_refresh_token, 167 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token()); 168 EXPECT_EQ( 169 other_refresh_token, 170 oauth2_service_.refresh_tokens()[other_account_id]->refresh_token()); 171 172 oauth2_service_.RevokeAllCredentials(); 173} 174 175TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceRevokeCredentials) { 176 std::string account_id_1 = "account_id_1"; 177 std::string refresh_token_1 = "refresh_token_1"; 178 std::string account_id_2 = "account_id_2"; 179 std::string refresh_token_2 = "refresh_token_2"; 180 181 // TODO(fgorski): Enable below when implemented: 182 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1)); 183 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_2)); 184 185 oauth2_service_.UpdateCredentials(account_id_1, refresh_token_1); 186 oauth2_service_.UpdateCredentials(account_id_2, refresh_token_2); 187 188 // TODO(fgorski): Enable below when implemented: 189 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1)); 190 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2)); 191 192 ResetObserverCounts(); 193 oauth2_service_.RevokeCredentials(account_id_1); 194 ExpectOneTokenRevokedNotification(); 195 196 // TODO(fgorski): Enable below when implemented: 197 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1)); 198 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2)); 199 200 oauth2_service_.RevokeAllCredentials(); 201 EXPECT_EQ(0, token_available_count_); 202 EXPECT_EQ(1, token_revoked_count_); 203 EXPECT_EQ(0, tokens_loaded_count_); 204 ResetObserverCounts(); 205} 206 207TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceLoadCredentials) { 208 // Ensure DB is clean. 209 oauth2_service_.RevokeAllCredentials(); 210 ResetObserverCounts(); 211 // Perform a load from an empty DB. 212 oauth2_service_.LoadCredentials("account_id"); 213 base::RunLoop().RunUntilIdle(); 214 ExpectOneTokensLoadedNotification(); 215 // LoadCredentials() guarantees that the account given to it as argument 216 // is in the refresh_token map. 217 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size()); 218 EXPECT_TRUE( 219 oauth2_service_.refresh_tokens()["account_id"]->refresh_token().empty()); 220 // Setup a DB with tokens that don't require upgrade and clear memory. 221 oauth2_service_.UpdateCredentials("account_id", "refresh_token"); 222 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2"); 223 oauth2_service_.refresh_tokens().clear(); 224 ResetObserverCounts(); 225 226 oauth2_service_.LoadCredentials("account_id"); 227 base::RunLoop().RunUntilIdle(); 228 EXPECT_EQ(2, token_available_count_); 229 EXPECT_EQ(0, token_revoked_count_); 230 EXPECT_EQ(1, tokens_loaded_count_); 231 ResetObserverCounts(); 232 233 // TODO(fgorski): Enable below when implemented: 234 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id")); 235 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2")); 236 237 oauth2_service_.RevokeAllCredentials(); 238 EXPECT_EQ(0, token_available_count_); 239 EXPECT_EQ(2, token_revoked_count_); 240 EXPECT_EQ(0, tokens_loaded_count_); 241 ResetObserverCounts(); 242} 243 244TEST_F(MutableProfileOAuth2TokenServiceTest, PersistanceNotifications) { 245 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing()); 246 oauth2_service_.UpdateCredentials("account_id", "refresh_token"); 247 ExpectOneTokenAvailableNotification(); 248 249 oauth2_service_.UpdateCredentials("account_id", "refresh_token"); 250 ExpectNoNotifications(); 251 252 oauth2_service_.UpdateCredentials("account_id", "refresh_token2"); 253 ExpectOneTokenAvailableNotification(); 254 255 oauth2_service_.RevokeCredentials("account_id"); 256 ExpectOneTokenRevokedNotification(); 257 258 oauth2_service_.UpdateCredentials("account_id", "refresh_token2"); 259 ExpectOneTokenAvailableNotification(); 260 261 oauth2_service_.RevokeAllCredentials(); 262 ResetObserverCounts(); 263} 264 265TEST_F(MutableProfileOAuth2TokenServiceTest, GetAccounts) { 266 EXPECT_TRUE(oauth2_service_.GetAccounts().empty()); 267 oauth2_service_.UpdateCredentials("account_id1", "refresh_token1"); 268 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2"); 269 std::vector<std::string> accounts = oauth2_service_.GetAccounts(); 270 EXPECT_EQ(2u, accounts.size()); 271 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1")); 272 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2")); 273 oauth2_service_.RevokeCredentials("account_id2"); 274 accounts = oauth2_service_.GetAccounts(); 275 EXPECT_EQ(1u, oauth2_service_.GetAccounts().size()); 276 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1")); 277} 278 279TEST_F(MutableProfileOAuth2TokenServiceTest, TokenServiceUpdateClearsCache) { 280 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing()); 281 std::set<std::string> scope_list; 282 scope_list.insert("scope"); 283 oauth2_service_.UpdateCredentials(kEmail, "refreshToken"); 284 ExpectOneTokenAvailableNotification(); 285 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), 286 GetValidTokenResponse("token", 3600), 287 net::HTTP_OK, 288 net::URLRequestStatus::SUCCESS); 289 290 scoped_ptr<OAuth2TokenService::Request> request( 291 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_)); 292 base::RunLoop().RunUntilIdle(); 293 EXPECT_EQ(1, consumer_.number_of_successful_tokens_); 294 EXPECT_EQ(0, consumer_.number_of_errors_); 295 EXPECT_EQ("token", consumer_.last_token_); 296 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing()); 297 298 // Signs out and signs in 299 oauth2_service_.RevokeCredentials(kEmail); 300 ExpectOneTokenRevokedNotification(); 301 302 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing()); 303 oauth2_service_.UpdateCredentials(kEmail, "refreshToken"); 304 ExpectOneTokenAvailableNotification(); 305 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), 306 GetValidTokenResponse("another token", 3600), 307 net::HTTP_OK, 308 net::URLRequestStatus::SUCCESS); 309 310 request = oauth2_service_.StartRequest(kEmail, scope_list, &consumer_); 311 base::RunLoop().RunUntilIdle(); 312 EXPECT_EQ(2, consumer_.number_of_successful_tokens_); 313 EXPECT_EQ(0, consumer_.number_of_errors_); 314 EXPECT_EQ("another token", consumer_.last_token_); 315 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing()); 316} 317 318TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) { 319 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(), 320 "", 321 net::HTTP_FORBIDDEN, 322 net::URLRequestStatus::FAILED); 323 324 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing()); 325 std::set<std::string> scope_list; 326 scope_list.insert("scope"); 327 oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0); 328 oauth2_service_.UpdateCredentials(kEmail, "refreshToken"); 329 ExpectOneTokenAvailableNotification(); 330 331 scoped_ptr<OAuth2TokenService::Request> request( 332 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_)); 333 base::RunLoop().RunUntilIdle(); 334 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(), 335 oauth2_service_.signin_error_controller()->auth_error()); 336} 337