Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / sync / test / integration / sync_auth_test.cc
blob83d1f91b739eb405ce381412531cfc6e1a2f5d44
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.
5 #include "base/strings/stringprintf.h"
6 #include "base/threading/platform_thread.h"
7 #include "base/time/time.h"
8 #include "chrome/browser/signin/profile_oauth2_token_service.h"
9 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
10 #include "chrome/browser/sync/profile_sync_service.h"
11 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
12 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
13 #include "chrome/browser/sync/test/integration/sync_test.h"
14 #include "google_apis/gaia/google_service_auth_error.h"
15 #include "net/http/http_status_code.h"
16 #include "net/url_request/url_request_status.h"
18 using bookmarks_helper::AddURL;
20 const char kShortLivedOAuth2Token[] =
21 "{"
22 " \"refresh_token\": \"short_lived_refresh_token\","
23 " \"access_token\": \"short_lived_access_token\","
24 " \"expires_in\": 5," // 5 seconds.
25 " \"token_type\": \"Bearer\""
26 "}";
28 const char kValidOAuth2Token[] = "{"
29 " \"refresh_token\": \"new_refresh_token\","
30 " \"access_token\": \"new_access_token\","
31 " \"expires_in\": 3600," // 1 hour.
32 " \"token_type\": \"Bearer\""
33 "}";
35 const char kInvalidGrantOAuth2Token[] = "{"
36 " \"error\": \"invalid_grant\""
37 "}";
39 const char kInvalidClientOAuth2Token[] = "{"
40 " \"error\": \"invalid_client\""
41 "}";
43 const char kEmptyOAuth2Token[] = "";
45 const char kMalformedOAuth2Token[] = "{ \"foo\": ";
47 class SyncAuthTest : public SyncTest {
48 public:
49 SyncAuthTest() : SyncTest(SINGLE_CLIENT) {}
50 virtual ~SyncAuthTest() {}
52 // Helper function that adds a bookmark with index |bookmark_index| and waits
53 // for sync to complete. The return value indicates whether the sync cycle
54 // completed successfully (true) or encountered an auth error (false).
55 bool AddBookmarkAndWaitForSync(int bookmark_index) {
56 std::wstring title = base::StringPrintf(L"Bookmark %d", bookmark_index);
57 GURL url = GURL(base::StringPrintf("http://www.foo%d.com", bookmark_index));
58 EXPECT_TRUE(AddURL(0, title, url) != NULL);
59 return GetClient(0)->AwaitFullSyncCompletion();
62 // Sets the authenticated state of the python sync server to |auth_state| and
63 // sets the canned response that will be returned to the OAuth2TokenService
64 // when it tries to fetch an access token.
65 void SetAuthStateAndTokenResponse(PythonServerAuthState auth_state,
66 const std::string& response_data,
67 net::HttpStatusCode response_code,
68 net::URLRequestStatus::Status status) {
69 TriggerAuthState(auth_state);
71 // If ProfileSyncService observes a transient error like SERVICE_UNAVAILABLE
72 // or CONNECTION_FAILED, this means the OAuth2TokenService has given up
73 // trying to reach Gaia. In practice, OA2TS retries a fixed number of times,
74 // but the count is transparent to PSS.
75 // Override the max retry count in TokenService so that we instantly trigger
76 // the case where ProfileSyncService must pick up where OAuth2TokenService
77 // left off (in terms of retries).
78 ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile(0))->
79 set_max_authorization_token_fetch_retries_for_testing(0);
81 SetOAuth2TokenResponse(response_data, response_code, status);
84 private:
85 DISALLOW_COPY_AND_ASSIGN(SyncAuthTest);
88 // Verify that sync works with a valid OAuth2 token.
89 IN_PROC_BROWSER_TEST_F(SyncAuthTest, Sanity) {
90 ASSERT_TRUE(SetupSync());
91 SetAuthStateAndTokenResponse(AUTHENTICATED_TRUE,
92 kValidOAuth2Token,
93 net::HTTP_OK,
94 net::URLRequestStatus::SUCCESS);
95 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
98 // Verify that ProfileSyncService continues trying to fetch access tokens
99 // when OAuth2TokenService has encountered more than a fixed number of
100 // HTTP_INTERNAL_SERVER_ERROR (500) errors.
101 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RetryOnInternalServerError500) {
102 ASSERT_TRUE(SetupSync());
103 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
104 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
105 kValidOAuth2Token,
106 net::HTTP_INTERNAL_SERVER_ERROR,
107 net::URLRequestStatus::SUCCESS);
108 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
109 ASSERT_TRUE(
110 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
113 // Verify that ProfileSyncService continues trying to fetch access tokens
114 // when OAuth2TokenService has encountered more than a fixed number of
115 // HTTP_FORBIDDEN (403) errors.
116 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RetryOnHttpForbidden403) {
117 ASSERT_TRUE(SetupSync());
118 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
119 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
120 kEmptyOAuth2Token,
121 net::HTTP_FORBIDDEN,
122 net::URLRequestStatus::SUCCESS);
123 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
124 ASSERT_TRUE(
125 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
128 // Verify that ProfileSyncService continues trying to fetch access tokens
129 // when OAuth2TokenService has encountered a URLRequestStatus of FAILED.
130 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RetryOnRequestFailed) {
131 ASSERT_TRUE(SetupSync());
132 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
133 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
134 kEmptyOAuth2Token,
135 net::HTTP_INTERNAL_SERVER_ERROR,
136 net::URLRequestStatus::FAILED);
137 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
138 ASSERT_TRUE(
139 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
142 // Verify that ProfileSyncService continues trying to fetch access tokens
143 // when OAuth2TokenService receives a malformed token.
144 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RetryOnMalformedToken) {
145 ASSERT_TRUE(SetupSync());
146 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
147 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
148 kMalformedOAuth2Token,
149 net::HTTP_OK,
150 net::URLRequestStatus::SUCCESS);
151 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
152 ASSERT_TRUE(
153 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
156 // Verify that ProfileSyncService ends up with an INVALID_GAIA_CREDENTIALS auth
157 // error when an invalid_grant error is returned by OAuth2TokenService with an
158 // HTTP_BAD_REQUEST (400) response code.
159 IN_PROC_BROWSER_TEST_F(SyncAuthTest, InvalidGrant) {
160 ASSERT_TRUE(SetupSync());
161 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
162 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
163 kInvalidGrantOAuth2Token,
164 net::HTTP_BAD_REQUEST,
165 net::URLRequestStatus::SUCCESS);
166 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
167 ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
168 GetClient(0)->service()->GetAuthError().state());
171 // Verify that ProfileSyncService ends up with an SERVICE_ERROR auth error when
172 // an invalid_client error is returned by OAuth2TokenService with an
173 // HTTP_BAD_REQUEST (400) response code.
174 IN_PROC_BROWSER_TEST_F(SyncAuthTest, InvalidClient) {
175 ASSERT_TRUE(SetupSync());
176 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
177 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
178 kInvalidClientOAuth2Token,
179 net::HTTP_BAD_REQUEST,
180 net::URLRequestStatus::SUCCESS);
181 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
182 ASSERT_EQ(GoogleServiceAuthError::SERVICE_ERROR,
183 GetClient(0)->service()->GetAuthError().state());
186 // Verify that ProfileSyncService ends up with a REQUEST_CANCELED auth error
187 // when when OAuth2TokenService has encountered a URLRequestStatus of CANCELED.
188 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RequestCanceled) {
189 ASSERT_TRUE(SetupSync());
190 ASSERT_TRUE(AddBookmarkAndWaitForSync(1));
191 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
192 kEmptyOAuth2Token,
193 net::HTTP_INTERNAL_SERVER_ERROR,
194 net::URLRequestStatus::CANCELED);
195 ASSERT_FALSE(AddBookmarkAndWaitForSync(2));
196 ASSERT_EQ(GoogleServiceAuthError::REQUEST_CANCELED,
197 GetClient(0)->service()->GetAuthError().state());
200 // Verify that ProfileSyncService fails initial sync setup during backend
201 // initialization and ends up with an INVALID_GAIA_CREDENTIALS auth error when
202 // an invalid_grant error is returned by OAuth2TokenService with an
203 // HTTP_BAD_REQUEST (400) response code.
204 IN_PROC_BROWSER_TEST_F(SyncAuthTest, FailInitialSetupWithPersistentError) {
205 ASSERT_TRUE(SetupClients());
206 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
207 kInvalidGrantOAuth2Token,
208 net::HTTP_BAD_REQUEST,
209 net::URLRequestStatus::SUCCESS);
210 ASSERT_FALSE(GetClient(0)->SetupSync());
211 ASSERT_FALSE(GetClient(0)->service()->sync_initialized());
212 ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
213 GetClient(0)->service()->GetAuthError().state());
216 // Verify that ProfileSyncService fails initial sync setup during backend
217 // initialization, but continues trying to fetch access tokens when
218 // OAuth2TokenService receives an HTTP_INTERNAL_SERVER_ERROR (500) response
219 // code.
220 IN_PROC_BROWSER_TEST_F(SyncAuthTest, RetryInitialSetupWithTransientError) {
221 ASSERT_TRUE(SetupClients());
222 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
223 kEmptyOAuth2Token,
224 net::HTTP_INTERNAL_SERVER_ERROR,
225 net::URLRequestStatus::SUCCESS);
226 ASSERT_FALSE(GetClient(0)->SetupSync());
227 ASSERT_FALSE(GetClient(0)->service()->sync_initialized());
228 ASSERT_TRUE(
229 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
232 // Verify that ProfileSyncService fetches a new token when an old token expires.
233 IN_PROC_BROWSER_TEST_F(SyncAuthTest, TokenExpiry) {
234 // Initial sync succeeds with a short lived OAuth2 Token.
235 ASSERT_TRUE(SetupClients());
236 SetAuthStateAndTokenResponse(AUTHENTICATED_TRUE,
237 kShortLivedOAuth2Token,
238 net::HTTP_OK,
239 net::URLRequestStatus::SUCCESS);
240 ASSERT_TRUE(GetClient(0)->SetupSync());
241 std::string old_token = GetClient(0)->service()->GetAccessTokenForTest();
243 // Wait until the token has expired.
244 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(5));
246 // Trigger an auth error on the server so PSS requests OA2TS for a new token
247 // during the next sync cycle.
248 SetAuthStateAndTokenResponse(AUTHENTICATED_FALSE,
249 kEmptyOAuth2Token,
250 net::HTTP_INTERNAL_SERVER_ERROR,
251 net::URLRequestStatus::SUCCESS);
252 ASSERT_FALSE(AddBookmarkAndWaitForSync(1));
253 ASSERT_TRUE(
254 GetClient(0)->service()->IsRetryingAccessTokenFetchForTest());
256 // Trigger an auth success state and set up a new valid OAuth2 token.
257 SetAuthStateAndTokenResponse(AUTHENTICATED_TRUE,
258 kValidOAuth2Token,
259 net::HTTP_OK,
260 net::URLRequestStatus::SUCCESS);
262 // Verify that the next sync cycle is successful, and uses the new auth token.
263 ASSERT_TRUE(GetClient(0)->AwaitFullSyncCompletion());
264 std::string new_token = GetClient(0)->service()->GetAccessTokenForTest();
265 ASSERT_NE(old_token, new_token);