Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: chrome/browser/invalidation/ticl_invalidation_service.cc

Issue 15580002: Make use of InvalidationService (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/invalidation/ticl_invalidation_service.h" 5 #include "chrome/browser/invalidation/ticl_invalidation_service.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "chrome/browser/invalidation/invalidation_service_util.h" 8 #include "chrome/browser/invalidation/invalidation_service_util.h"
9 #include "chrome/browser/managed_mode/managed_user_service.h"
9 #include "chrome/browser/profiles/profile.h" 10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/signin/profile_oauth2_token_service.h"
12 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
10 #include "chrome/browser/signin/signin_manager.h" 13 #include "chrome/browser/signin/signin_manager.h"
11 #include "chrome/browser/signin/token_service.h"
12 #include "chrome/common/chrome_notification_types.h" 14 #include "chrome/common/chrome_notification_types.h"
13 #include "content/public/browser/notification_service.h" 15 #include "content/public/browser/notification_service.h"
14 #include "google_apis/gaia/gaia_constants.h" 16 #include "google_apis/gaia/gaia_constants.h"
15 #include "sync/notifier/invalidator.h" 17 #include "sync/notifier/invalidator.h"
16 #include "sync/notifier/invalidator_state.h" 18 #include "sync/notifier/invalidator_state.h"
17 #include "sync/notifier/non_blocking_invalidator.h" 19 #include "sync/notifier/non_blocking_invalidator.h"
18 20
21 static const char* kOAuth2Scopes[] = {
22 GaiaConstants::kGoogleTalkOAuth2Scope
23 };
24
25 static const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
26 // Number of initial errors (in sequence) to ignore before applying
27 // exponential back-off rules.
28 0,
29
30 // Initial delay for exponential back-off in ms.
31 2000,
32
33 // Factor by which the waiting time will be multiplied.
34 2,
35
36 // Fuzzing percentage. ex: 10% will spread requests randomly
37 // between 90%-100% of the calculated time.
38 0.2, // 20%
39
40 // Maximum amount of time we are willing to delay our request in ms.
41 // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
42 // RequestAccessToken on connection state change after backoff
43 1000 * 3600 * 4, // 4 hours.
44
45 // Time to keep an entry from being discarded even when it
46 // has no significant state, -1 to never discard.
47 -1,
48
49 // Don't use initial delay unless the last request was an error.
50 false,
51 };
52
19 namespace invalidation { 53 namespace invalidation {
20 54
21 TiclInvalidationService::TiclInvalidationService(SigninManagerBase* signin, 55 TiclInvalidationService::TiclInvalidationService(
22 TokenService* token_service, 56 SigninManagerBase* signin,
23 Profile* profile) 57 TokenService* token_service,
24 : profile_(profile), 58 OAuth2TokenService* oauth2_token_service,
25 signin_manager_(signin), 59 Profile* profile)
26 token_service_(token_service), 60 : profile_(profile),
27 invalidator_registrar_(new syncer::InvalidatorRegistrar()) { } 61 signin_manager_(signin),
62 token_service_(token_service),
63 oauth2_token_service_(oauth2_token_service),
64 invalidator_registrar_(new syncer::InvalidatorRegistrar()),
65 request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy) {
66 }
28 67
29 TiclInvalidationService::~TiclInvalidationService() { 68 TiclInvalidationService::~TiclInvalidationService() {
30 DCHECK(CalledOnValidThread()); 69 DCHECK(CalledOnValidThread());
31 } 70 }
32 71
33 void TiclInvalidationService::Init() { 72 void TiclInvalidationService::Init() {
34 DCHECK(CalledOnValidThread()); 73 DCHECK(CalledOnValidThread());
35 74
36 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs())); 75 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
37 if (invalidator_storage_->GetInvalidatorClientId().empty()) { 76 if (invalidator_storage_->GetInvalidatorClientId().empty()) {
38 // This also clears any existing state. We can't reuse old invalidator 77 // This also clears any existing state. We can't reuse old invalidator
39 // state with the new ID anyway. 78 // state with the new ID anyway.
40 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId()); 79 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
41 } 80 }
42 81
43 if (IsReadyToStart()) { 82 if (IsReadyToStart()) {
44 Start(); 83 StartInvalidator();
45 } 84 }
46 85
47 notification_registrar_.Add(this, 86 notification_registrar_.Add(this,
48 chrome::NOTIFICATION_TOKEN_AVAILABLE, 87 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
88 content::Source<Profile>(profile_));
89 notification_registrar_.Add(this,
90 chrome::NOTIFICATION_TOKEN_LOADING_FINISHED,
49 content::Source<TokenService>(token_service_)); 91 content::Source<TokenService>(token_service_));
50 notification_registrar_.Add(this, 92 notification_registrar_.Add(this,
51 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 93 chrome::NOTIFICATION_TOKENS_CLEARED,
52 content::Source<Profile>(profile_)); 94 content::Source<TokenService>(token_service_));
53 } 95 }
54 96
55 void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) { 97 void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
56 // Here we perform the equivalent of Init() and Start(), but with some minor 98 // Here we perform the equivalent of Init() and StartInvalidator(), but with
57 // changes to account for the fact that we're injecting the invalidator. 99 // some minor changes to account for the fact that we're injecting the
100 // invalidator.
58 invalidator_.reset(invalidator); 101 invalidator_.reset(invalidator);
59 102
60 invalidator_->RegisterHandler(this); 103 invalidator_->RegisterHandler(this);
61 invalidator_->UpdateRegisteredIds( 104 invalidator_->UpdateRegisteredIds(
62 this, 105 this,
63 invalidator_registrar_->GetAllRegisteredIds()); 106 invalidator_registrar_->GetAllRegisteredIds());
64 } 107 }
65 108
66 void TiclInvalidationService::RegisterInvalidationHandler( 109 void TiclInvalidationService::RegisterInvalidationHandler(
67 syncer::InvalidationHandler* handler) { 110 syncer::InvalidationHandler* handler) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 return invalidator_storage_->GetInvalidatorClientId(); 164 return invalidator_storage_->GetInvalidatorClientId();
122 } 165 }
123 166
124 void TiclInvalidationService::Observe( 167 void TiclInvalidationService::Observe(
125 int type, 168 int type,
126 const content::NotificationSource& source, 169 const content::NotificationSource& source,
127 const content::NotificationDetails& details) { 170 const content::NotificationDetails& details) {
128 DCHECK(CalledOnValidThread()); 171 DCHECK(CalledOnValidThread());
129 172
130 switch (type) { 173 switch (type) {
131 case chrome::NOTIFICATION_TOKEN_AVAILABLE: { 174 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: {
132 const TokenService::TokenAvailableDetails& token_details = 175 if (!IsStarted() && IsReadyToStart()) {
133 *(content::Details<const TokenService::TokenAvailableDetails>( 176 StartInvalidator();
134 details).ptr());
135 if (token_details.service() == GaiaConstants::kSyncService) {
136 DCHECK(IsReadyToStart());
137 if (!IsStarted()) {
138 Start();
139 } else {
140 UpdateToken();
141 }
142 } 177 }
143 break; 178 break;
144 } 179 }
180 case chrome::NOTIFICATION_TOKENS_CLEARED: {
181 access_token_.clear();
182 if (IsStarted()) {
183 UpdateInvalidatorCredentials();
184 }
185 break;
186 }
145 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: { 187 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: {
146 Logout(); 188 Logout();
147 break; 189 break;
148 } 190 }
149 default: { 191 default: {
150 NOTREACHED(); 192 NOTREACHED();
151 } 193 }
152 } 194 }
153 } 195 }
154 196
197 void TiclInvalidationService::RequestAccessToken() {
198 // Only one active request at a time.
199 if (access_token_request_ != NULL)
200 return;
201 request_access_token_retry_timer_.Stop();
202 OAuth2TokenService::ScopeSet oauth2_scopes;
203 for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
204 oauth2_scopes.insert(kOAuth2Scopes[i]);
205 // Invalidate previous token, otherwise token service will return the same
206 // token again.
207 oauth2_token_service_->InvalidateToken(oauth2_scopes, access_token_);
208 access_token_.clear();
209 access_token_request_ =
210 oauth2_token_service_->StartRequest(oauth2_scopes, this);
211 }
212
213 void TiclInvalidationService::OnGetTokenSuccess(
214 const OAuth2TokenService::Request* request,
215 const std::string& access_token,
216 const base::Time& expiration_time) {
217 DCHECK_EQ(access_token_request_, request);
218 access_token_request_.reset();
219 // Reset backoff time after successful response.
220 request_access_token_backoff_.Reset();
221 access_token_ = access_token;
222 if (!IsStarted() && IsReadyToStart()) {
223 StartInvalidator();
224 } else {
225 UpdateInvalidatorCredentials();
226 }
227 }
228
229 void TiclInvalidationService::OnGetTokenFailure(
230 const OAuth2TokenService::Request* request,
231 const GoogleServiceAuthError& error) {
232 DCHECK_EQ(access_token_request_, request);
233 DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
234 access_token_request_.reset();
235 switch (error.state()) {
236 case GoogleServiceAuthError::CONNECTION_FAILED:
237 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
238 // Transient error. Retry after some time.
239 request_access_token_backoff_.InformOfRequest(false);
240 request_access_token_retry_timer_.Start(
241 FROM_HERE,
242 request_access_token_backoff_.GetTimeUntilRelease(),
243 base::Bind(&TiclInvalidationService::RequestAccessToken,
244 base::Unretained(this)));
245 break;
246 }
247 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
248 // This is a real auth error.
249 invalidator_registrar_->UpdateInvalidatorState(
250 syncer::INVALIDATION_CREDENTIALS_REJECTED);
251 break;
252 }
253 default: {
254 // We have no way to notify the user of this. Do nothing.
255 }
256 }
257 }
258
155 void TiclInvalidationService::OnInvalidatorStateChange( 259 void TiclInvalidationService::OnInvalidatorStateChange(
156 syncer::InvalidatorState state) { 260 syncer::InvalidatorState state) {
157 invalidator_registrar_->UpdateInvalidatorState(state); 261 invalidator_registrar_->UpdateInvalidatorState(state);
158 } 262 }
159 263
160 void TiclInvalidationService::OnIncomingInvalidation( 264 void TiclInvalidationService::OnIncomingInvalidation(
161 const syncer::ObjectIdInvalidationMap& invalidation_map) { 265 const syncer::ObjectIdInvalidationMap& invalidation_map) {
162 invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map); 266 invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
163 } 267 }
164 268
165 void TiclInvalidationService::Shutdown() { 269 void TiclInvalidationService::Shutdown() {
166 DCHECK(CalledOnValidThread()); 270 DCHECK(CalledOnValidThread());
167 if (IsStarted()) { 271 if (IsStarted()) {
168 StopInvalidator(); 272 StopInvalidator();
169 } 273 }
170 invalidator_storage_.reset(); 274 invalidator_storage_.reset();
171 invalidator_registrar_.reset(); 275 invalidator_registrar_.reset();
172 } 276 }
173 277
174 bool TiclInvalidationService::IsReadyToStart() { 278 bool TiclInvalidationService::IsReadyToStart() {
175 if (signin_manager_->GetAuthenticatedUsername().empty()) { 279 if (ManagedUserService::ProfileIsManaged(profile_)) {
176 DVLOG(2) << "Not starting TiclInvalidationService: user is not signed in."; 280 DVLOG(2) << "Not starting TiclInvalidationService: User is managed.";
177 return false; 281 return false;
178 } 282 }
179 283
180 if (!token_service_) { 284 if (signin_manager_->GetAuthenticatedUsername().empty()) {
285 DVLOG(2) << "Not starting TiclInvalidationService: User is not signed in.";
286 return false;
287 }
288
289 if (!oauth2_token_service_) {
181 DVLOG(2) 290 DVLOG(2)
182 << "Not starting TiclInvalidationService: TokenService unavailable."; 291 << "Not starting TiclInvalidationService: TokenService unavailable.";
183 return false; 292 return false;
184 } 293 }
185 294
186 if (!token_service_->HasTokenForService(GaiaConstants::kSyncService)) { 295 if (!oauth2_token_service_->RefreshTokenIsAvailable()) {
187 DVLOG(2) << "Not starting TiclInvalidationService: Sync token unavailable."; 296 DVLOG(2)
297 << "Not starting TiclInvalidationServce: Waiting for refresh token.";
188 return false; 298 return false;
189 } 299 }
190 300
191 return true; 301 return true;
192 } 302 }
193 303
194 bool TiclInvalidationService::IsStarted() { 304 bool TiclInvalidationService::IsStarted() {
195 return invalidator_.get() != NULL; 305 return invalidator_.get() != NULL;
196 } 306 }
197 307
198 void TiclInvalidationService::Start() { 308 void TiclInvalidationService::StartInvalidator() {
199 DCHECK(CalledOnValidThread()); 309 DCHECK(CalledOnValidThread());
200 DCHECK(!invalidator_); 310 DCHECK(!invalidator_);
201 DCHECK(invalidator_storage_); 311 DCHECK(invalidator_storage_);
202 DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty()); 312 DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());
203 313
314 if (access_token_.empty()) {
315 DVLOG(1)
316 << "TiclInvalidationService: "
317 << "Deferring start until we have an access token.";
318 RequestAccessToken();
319 return;
320 }
321
204 notifier::NotifierOptions options = 322 notifier::NotifierOptions options =
205 ParseNotifierOptions(*CommandLine::ForCurrentProcess()); 323 ParseNotifierOptions(*CommandLine::ForCurrentProcess());
206 options.request_context_getter = profile_->GetRequestContext(); 324 options.request_context_getter = profile_->GetRequestContext();
325 options.auth_mechanism = "X-OAUTH2";
207 invalidator_.reset(new syncer::NonBlockingInvalidator( 326 invalidator_.reset(new syncer::NonBlockingInvalidator(
208 options, 327 options,
209 invalidator_storage_->GetInvalidatorClientId(), 328 invalidator_storage_->GetInvalidatorClientId(),
210 invalidator_storage_->GetAllInvalidationStates(), 329 invalidator_storage_->GetAllInvalidationStates(),
211 invalidator_storage_->GetBootstrapData(), 330 invalidator_storage_->GetBootstrapData(),
212 syncer::WeakHandle<syncer::InvalidationStateTracker>( 331 syncer::WeakHandle<syncer::InvalidationStateTracker>(
213 invalidator_storage_->AsWeakPtr()), 332 invalidator_storage_->AsWeakPtr()),
214 content::GetUserAgent(GURL()))); 333 content::GetUserAgent(GURL())));
215 334
216 UpdateToken(); 335 UpdateInvalidatorCredentials();
217 336
218 invalidator_->RegisterHandler(this); 337 invalidator_->RegisterHandler(this);
219 invalidator_->UpdateRegisteredIds( 338 invalidator_->UpdateRegisteredIds(
220 this, 339 this,
221 invalidator_registrar_->GetAllRegisteredIds()); 340 invalidator_registrar_->GetAllRegisteredIds());
222 } 341 }
223 342
224 void TiclInvalidationService::UpdateToken() { 343 void TiclInvalidationService::UpdateInvalidatorCredentials() {
225 std::string email = signin_manager_->GetAuthenticatedUsername(); 344 std::string email = signin_manager_->GetAuthenticatedUsername();
345
226 DCHECK(!email.empty()) << "Expected user to be signed in."; 346 DCHECK(!email.empty()) << "Expected user to be signed in.";
227 DCHECK(token_service_->HasTokenForService(GaiaConstants::kSyncService)); 347 DCHECK(!access_token_.empty());
228
229 std::string sync_token = token_service_->GetTokenForService(
230 GaiaConstants::kSyncService);
231 348
232 DVLOG(2) << "UpdateCredentials: " << email; 349 DVLOG(2) << "UpdateCredentials: " << email;
233 invalidator_->UpdateCredentials(email, sync_token); 350 invalidator_->UpdateCredentials(email, access_token_);
234 } 351 }
235 352
236 void TiclInvalidationService::StopInvalidator() { 353 void TiclInvalidationService::StopInvalidator() {
237 DCHECK(invalidator_); 354 DCHECK(invalidator_);
238 invalidator_->UnregisterHandler(this); 355 invalidator_->UnregisterHandler(this);
239 invalidator_.reset(); 356 invalidator_.reset();
240 } 357 }
241 358
242 void TiclInvalidationService::Logout() { 359 void TiclInvalidationService::Logout() {
360 request_access_token_retry_timer_.Stop();
361
243 StopInvalidator(); 362 StopInvalidator();
244 363
245 // This service always expects to have a valid invalidator storage. 364 // This service always expects to have a valid invalidator storage.
246 // So we must not only clear the old one, but also start a new one. 365 // So we must not only clear the old one, but also start a new one.
247 invalidator_storage_->Clear(); 366 invalidator_storage_->Clear();
248 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs())); 367 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
249 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId()); 368 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
250 } 369 }
251 370
252 } // namespace invalidation 371 } // namespace invalidation
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698