1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// found in the LICENSE file.
4a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/invalidation/ticl_invalidation_service.h"
6a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
7a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "base/command_line.h"
83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/metrics/histogram.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/gcm_driver/gcm_driver.h"
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/invalidation/gcm_invalidation_bridge.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/invalidation/invalidation_service_util.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/invalidation/invalidation_util.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/invalidation/invalidator.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/invalidation/invalidator_state.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/invalidation/non_blocking_invalidator.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/invalidation/object_id_invalidation_map.h"
17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "net/url_request/url_request_context_getter.h"
19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const char* kOAuth2Scopes[] = {
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GaiaConstants::kGoogleTalkOAuth2Scope
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Number of initial errors (in sequence) to ignore before applying
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // exponential back-off rules.
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  0,
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Initial delay for exponential back-off in ms.
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  2000,
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Factor by which the waiting time will be multiplied.
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  2,
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Fuzzing percentage. ex: 10% will spread requests randomly
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // between 90%-100% of the calculated time.
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  0.2, // 20%
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Maximum amount of time we are willing to delay our request in ms.
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(pavely): crbug.com/246686 ProfileSyncService should retry
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // RequestAccessToken on connection state change after backoff
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  1000 * 3600 * 4, // 4 hours.
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Time to keep an entry from being discarded even when it
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // has no significant state, -1 to never discard.
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  -1,
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Don't use initial delay unless the last request was an error.
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  false,
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)namespace invalidation {
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTiclInvalidationService::TiclInvalidationService(
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& user_agent,
560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scoped_ptr<IdentityProvider> identity_provider,
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    scoped_ptr<TiclSettingsProvider> settings_provider,
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    gcm::GCMDriver* gcm_driver,
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<net::URLRequestContextGetter>& request_context)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : OAuth2TokenService::Consumer("ticl_invalidation"),
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      user_agent_(user_agent),
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      identity_provider_(identity_provider.Pass()),
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      settings_provider_(settings_provider.Pass()),
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      invalidator_registrar_(new syncer::InvalidatorRegistrar()),
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
661675a649fd7a8b3cb80ffddae2dc181f122353c5Ben Murdoch      network_channel_type_(GCM_NETWORK_CHANNEL),
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      gcm_driver_(gcm_driver),
680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      request_context_(request_context),
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      logger_() {}
70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)TiclInvalidationService::~TiclInvalidationService() {
72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  settings_provider_->RemoveObserver(this);
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  identity_provider_->RemoveActiveAccountRefreshTokenObserver(this);
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  identity_provider_->RemoveObserver(this);
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (IsStarted()) {
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    StopInvalidator();
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid TiclInvalidationService::Init(
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scoped_ptr<syncer::InvalidationStateTracker> invalidation_state_tracker) {
83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  invalidation_state_tracker_ = invalidation_state_tracker.Pass();
85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (invalidation_state_tracker_->GetInvalidatorClientId().empty()) {
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    invalidation_state_tracker_->ClearAndSetNewClientId(
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        GenerateInvalidatorClientId());
89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  UpdateInvalidationNetworkChannel();
92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (IsReadyToStart()) {
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    StartInvalidator(network_channel_type_);
94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  identity_provider_->AddObserver(this);
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  identity_provider_->AddActiveAccountRefreshTokenObserver(this);
985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  settings_provider_->AddObserver(this);
99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid TiclInvalidationService::InitForTest(
1020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    scoped_ptr<syncer::InvalidationStateTracker> invalidation_state_tracker,
1030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    syncer::Invalidator* invalidator) {
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Here we perform the equivalent of Init() and StartInvalidator(), but with
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // some minor changes to account for the fact that we're injecting the
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // invalidator.
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  invalidation_state_tracker_ = invalidation_state_tracker.Pass();
108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_.reset(invalidator);
109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_->RegisterHandler(this);
111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_->UpdateRegisteredIds(
112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      this,
113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      invalidator_registrar_->GetAllRegisteredIds());
114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TiclInvalidationService::RegisterInvalidationHandler(
117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    syncer::InvalidationHandler* handler) {
118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(2) << "Registering an invalidation handler";
120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_registrar_->RegisterHandler(handler);
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  logger_.OnRegistration(handler->GetOwnerName());
122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TiclInvalidationService::UpdateRegisteredInvalidationIds(
125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    syncer::InvalidationHandler* handler,
126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const syncer::ObjectIdSet& ids) {
127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(2) << "Registering ids: " << ids.size();
129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_registrar_->UpdateRegisteredIds(handler, ids);
130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (invalidator_) {
131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    invalidator_->UpdateRegisteredIds(
132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        this,
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        invalidator_registrar_->GetAllRegisteredIds());
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  logger_.OnUpdateIds(invalidator_registrar_->GetSanitizedHandlersIdsMap());
136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TiclInvalidationService::UnregisterInvalidationHandler(
139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    syncer::InvalidationHandler* handler) {
140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(2) << "Unregistering";
142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_registrar_->UnregisterHandler(handler);
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (invalidator_) {
144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    invalidator_->UpdateRegisteredIds(
145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        this,
146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        invalidator_registrar_->GetAllRegisteredIds());
147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  logger_.OnUnregistration(handler->GetOwnerName());
149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)syncer::InvalidatorState TiclInvalidationService::GetInvalidatorState() const {
152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (invalidator_) {
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DVLOG(2) << "GetInvalidatorState returning "
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        << invalidator_->GetInvalidatorState();
156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return invalidator_->GetInvalidatorState();
157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  } else {
158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(2) << "Invalidator currently stopped";
159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return syncer::TRANSIENT_INVALIDATION_ERROR;
160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string TiclInvalidationService::GetInvalidatorClientId() const {
164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return invalidation_state_tracker_->GetInvalidatorClientId();
166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)InvalidationLogger* TiclInvalidationService::GetInvalidationLogger() {
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return &logger_;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1720529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochIdentityProvider* TiclInvalidationService::GetIdentityProvider() {
1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return identity_provider_.get();
174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void TiclInvalidationService::RequestDetailedStatus(
177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    base::Callback<void(const base::DictionaryValue&)> return_callback) const {
178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (IsStarted()) {
179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return_callback.Run(network_channel_options_);
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    invalidator_->RequestDetailedStatus(return_callback);
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TiclInvalidationService::RequestAccessToken() {
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Only one active request at a time.
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (access_token_request_ != NULL)
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_access_token_retry_timer_.Stop();
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OAuth2TokenService::ScopeSet oauth2_scopes;
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    oauth2_scopes.insert(kOAuth2Scopes[i]);
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Invalidate previous token, otherwise token service will return the same
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // token again.
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const std::string& account_id = identity_provider_->GetActiveAccountId();
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  OAuth2TokenService* token_service = identity_provider_->GetTokenService();
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  token_service->InvalidateToken(account_id, oauth2_scopes, access_token_);
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  access_token_.clear();
19823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  access_token_request_ =
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      token_service->StartRequest(account_id, oauth2_scopes, this);
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TiclInvalidationService::OnGetTokenSuccess(
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const OAuth2TokenService::Request* request,
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& access_token,
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const base::Time& expiration_time) {
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_EQ(access_token_request_, request);
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  access_token_request_.reset();
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Reset backoff time after successful response.
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  request_access_token_backoff_.Reset();
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  access_token_ = access_token;
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!IsStarted() && IsReadyToStart()) {
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    StartInvalidator(network_channel_type_);
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UpdateInvalidatorCredentials();
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TiclInvalidationService::OnGetTokenFailure(
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const OAuth2TokenService::Request* request,
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const GoogleServiceAuthError& error) {
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_EQ(access_token_request_, request);
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  access_token_request_.reset();
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (error.state()) {
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case GoogleServiceAuthError::CONNECTION_FAILED:
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case GoogleServiceAuthError::SERVICE_UNAVAILABLE: {
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Transient error. Retry after some time.
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      request_access_token_backoff_.InformOfRequest(false);
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      request_access_token_retry_timer_.Start(
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            FROM_HERE,
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            request_access_token_backoff_.GetTimeUntilRelease(),
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            base::Bind(&TiclInvalidationService::RequestAccessToken,
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       base::Unretained(this)));
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case GoogleServiceAuthError::SERVICE_ERROR:
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      invalidator_registrar_->UpdateInvalidatorState(
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          syncer::INVALIDATION_CREDENTIALS_REJECTED);
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      break;
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    default: {
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // We have no way to notify the user of this.  Do nothing.
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TiclInvalidationService::OnRefreshTokenAvailable(
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id) {
2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!IsStarted() && IsReadyToStart())
2510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    StartInvalidator(network_channel_type_);
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TiclInvalidationService::OnRefreshTokenRevoked(
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const std::string& account_id) {
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  access_token_.clear();
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (IsStarted())
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    UpdateInvalidatorCredentials();
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid TiclInvalidationService::OnActiveAccountLogout() {
26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  access_token_request_.reset();
26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  request_access_token_retry_timer_.Stop();
26423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
26523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (IsStarted()) {
26623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    StopInvalidator();
26723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
26823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // This service always expects to have a valid invalidation state. Thus, we
2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // must generate a new client ID to replace the existing one. Setting a new
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // client ID also clears all other state.
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  invalidation_state_tracker_->
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      ClearAndSetNewClientId(GenerateInvalidatorClientId());
27423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
27523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid TiclInvalidationService::OnUseGCMChannelChanged() {
2775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  UpdateInvalidationNetworkChannel();
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TiclInvalidationService::OnInvalidatorStateChange(
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    syncer::InvalidatorState state) {
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (state == syncer::INVALIDATION_CREDENTIALS_REJECTED) {
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // This may be due to normal OAuth access token expiration.  If so, we must
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // fetch a new one using our refresh token.  Resetting the invalidator's
285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // access token will not reset the invalidator's exponential backoff, so
286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // it's safe to try to update the token every time we receive this signal.
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    //
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // We won't be receiving any invalidations while the refresh is in progress,
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // we set our state to TRANSIENT_INVALIDATION_ERROR.  If the credentials
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // really are invalid, the refresh request should fail and
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // OnGetTokenFailure() will put us into a INVALIDATION_CREDENTIALS_REJECTED
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // state.
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidator_registrar_->UpdateInvalidatorState(
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        syncer::TRANSIENT_INVALIDATION_ERROR);
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    RequestAccessToken();
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  } else {
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    invalidator_registrar_->UpdateInvalidatorState(state);
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  logger_.OnStateChange(state);
300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void TiclInvalidationService::OnIncomingInvalidation(
303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const syncer::ObjectIdInvalidationMap& invalidation_map) {
304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_registrar_->DispatchInvalidationsToHandlers(invalidation_map);
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  logger_.OnInvalidation(invalidation_map);
307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string TiclInvalidationService::GetOwnerName() const { return "TICL"; }
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool TiclInvalidationService::IsReadyToStart() {
3120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (identity_provider_->GetActiveAccountId().empty()) {
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DVLOG(2) << "Not starting TiclInvalidationService: User is not signed in.";
314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
316a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  OAuth2TokenService* token_service = identity_provider_->GetTokenService();
31823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!token_service) {
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DVLOG(2)
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        << "Not starting TiclInvalidationService: "
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        << "OAuth2TokenService unavailable.";
322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!token_service->RefreshTokenIsAvailable(
3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          identity_provider_->GetActiveAccountId())) {
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DVLOG(2)
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        << "Not starting TiclInvalidationServce: Waiting for refresh token.";
329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
330a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
331a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return true;
333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
334a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool TiclInvalidationService::IsStarted() const {
336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return invalidator_.get() != NULL;
337a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
338a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TiclInvalidationService::StartInvalidator(
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    InvalidationNetworkChannel network_channel) {
341a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(CalledOnValidThread());
342a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(!invalidator_);
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(invalidation_state_tracker_);
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DCHECK(!invalidation_state_tracker_->GetInvalidatorClientId().empty());
345a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Request access token for PushClientChannel. GCMNetworkChannel will request
347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // access token before sending message to server.
348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (network_channel == PUSH_CLIENT_CHANNEL && access_token_.empty()) {
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DVLOG(1)
350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        << "TiclInvalidationService: "
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        << "Deferring start until we have an access token.";
352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestAccessToken();
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  syncer::NetworkChannelCreator network_channel_creator;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (network_channel) {
3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case PUSH_CLIENT_CHANNEL: {
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      notifier::NotifierOptions options =
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ParseNotifierOptions(*CommandLine::ForCurrentProcess());
3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      options.request_context_getter = request_context_;
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      options.auth_mechanism = "X-OAUTH2";
36423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      network_channel_options_.SetString("Options.HostPort",
36523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         options.xmpp_host_port.ToString());
36623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      network_channel_options_.SetString("Options.AuthMechanism",
36723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         options.auth_mechanism);
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK_EQ(notifier::NOTIFICATION_SERVER, options.notification_method);
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      network_channel_creator =
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::NonBlockingInvalidator::MakePushClientChannelCreator(options);
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    case GCM_NETWORK_CHANNEL: {
3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      gcm_invalidation_bridge_.reset(new GCMInvalidationBridge(
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          gcm_driver_, identity_provider_.get()));
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      network_channel_creator =
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::NonBlockingInvalidator::MakeGCMNetworkChannelCreator(
3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              request_context_,
379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              gcm_invalidation_bridge_->CreateDelegate().Pass());
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      break;
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    default: {
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "Invalidations.NetworkChannel", network_channel, NETWORK_CHANNELS_COUNT);
390a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_.reset(new syncer::NonBlockingInvalidator(
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          network_channel_creator,
3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          invalidation_state_tracker_->GetInvalidatorClientId(),
3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          invalidation_state_tracker_->GetSavedInvalidations(),
3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          invalidation_state_tracker_->GetBootstrapData(),
3950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          invalidation_state_tracker_.get(),
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          user_agent_,
3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          request_context_));
398a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UpdateInvalidatorCredentials();
400a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
401a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_->RegisterHandler(this);
402a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  invalidator_->UpdateRegisteredIds(
403a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      this,
404a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      invalidator_registrar_->GetAllRegisteredIds());
405a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
406a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
407effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid TiclInvalidationService::UpdateInvalidationNetworkChannel() {
4085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const InvalidationNetworkChannel network_channel_type =
4095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      settings_provider_->UseGCMChannel() ? GCM_NETWORK_CHANNEL
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                          : PUSH_CLIENT_CHANNEL;
411effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (network_channel_type_ == network_channel_type)
412effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  network_channel_type_ = network_channel_type;
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (IsStarted()) {
415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    StopInvalidator();
416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    StartInvalidator(network_channel_type_);
417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TiclInvalidationService::UpdateInvalidatorCredentials() {
4210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  std::string email = identity_provider_->GetActiveAccountId();
422a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!email.empty()) << "Expected user to be signed in.";
424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
425a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DVLOG(2) << "UpdateCredentials: " << email;
426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  invalidator_->UpdateCredentials(email, access_token_);
427a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
428a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TiclInvalidationService::StopInvalidator() {
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(invalidator_);
431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gcm_invalidation_bridge_.reset();
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  invalidator_->UnregisterHandler(this);
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  invalidator_.reset();
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
436a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}  // namespace invalidation
437