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