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.
5 #include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
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"
19 #if defined(OS_MACOSX)
20 #include "components/os_crypt/os_crypt.h"
23 // Defining constant here to handle backward compatiblity tests, but this
24 // constant is no longer used in current versions of chrome.
25 static const char kLSOService[] = "lso";
26 static const char kEmail[] = "user@gmail.com";
28 class MutableProfileOAuth2TokenServiceTest
29 : public testing::Test,
30 public OAuth2TokenService::Observer {
32 MutableProfileOAuth2TokenServiceTest()
34 token_available_count_(0),
35 token_revoked_count_(0),
36 tokens_loaded_count_(0),
37 start_batch_changes_(0),
38 end_batch_changes_(0) {}
40 virtual void SetUp() OVERRIDE {
41 #if defined(OS_MACOSX)
42 OSCrypt::UseMockKeychain(true);
45 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(),
48 net::URLRequestStatus::SUCCESS);
49 oauth2_service_.Initialize(&client_);
50 // Make sure PO2TS has a chance to load itself before continuing.
51 base::RunLoop().RunUntilIdle();
52 oauth2_service_.AddObserver(this);
55 virtual void TearDown() OVERRIDE {
56 oauth2_service_.RemoveObserver(this);
57 oauth2_service_.Shutdown();
60 void AddAuthTokenManually(const std::string& service,
61 const std::string& value) {
62 scoped_refptr<TokenWebData> token_web_data = client_.GetDatabase();
63 if (token_web_data.get())
64 token_web_data->SetTokenForService(service, value);
67 // OAuth2TokenService::Observer implementation.
68 virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE {
69 ++token_available_count_;
71 virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE {
72 ++token_revoked_count_;
74 virtual void OnRefreshTokensLoaded() OVERRIDE { ++tokens_loaded_count_; }
76 virtual void OnStartBatchChanges() OVERRIDE {
77 ++start_batch_changes_;
80 virtual void OnEndBatchChanges() OVERRIDE {
84 void ResetObserverCounts() {
85 token_available_count_ = 0;
86 token_revoked_count_ = 0;
87 tokens_loaded_count_ = 0;
88 start_batch_changes_ = 0;
89 end_batch_changes_ = 0;
92 void ExpectNoNotifications() {
93 EXPECT_EQ(0, token_available_count_);
94 EXPECT_EQ(0, token_revoked_count_);
95 EXPECT_EQ(0, tokens_loaded_count_);
96 ResetObserverCounts();
99 void ExpectOneTokenAvailableNotification() {
100 EXPECT_EQ(1, token_available_count_);
101 EXPECT_EQ(0, token_revoked_count_);
102 EXPECT_EQ(0, tokens_loaded_count_);
103 ResetObserverCounts();
106 void ExpectOneTokenRevokedNotification() {
107 EXPECT_EQ(0, token_available_count_);
108 EXPECT_EQ(1, token_revoked_count_);
109 EXPECT_EQ(0, tokens_loaded_count_);
110 ResetObserverCounts();
113 void ExpectOneTokensLoadedNotification() {
114 EXPECT_EQ(0, token_available_count_);
115 EXPECT_EQ(0, token_revoked_count_);
116 EXPECT_EQ(1, tokens_loaded_count_);
117 ResetObserverCounts();
121 base::MessageLoop message_loop_;
122 net::FakeURLFetcherFactory factory_;
123 TestSigninClient client_;
124 MutableProfileOAuth2TokenService oauth2_service_;
125 TestingOAuth2TokenServiceConsumer consumer_;
126 int token_available_count_;
127 int token_revoked_count_;
128 int tokens_loaded_count_;
129 int start_batch_changes_;
130 int end_batch_changes_;
133 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
134 std::string main_account_id(kEmail);
135 std::string main_refresh_token("old_refresh_token");
137 // Populate DB with legacy tokens.
138 AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken");
139 AddAuthTokenManually(kLSOService, "lsoToken");
140 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
143 // Force LoadCredentials.
144 oauth2_service_.LoadCredentials(main_account_id);
145 base::RunLoop().RunUntilIdle();
147 // Legacy tokens get discarded, but the old refresh token is kept.
148 EXPECT_EQ(1, tokens_loaded_count_);
149 EXPECT_EQ(1, token_available_count_);
150 EXPECT_EQ(1, start_batch_changes_);
151 EXPECT_EQ(1, end_batch_changes_);
152 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
153 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
154 EXPECT_EQ(main_refresh_token,
155 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
157 // Add an old legacy token to the DB, to ensure it will not overwrite existing
158 // credentials for main account.
159 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
160 "secondOldRefreshToken");
161 // Add some other legacy token. (Expected to get discarded).
162 AddAuthTokenManually(kLSOService, "lsoToken");
163 // Also add a token using PO2TS.UpdateCredentials and make sure upgrade does
165 std::string other_account_id("other_account_id");
166 std::string other_refresh_token("other_refresh_token");
167 oauth2_service_.UpdateCredentials(other_account_id, other_refresh_token);
168 ResetObserverCounts();
170 // Force LoadCredentials.
171 oauth2_service_.LoadCredentials(main_account_id);
172 base::RunLoop().RunUntilIdle();
174 // Again legacy tokens get discarded, but since the main porfile account
175 // token is present it is not overwritten.
176 EXPECT_EQ(2, token_available_count_);
177 EXPECT_EQ(1, tokens_loaded_count_);
178 EXPECT_EQ(1, start_batch_changes_);
179 EXPECT_EQ(1, end_batch_changes_);
180 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
181 // TODO(fgorski): cover both using RefreshTokenIsAvailable() and then get the
182 // tokens using GetRefreshToken()
183 EXPECT_EQ(2U, oauth2_service_.refresh_tokens().size());
184 EXPECT_EQ(main_refresh_token,
185 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
188 oauth2_service_.refresh_tokens()[other_account_id]->refresh_token());
190 oauth2_service_.RevokeAllCredentials();
191 EXPECT_EQ(2, start_batch_changes_);
192 EXPECT_EQ(2, end_batch_changes_);
195 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceRevokeCredentials) {
196 std::string account_id_1 = "account_id_1";
197 std::string refresh_token_1 = "refresh_token_1";
198 std::string account_id_2 = "account_id_2";
199 std::string refresh_token_2 = "refresh_token_2";
201 // TODO(fgorski): Enable below when implemented:
202 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
203 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_2));
205 oauth2_service_.UpdateCredentials(account_id_1, refresh_token_1);
206 oauth2_service_.UpdateCredentials(account_id_2, refresh_token_2);
207 EXPECT_EQ(2, start_batch_changes_);
208 EXPECT_EQ(2, end_batch_changes_);
210 // TODO(fgorski): Enable below when implemented:
211 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
212 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
214 ResetObserverCounts();
215 oauth2_service_.RevokeCredentials(account_id_1);
216 EXPECT_EQ(1, start_batch_changes_);
217 EXPECT_EQ(1, end_batch_changes_);
218 ExpectOneTokenRevokedNotification();
220 // TODO(fgorski): Enable below when implemented:
221 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
222 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
224 oauth2_service_.RevokeAllCredentials();
225 EXPECT_EQ(0, token_available_count_);
226 EXPECT_EQ(1, token_revoked_count_);
227 EXPECT_EQ(0, tokens_loaded_count_);
228 EXPECT_EQ(1, start_batch_changes_);
229 EXPECT_EQ(1, end_batch_changes_);
230 ResetObserverCounts();
233 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceLoadCredentials) {
234 // Ensure DB is clean.
235 oauth2_service_.RevokeAllCredentials();
236 ResetObserverCounts();
237 // Perform a load from an empty DB.
238 oauth2_service_.LoadCredentials("account_id");
239 base::RunLoop().RunUntilIdle();
240 EXPECT_EQ(1, start_batch_changes_);
241 EXPECT_EQ(1, end_batch_changes_);
242 ExpectOneTokensLoadedNotification();
243 // LoadCredentials() guarantees that the account given to it as argument
244 // is in the refresh_token map.
245 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
247 oauth2_service_.refresh_tokens()["account_id"]->refresh_token().empty());
248 // Setup a DB with tokens that don't require upgrade and clear memory.
249 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
250 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
251 oauth2_service_.refresh_tokens().clear();
252 EXPECT_EQ(2, start_batch_changes_);
253 EXPECT_EQ(2, end_batch_changes_);
254 ResetObserverCounts();
256 oauth2_service_.LoadCredentials("account_id");
257 base::RunLoop().RunUntilIdle();
258 EXPECT_EQ(2, token_available_count_);
259 EXPECT_EQ(0, token_revoked_count_);
260 EXPECT_EQ(1, tokens_loaded_count_);
261 EXPECT_EQ(1, start_batch_changes_);
262 EXPECT_EQ(1, end_batch_changes_);
263 ResetObserverCounts();
265 // TODO(fgorski): Enable below when implemented:
266 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id"));
267 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2"));
269 oauth2_service_.RevokeAllCredentials();
270 EXPECT_EQ(0, token_available_count_);
271 EXPECT_EQ(2, token_revoked_count_);
272 EXPECT_EQ(0, tokens_loaded_count_);
273 EXPECT_EQ(1, start_batch_changes_);
274 EXPECT_EQ(1, end_batch_changes_);
275 ResetObserverCounts();
278 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistanceNotifications) {
279 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
280 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
281 ExpectOneTokenAvailableNotification();
283 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
284 ExpectNoNotifications();
286 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
287 ExpectOneTokenAvailableNotification();
289 oauth2_service_.RevokeCredentials("account_id");
290 ExpectOneTokenRevokedNotification();
292 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
293 ExpectOneTokenAvailableNotification();
295 oauth2_service_.RevokeAllCredentials();
296 ResetObserverCounts();
299 TEST_F(MutableProfileOAuth2TokenServiceTest, GetAccounts) {
300 EXPECT_TRUE(oauth2_service_.GetAccounts().empty());
301 oauth2_service_.UpdateCredentials("account_id1", "refresh_token1");
302 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
303 std::vector<std::string> accounts = oauth2_service_.GetAccounts();
304 EXPECT_EQ(2u, accounts.size());
305 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
306 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
307 oauth2_service_.RevokeCredentials("account_id2");
308 accounts = oauth2_service_.GetAccounts();
309 EXPECT_EQ(1u, oauth2_service_.GetAccounts().size());
310 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
313 TEST_F(MutableProfileOAuth2TokenServiceTest, TokenServiceUpdateClearsCache) {
314 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
315 std::set<std::string> scope_list;
316 scope_list.insert("scope");
317 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
318 ExpectOneTokenAvailableNotification();
319 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
320 GetValidTokenResponse("token", 3600),
322 net::URLRequestStatus::SUCCESS);
324 scoped_ptr<OAuth2TokenService::Request> request(
325 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
326 base::RunLoop().RunUntilIdle();
327 EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
328 EXPECT_EQ(0, consumer_.number_of_errors_);
329 EXPECT_EQ("token", consumer_.last_token_);
330 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
332 // Signs out and signs in
333 oauth2_service_.RevokeCredentials(kEmail);
334 ExpectOneTokenRevokedNotification();
336 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
337 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
338 ExpectOneTokenAvailableNotification();
339 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
340 GetValidTokenResponse("another token", 3600),
342 net::URLRequestStatus::SUCCESS);
344 request = oauth2_service_.StartRequest(kEmail, scope_list, &consumer_);
345 base::RunLoop().RunUntilIdle();
346 EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
347 EXPECT_EQ(0, consumer_.number_of_errors_);
348 EXPECT_EQ("another token", consumer_.last_token_);
349 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
352 TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) {
353 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
356 net::URLRequestStatus::FAILED);
358 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
359 std::set<std::string> scope_list;
360 scope_list.insert("scope");
361 oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
362 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
363 ExpectOneTokenAvailableNotification();
365 scoped_ptr<OAuth2TokenService::Request> request(
366 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
367 base::RunLoop().RunUntilIdle();
368 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
369 oauth2_service_.signin_error_controller()->auth_error());