Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / components / signin / core / browser / mutable_profile_oauth2_token_service_unittest.cc
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.
25 static const char kLSOService[] = "lso";
26 static const char kEmail[] = "user@gmail.com";
27
28 class 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         start_batch_changes_(0),
38         end_batch_changes_(0) {}
39
40   void SetUp() override {
41 #if defined(OS_MACOSX)
42     OSCrypt::UseMockKeychain(true);
43 #endif
44
45     factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(),
46                              "",
47                              net::HTTP_OK,
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);
53   }
54
55   void TearDown() override {
56     oauth2_service_.RemoveObserver(this);
57     oauth2_service_.Shutdown();
58   }
59
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);
65   }
66
67   // OAuth2TokenService::Observer implementation.
68   void OnRefreshTokenAvailable(const std::string& account_id) override {
69     ++token_available_count_;
70   }
71   void OnRefreshTokenRevoked(const std::string& account_id) override {
72     ++token_revoked_count_;
73   }
74   void OnRefreshTokensLoaded() override { ++tokens_loaded_count_; }
75
76   void OnStartBatchChanges() override { ++start_batch_changes_; }
77
78   void OnEndBatchChanges() override { ++end_batch_changes_; }
79
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;
86   }
87
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();
93   }
94
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();
100   }
101
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();
107   }
108
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();
114   }
115
116  protected:
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_;
127 };
128
129 TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
130   std::string main_account_id(kEmail);
131   std::string main_refresh_token("old_refresh_token");
132
133   // Populate DB with legacy tokens.
134   AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken");
135   AddAuthTokenManually(kLSOService, "lsoToken");
136   AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
137                        main_refresh_token);
138
139   // Force LoadCredentials.
140   oauth2_service_.LoadCredentials(main_account_id);
141   base::RunLoop().RunUntilIdle();
142
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());
152
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
160   // not wipe it.
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();
165
166   // Force LoadCredentials.
167   oauth2_service_.LoadCredentials(main_account_id);
168   base::RunLoop().RunUntilIdle();
169
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());
182   EXPECT_EQ(
183       other_refresh_token,
184       oauth2_service_.refresh_tokens()[other_account_id]->refresh_token());
185
186   oauth2_service_.RevokeAllCredentials();
187   EXPECT_EQ(2, start_batch_changes_);
188   EXPECT_EQ(2, end_batch_changes_);
189 }
190
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";
196
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));
200
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_);
205
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));
209
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();
215
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));
219
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();
227 }
228
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());
242   EXPECT_TRUE(
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();
251
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();
260
261   // TODO(fgorski): Enable below when implemented:
262   // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id"));
263   // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2"));
264
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();
272 }
273
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();
278
279   oauth2_service_.UpdateCredentials("account_id", "refresh_token");
280   ExpectNoNotifications();
281
282   oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
283   ExpectOneTokenAvailableNotification();
284
285   oauth2_service_.RevokeCredentials("account_id");
286   ExpectOneTokenRevokedNotification();
287
288   oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
289   ExpectOneTokenAvailableNotification();
290
291   oauth2_service_.RevokeAllCredentials();
292   ResetObserverCounts();
293 }
294
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"));
307 }
308
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),
317                            net::HTTP_OK,
318                            net::URLRequestStatus::SUCCESS);
319
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());
327
328   // Signs out and signs in
329   oauth2_service_.RevokeCredentials(kEmail);
330   ExpectOneTokenRevokedNotification();
331
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),
337                            net::HTTP_OK,
338                            net::URLRequestStatus::SUCCESS);
339
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());
346 }
347
348 TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) {
349   factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
350                            "",
351                            net::HTTP_FORBIDDEN,
352                            net::URLRequestStatus::FAILED);
353
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();
360
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());
366 }
367
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";
373
374   oauth2_service_.LoadAllCredentialsIntoMemory(tokens);
375
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"));
379 }