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) {}
38 virtual void SetUp() OVERRIDE {
39 #if defined(OS_MACOSX)
40 OSCrypt::UseMockKeychain(true);
43 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(),
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);
53 virtual void TearDown() OVERRIDE {
54 oauth2_service_.RemoveObserver(this);
55 oauth2_service_.Shutdown();
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);
65 // OAuth2TokenService::Observer implementation.
66 virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE {
67 ++token_available_count_;
69 virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE {
70 ++token_revoked_count_;
72 virtual void OnRefreshTokensLoaded() OVERRIDE { ++tokens_loaded_count_; }
74 void ResetObserverCounts() {
75 token_available_count_ = 0;
76 token_revoked_count_ = 0;
77 tokens_loaded_count_ = 0;
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();
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();
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();
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();
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_;
119 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
120 std::string main_account_id(kEmail);
121 std::string main_refresh_token("old_refresh_token");
123 // Populate DB with legacy tokens.
124 AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken");
125 AddAuthTokenManually(kLSOService, "lsoToken");
126 AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
129 // Force LoadCredentials.
130 oauth2_service_.LoadCredentials(main_account_id);
131 base::RunLoop().RunUntilIdle();
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());
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
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();
154 // Force LoadCredentials.
155 oauth2_service_.LoadCredentials(main_account_id);
156 base::RunLoop().RunUntilIdle();
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());
170 oauth2_service_.refresh_tokens()[other_account_id]->refresh_token());
172 oauth2_service_.RevokeAllCredentials();
175 TEST_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";
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));
185 oauth2_service_.UpdateCredentials(account_id_1, refresh_token_1);
186 oauth2_service_.UpdateCredentials(account_id_2, refresh_token_2);
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));
192 ResetObserverCounts();
193 oauth2_service_.RevokeCredentials(account_id_1);
194 ExpectOneTokenRevokedNotification();
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));
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();
207 TEST_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());
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();
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();
233 // TODO(fgorski): Enable below when implemented:
234 // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id"));
235 // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2"));
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();
244 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistanceNotifications) {
245 EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
246 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
247 ExpectOneTokenAvailableNotification();
249 oauth2_service_.UpdateCredentials("account_id", "refresh_token");
250 ExpectNoNotifications();
252 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
253 ExpectOneTokenAvailableNotification();
255 oauth2_service_.RevokeCredentials("account_id");
256 ExpectOneTokenRevokedNotification();
258 oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
259 ExpectOneTokenAvailableNotification();
261 oauth2_service_.RevokeAllCredentials();
262 ResetObserverCounts();
265 TEST_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"));
279 TEST_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),
288 net::URLRequestStatus::SUCCESS);
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());
298 // Signs out and signs in
299 oauth2_service_.RevokeCredentials(kEmail);
300 ExpectOneTokenRevokedNotification();
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),
308 net::URLRequestStatus::SUCCESS);
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());
318 TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) {
319 factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
322 net::URLRequestStatus::FAILED);
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();
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());