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

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

Issue 17911005: Merge 208347 "Revert 208315 "Make use of InvalidationService"" (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1547/src/
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
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"
10 #include "chrome/browser/profiles/profile.h" 9 #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"
13 #include "chrome/browser/signin/signin_manager.h" 10 #include "chrome/browser/signin/signin_manager.h"
11 #include "chrome/browser/signin/token_service.h"
14 #include "chrome/common/chrome_notification_types.h" 12 #include "chrome/common/chrome_notification_types.h"
15 #include "content/public/browser/notification_service.h" 13 #include "content/public/browser/notification_service.h"
16 #include "google_apis/gaia/gaia_constants.h" 14 #include "google_apis/gaia/gaia_constants.h"
17 #include "sync/notifier/invalidator.h" 15 #include "sync/notifier/invalidator.h"
18 #include "sync/notifier/invalidator_state.h" 16 #include "sync/notifier/invalidator_state.h"
19 #include "sync/notifier/non_blocking_invalidator.h" 17 #include "sync/notifier/non_blocking_invalidator.h"
20 18
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
53 namespace invalidation { 19 namespace invalidation {
54 20
55 TiclInvalidationService::TiclInvalidationService( 21 TiclInvalidationService::TiclInvalidationService(SigninManagerBase* signin,
56 SigninManagerBase* signin, 22 TokenService* token_service,
57 TokenService* token_service, 23 Profile* profile)
58 OAuth2TokenService* oauth2_token_service, 24 : profile_(profile),
59 Profile* profile) 25 signin_manager_(signin),
60 : profile_(profile), 26 token_service_(token_service),
61 signin_manager_(signin), 27 invalidator_registrar_(new syncer::InvalidatorRegistrar()) { }
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 }
67 28
68 TiclInvalidationService::~TiclInvalidationService() { 29 TiclInvalidationService::~TiclInvalidationService() {
69 DCHECK(CalledOnValidThread()); 30 DCHECK(CalledOnValidThread());
70 } 31 }
71 32
72 void TiclInvalidationService::Init() { 33 void TiclInvalidationService::Init() {
73 DCHECK(CalledOnValidThread()); 34 DCHECK(CalledOnValidThread());
74 35
75 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs())); 36 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
76 if (invalidator_storage_->GetInvalidatorClientId().empty()) { 37 if (invalidator_storage_->GetInvalidatorClientId().empty()) {
77 // This also clears any existing state. We can't reuse old invalidator 38 // This also clears any existing state. We can't reuse old invalidator
78 // state with the new ID anyway. 39 // state with the new ID anyway.
79 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId()); 40 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
80 } 41 }
81 42
82 if (IsReadyToStart()) { 43 if (IsReadyToStart()) {
83 StartInvalidator(); 44 Start();
84 } 45 }
85 46
86 notification_registrar_.Add(this, 47 notification_registrar_.Add(this,
48 chrome::NOTIFICATION_TOKEN_AVAILABLE,
49 content::Source<TokenService>(token_service_));
50 notification_registrar_.Add(this,
87 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, 51 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
88 content::Source<Profile>(profile_)); 52 content::Source<Profile>(profile_));
89 notification_registrar_.Add(this,
90 chrome::NOTIFICATION_TOKEN_LOADING_FINISHED,
91 content::Source<TokenService>(token_service_));
92 notification_registrar_.Add(this,
93 chrome::NOTIFICATION_TOKENS_CLEARED,
94 content::Source<TokenService>(token_service_));
95 } 53 }
96 54
97 void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) { 55 void TiclInvalidationService::InitForTest(syncer::Invalidator* invalidator) {
98 // Here we perform the equivalent of Init() and StartInvalidator(), but with 56 // Here we perform the equivalent of Init() and Start(), but with some minor
99 // some minor changes to account for the fact that we're injecting the 57 // changes to account for the fact that we're injecting the invalidator.
100 // invalidator.
101 invalidator_.reset(invalidator); 58 invalidator_.reset(invalidator);
102 59
103 invalidator_->RegisterHandler(this); 60 invalidator_->RegisterHandler(this);
104 invalidator_->UpdateRegisteredIds( 61 invalidator_->UpdateRegisteredIds(
105 this, 62 this,
106 invalidator_registrar_->GetAllRegisteredIds()); 63 invalidator_registrar_->GetAllRegisteredIds());
107 } 64 }
108 65
109 void TiclInvalidationService::RegisterInvalidationHandler( 66 void TiclInvalidationService::RegisterInvalidationHandler(
110 syncer::InvalidationHandler* handler) { 67 syncer::InvalidationHandler* handler) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 return invalidator_storage_->GetInvalidatorClientId(); 121 return invalidator_storage_->GetInvalidatorClientId();
165 } 122 }
166 123
167 void TiclInvalidationService::Observe( 124 void TiclInvalidationService::Observe(
168 int type, 125 int type,
169 const content::NotificationSource& source, 126 const content::NotificationSource& source,
170 const content::NotificationDetails& details) { 127 const content::NotificationDetails& details) {
171 DCHECK(CalledOnValidThread()); 128 DCHECK(CalledOnValidThread());
172 129
173 switch (type) { 130 switch (type) {
174 case chrome::NOTIFICATION_TOKEN_LOADING_FINISHED: { 131 case chrome::NOTIFICATION_TOKEN_AVAILABLE: {
175 if (!IsStarted() && IsReadyToStart()) { 132 const TokenService::TokenAvailableDetails& token_details =
176 StartInvalidator(); 133 *(content::Details<const TokenService::TokenAvailableDetails>(
177 } 134 details).ptr());
178 break; 135 if (token_details.service() == GaiaConstants::kSyncService) {
179 } 136 DCHECK(IsReadyToStart());
180 case chrome::NOTIFICATION_TOKENS_CLEARED: { 137 if (!IsStarted()) {
181 access_token_.clear(); 138 Start();
182 if (IsStarted()) { 139 } else {
183 UpdateInvalidatorCredentials(); 140 UpdateToken();
141 }
184 } 142 }
185 break; 143 break;
186 } 144 }
187 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: { 145 case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: {
188 Logout(); 146 Logout();
189 break; 147 break;
190 } 148 }
191 default: { 149 default: {
192 NOTREACHED(); 150 NOTREACHED();
193 } 151 }
194 } 152 }
195 } 153 }
196 154
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
259 void TiclInvalidationService::OnInvalidatorStateChange( 155 void TiclInvalidationService::OnInvalidatorStateChange(
260 syncer::InvalidatorState state) { 156 syncer::InvalidatorState state) {
261 invalidator_registrar_->UpdateInvalidatorState(state); 157 invalidator_registrar_->UpdateInvalidatorState(state);
262 } 158 }
263 159
264 void TiclInvalidationService::OnIncomingInvalidation( 160 void TiclInvalidationService::OnIncomingInvalidation(
265 const syncer::ObjectIdInvalidationMap& invalidation_map) { 161 const syncer::ObjectIdInvalidationMap& invalidation_map) {
266 invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map); 162 invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
267 } 163 }
268 164
269 void TiclInvalidationService::Shutdown() { 165 void TiclInvalidationService::Shutdown() {
270 DCHECK(CalledOnValidThread()); 166 DCHECK(CalledOnValidThread());
271 if (IsStarted()) { 167 if (IsStarted()) {
272 StopInvalidator(); 168 StopInvalidator();
273 } 169 }
274 invalidator_storage_.reset(); 170 invalidator_storage_.reset();
275 invalidator_registrar_.reset(); 171 invalidator_registrar_.reset();
276 } 172 }
277 173
278 bool TiclInvalidationService::IsReadyToStart() { 174 bool TiclInvalidationService::IsReadyToStart() {
279 if (ManagedUserService::ProfileIsManaged(profile_)) { 175 if (signin_manager_->GetAuthenticatedUsername().empty()) {
280 DVLOG(2) << "Not starting TiclInvalidationService: User is managed."; 176 DVLOG(2) << "Not starting TiclInvalidationService: user is not signed in.";
281 return false; 177 return false;
282 } 178 }
283 179
284 if (signin_manager_->GetAuthenticatedUsername().empty()) { 180 if (!token_service_) {
285 DVLOG(2) << "Not starting TiclInvalidationService: User is not signed in.";
286 return false;
287 }
288
289 if (!oauth2_token_service_) {
290 DVLOG(2) 181 DVLOG(2)
291 << "Not starting TiclInvalidationService: TokenService unavailable."; 182 << "Not starting TiclInvalidationService: TokenService unavailable.";
292 return false; 183 return false;
293 } 184 }
294 185
295 if (!oauth2_token_service_->RefreshTokenIsAvailable()) { 186 if (!token_service_->HasTokenForService(GaiaConstants::kSyncService)) {
296 DVLOG(2) 187 DVLOG(2) << "Not starting TiclInvalidationService: Sync token unavailable.";
297 << "Not starting TiclInvalidationServce: Waiting for refresh token.";
298 return false; 188 return false;
299 } 189 }
300 190
301 return true; 191 return true;
302 } 192 }
303 193
304 bool TiclInvalidationService::IsStarted() { 194 bool TiclInvalidationService::IsStarted() {
305 return invalidator_.get() != NULL; 195 return invalidator_.get() != NULL;
306 } 196 }
307 197
308 void TiclInvalidationService::StartInvalidator() { 198 void TiclInvalidationService::Start() {
309 DCHECK(CalledOnValidThread()); 199 DCHECK(CalledOnValidThread());
310 DCHECK(!invalidator_); 200 DCHECK(!invalidator_);
311 DCHECK(invalidator_storage_); 201 DCHECK(invalidator_storage_);
312 DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty()); 202 DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());
313 203
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
322 notifier::NotifierOptions options = 204 notifier::NotifierOptions options =
323 ParseNotifierOptions(*CommandLine::ForCurrentProcess()); 205 ParseNotifierOptions(*CommandLine::ForCurrentProcess());
324 options.request_context_getter = profile_->GetRequestContext(); 206 options.request_context_getter = profile_->GetRequestContext();
325 options.auth_mechanism = "X-OAUTH2";
326 invalidator_.reset(new syncer::NonBlockingInvalidator( 207 invalidator_.reset(new syncer::NonBlockingInvalidator(
327 options, 208 options,
328 invalidator_storage_->GetInvalidatorClientId(), 209 invalidator_storage_->GetInvalidatorClientId(),
329 invalidator_storage_->GetAllInvalidationStates(), 210 invalidator_storage_->GetAllInvalidationStates(),
330 invalidator_storage_->GetBootstrapData(), 211 invalidator_storage_->GetBootstrapData(),
331 syncer::WeakHandle<syncer::InvalidationStateTracker>( 212 syncer::WeakHandle<syncer::InvalidationStateTracker>(
332 invalidator_storage_->AsWeakPtr()), 213 invalidator_storage_->AsWeakPtr()),
333 content::GetUserAgent(GURL()))); 214 content::GetUserAgent(GURL())));
334 215
335 UpdateInvalidatorCredentials(); 216 UpdateToken();
336 217
337 invalidator_->RegisterHandler(this); 218 invalidator_->RegisterHandler(this);
338 invalidator_->UpdateRegisteredIds( 219 invalidator_->UpdateRegisteredIds(
339 this, 220 this,
340 invalidator_registrar_->GetAllRegisteredIds()); 221 invalidator_registrar_->GetAllRegisteredIds());
341 } 222 }
342 223
343 void TiclInvalidationService::UpdateInvalidatorCredentials() { 224 void TiclInvalidationService::UpdateToken() {
344 std::string email = signin_manager_->GetAuthenticatedUsername(); 225 std::string email = signin_manager_->GetAuthenticatedUsername();
226 DCHECK(!email.empty()) << "Expected user to be signed in.";
227 DCHECK(token_service_->HasTokenForService(GaiaConstants::kSyncService));
345 228
346 DCHECK(!email.empty()) << "Expected user to be signed in."; 229 std::string sync_token = token_service_->GetTokenForService(
347 DCHECK(!access_token_.empty()); 230 GaiaConstants::kSyncService);
348 231
349 DVLOG(2) << "UpdateCredentials: " << email; 232 DVLOG(2) << "UpdateCredentials: " << email;
350 invalidator_->UpdateCredentials(email, access_token_); 233 invalidator_->UpdateCredentials(email, sync_token);
351 } 234 }
352 235
353 void TiclInvalidationService::StopInvalidator() { 236 void TiclInvalidationService::StopInvalidator() {
354 DCHECK(invalidator_); 237 DCHECK(invalidator_);
355 invalidator_->UnregisterHandler(this); 238 invalidator_->UnregisterHandler(this);
356 invalidator_.reset(); 239 invalidator_.reset();
357 } 240 }
358 241
359 void TiclInvalidationService::Logout() { 242 void TiclInvalidationService::Logout() {
360 request_access_token_retry_timer_.Stop();
361
362 StopInvalidator(); 243 StopInvalidator();
363 244
364 // This service always expects to have a valid invalidator storage. 245 // This service always expects to have a valid invalidator storage.
365 // So we must not only clear the old one, but also start a new one. 246 // So we must not only clear the old one, but also start a new one.
366 invalidator_storage_->Clear(); 247 invalidator_storage_->Clear();
367 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs())); 248 invalidator_storage_.reset(new InvalidatorStorage(profile_->GetPrefs()));
368 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId()); 249 invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
369 } 250 }
370 251
371 } // namespace invalidation 252 } // namespace invalidation
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698