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 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 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 void OnRefreshTokenAvailable(const std::string& account_id) override {
69 ++token_available_count_;
71 void OnRefreshTokenRevoked(const std::string& account_id) override {
72 ++token_revoked_count_;
74 void OnRefreshTokensLoaded() override { ++tokens_loaded_count_; }
76 void OnStartBatchChanges() override { ++start_batch_changes_; }
78 void OnEndBatchChanges() override { ++end_batch_changes_; }
80 void ResetObserverCounts() {
81 token_available_count_ = 0;
82 token_revoked_count_ = 0;
83 tokens_loaded_count_ = 0;
84 start_batch_changes_ = 0;
85 end_batch_changes_ = 0;
88 void ExpectNoNotifications() {
89 EXPECT_EQ(0, token_available_count_);
90 EXPECT_EQ(0, token_revoked_count_);
91 EXPECT_EQ(0, tokens_loaded_count_);
92 ResetObserverCounts();
95 void ExpectOneTokenAvailableNotification() {
96 EXPECT_EQ(1, token_available_count_);
97 EXPECT_EQ(0, token_revoked_count_);
98 EXPECT_EQ(0, tokens_loaded_count_);
99 ResetObserverCounts();
102 void ExpectOneTokenRevokedNotification() {
103 EXPECT_EQ(0, token_available_count_);
104 EXPECT_EQ(1, token_revoked_count_);
105 EXPECT_EQ(0, tokens_loaded_count_);
106 ResetObserverCounts();
109 void ExpectOneTokensLoadedNotification() {
110 EXPECT_EQ(0, token_available_count_);
111 EXPECT_EQ(0, token_revoked_count_);
112 EXPECT_EQ(1, tokens_loaded_count_);
113 ResetObserverCounts();
117 base::MessageLoop message_loop_;
118 net::FakeURLFetcherFactory factory_;
119 TestSigninClient client_;
120 MutableProfileOAuth2TokenService oauth2_service_;
121 TestingOAuth2TokenServiceConsumer consumer_;
122 int token_available_count_;
123 int token_revoked_count_;
124 int tokens_loaded_count_;
125 int start_batch_changes_;
126 int end_batch_changes_;
129 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
130 std::string main_account_id(kEmail);
131 std::string main_refresh_token("old_refresh_token");
133 // Populate DB with legacy tokens.
134 AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken");
135 AddAuthTokenManually(kLSOService, "lsoToken");
136 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
139 // Force LoadCredentials.
140 oauth2_service_.LoadCredentials(main_account_id);
141 base::RunLoop().RunUntilIdle();
143 // Legacy tokens get discarded, but the old refresh token is kept.
144 EXPECT_EQ(1, tokens_loaded_count_);
145 EXPECT_EQ(1, token_available_count_);
146 EXPECT_EQ(1, start_batch_changes_);
147 EXPECT_EQ(1, end_batch_changes_);
148 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
149 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
150 EXPECT_EQ(main_refresh_token,
151 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
153 // Add an old legacy token to the DB, to ensure it will not overwrite existing
154 // credentials for main account.
155 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
156 "secondOldRefreshToken");
157 // Add some other legacy token. (Expected to get discarded).
158 AddAuthTokenManually(kLSOService, "lsoToken");
159 // Also add a token using PO2TS.UpdateCredentials and make sure upgrade does
161 std::string other_account_id("other_account_id");
162 std::string other_refresh_token("other_refresh_token");
163 oauth2_service_.UpdateCredentials(other_account_id, other_refresh_token);
164 ResetObserverCounts();
166 // Force LoadCredentials.
167 oauth2_service_.LoadCredentials(main_account_id);
168 base::RunLoop().RunUntilIdle();
170 // Again legacy tokens get discarded, but since the main porfile account
171 // token is present it is not overwritten.
172 EXPECT_EQ(2, token_available_count_);
173 EXPECT_EQ(1, tokens_loaded_count_);
174 EXPECT_EQ(1, start_batch_changes_);
175 EXPECT_EQ(1, end_batch_changes_);
176 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
177 // TODO(fgorski): cover both using RefreshTokenIsAvailable() and then get the
178 // tokens using GetRefreshToken()
179 EXPECT_EQ(2U, oauth2_service_.refresh_tokens().size());
180 EXPECT_EQ(main_refresh_token,
181 oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
184 oauth2_service_.refresh_tokens()[other_account_id]->refresh_token());
186 oauth2_service_.RevokeAllCredentials();
187 EXPECT_EQ(2, start_batch_changes_);
188 EXPECT_EQ(2, end_batch_changes_);
191 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceRevokeCredentials) {
192 std::string account_id_1 = "account_id_1";
193 std::string refresh_token_1 = "refresh_token_1";
194 std::string account_id_2 = "account_id_2";
195 std::string refresh_token_2 = "refresh_token_2";
197 // TODO(fgorski): Enable below when implemented:
198 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
199 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_2));
201 oauth2_service_.UpdateCredentials(account_id_1, refresh_token_1);
202 oauth2_service_.UpdateCredentials(account_id_2, refresh_token_2);
203 EXPECT_EQ(2, start_batch_changes_);
204 EXPECT_EQ(2, end_batch_changes_);
206 // TODO(fgorski): Enable below when implemented:
207 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
208 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
210 ResetObserverCounts();
211 oauth2_service_.RevokeCredentials(account_id_1);
212 EXPECT_EQ(1, start_batch_changes_);
213 EXPECT_EQ(1, end_batch_changes_);
214 ExpectOneTokenRevokedNotification();
216 // TODO(fgorski): Enable below when implemented:
217 // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
218 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
220 oauth2_service_.RevokeAllCredentials();
221 EXPECT_EQ(0, token_available_count_);
222 EXPECT_EQ(1, token_revoked_count_);
223 EXPECT_EQ(0, tokens_loaded_count_);
224 EXPECT_EQ(1, start_batch_changes_);
225 EXPECT_EQ(1, end_batch_changes_);
226 ResetObserverCounts();
229 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceLoadCredentials) {
230 // Ensure DB is clean.
231 oauth2_service_.RevokeAllCredentials();
232 ResetObserverCounts();
233 // Perform a load from an empty DB.
234 oauth2_service_.LoadCredentials("account_id");
235 base::RunLoop().RunUntilIdle();
236 EXPECT_EQ(1, start_batch_changes_);
237 EXPECT_EQ(1, end_batch_changes_);
238 ExpectOneTokensLoadedNotification();
239 // LoadCredentials() guarantees that the account given to it as argument
240 // is in the refresh_token map.
241 EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
243 oauth2_service_.refresh_tokens()["account_id"]->refresh_token().empty());
244 // Setup a DB with tokens that don't require upgrade and clear memory.
245 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
246 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
247 oauth2_service_.refresh_tokens().clear();
248 EXPECT_EQ(2, start_batch_changes_);
249 EXPECT_EQ(2, end_batch_changes_);
250 ResetObserverCounts();
252 oauth2_service_.LoadCredentials("account_id");
253 base::RunLoop().RunUntilIdle();
254 EXPECT_EQ(2, token_available_count_);
255 EXPECT_EQ(0, token_revoked_count_);
256 EXPECT_EQ(1, tokens_loaded_count_);
257 EXPECT_EQ(1, start_batch_changes_);
258 EXPECT_EQ(1, end_batch_changes_);
259 ResetObserverCounts();
261 // TODO(fgorski): Enable below when implemented:
262 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id"));
263 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2"));
265 oauth2_service_.RevokeAllCredentials();
266 EXPECT_EQ(0, token_available_count_);
267 EXPECT_EQ(2, token_revoked_count_);
268 EXPECT_EQ(0, tokens_loaded_count_);
269 EXPECT_EQ(1, start_batch_changes_);
270 EXPECT_EQ(1, end_batch_changes_);
271 ResetObserverCounts();
274 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistanceNotifications) {
275 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
276 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
277 ExpectOneTokenAvailableNotification();
279 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
280 ExpectNoNotifications();
282 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
283 ExpectOneTokenAvailableNotification();
285 oauth2_service_.RevokeCredentials("account_id");
286 ExpectOneTokenRevokedNotification();
288 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
289 ExpectOneTokenAvailableNotification();
291 oauth2_service_.RevokeAllCredentials();
292 ResetObserverCounts();
295 TEST_F(MutableProfileOAuth2TokenServiceTest, GetAccounts) {
296 EXPECT_TRUE(oauth2_service_.GetAccounts().empty());
297 oauth2_service_.UpdateCredentials("account_id1", "refresh_token1");
298 oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
299 std::vector<std::string> accounts = oauth2_service_.GetAccounts();
300 EXPECT_EQ(2u, accounts.size());
301 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
302 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
303 oauth2_service_.RevokeCredentials("account_id2");
304 accounts = oauth2_service_.GetAccounts();
305 EXPECT_EQ(1u, oauth2_service_.GetAccounts().size());
306 EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
309 TEST_F(MutableProfileOAuth2TokenServiceTest, TokenServiceUpdateClearsCache) {
310 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
311 std::set<std::string> scope_list;
312 scope_list.insert("scope");
313 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
314 ExpectOneTokenAvailableNotification();
315 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
316 GetValidTokenResponse("token", 3600),
318 net::URLRequestStatus::SUCCESS);
320 scoped_ptr<OAuth2TokenService::Request> request(
321 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
322 base::RunLoop().RunUntilIdle();
323 EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
324 EXPECT_EQ(0, consumer_.number_of_errors_);
325 EXPECT_EQ("token", consumer_.last_token_);
326 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
328 // Signs out and signs in
329 oauth2_service_.RevokeCredentials(kEmail);
330 ExpectOneTokenRevokedNotification();
332 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
333 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
334 ExpectOneTokenAvailableNotification();
335 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
336 GetValidTokenResponse("another token", 3600),
338 net::URLRequestStatus::SUCCESS);
340 request = oauth2_service_.StartRequest(kEmail, scope_list, &consumer_);
341 base::RunLoop().RunUntilIdle();
342 EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
343 EXPECT_EQ(0, consumer_.number_of_errors_);
344 EXPECT_EQ("another token", consumer_.last_token_);
345 EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
348 TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) {
349 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
352 net::URLRequestStatus::FAILED);
354 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
355 std::set<std::string> scope_list;
356 scope_list.insert("scope");
357 oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
358 oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
359 ExpectOneTokenAvailableNotification();
361 scoped_ptr<OAuth2TokenService::Request> request(
362 oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
363 base::RunLoop().RunUntilIdle();
364 EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
365 oauth2_service_.signin_error_controller()->auth_error());
368 TEST_F(MutableProfileOAuth2TokenServiceTest, CanonicalizeAccountId) {
369 std::map<std::string, std::string> tokens;
370 tokens["AccountId-user@gmail.com"] = "refresh_token";
371 tokens["AccountId-Foo.Bar@gmail.com"] = "refresh_token";
372 tokens["AccountId-12345"] = "refresh_token";
374 oauth2_service_.LoadAllCredentialsIntoMemory(tokens);
376 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("user@gmail.com"));
377 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("foobar@gmail.com"));
378 EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("12345"));