146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "components/invalidation/sync_invalidation_listener.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/invalidation/invalidation_util.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/invalidation/object_id_invalidation_map.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/invalidation/registration_manager.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google/cacheinvalidation/include/invalidation-client.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google/cacheinvalidation/include/types.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kApplicationName[] = "chrome-sync";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncInvalidationListener::Delegate::~Delegate() {}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncInvalidationListener::SyncInvalidationListener(
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<SyncNetworkChannel> network_channel)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : sync_network_channel_(network_channel.Pass()),
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sync_system_resources_(sync_network_channel_.get(), this),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(NULL),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ticl_state_(DEFAULT_INVALIDATION_ERROR),
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      push_client_state_(DEFAULT_INVALIDATION_ERROR),
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_network_channel_->AddObserver(this);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncInvalidationListener::~SyncInvalidationListener() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_network_channel_->RemoveObserver(this);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!delegate_);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::Start(
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const CreateInvalidationClientCallback& create_invalidation_client_callback,
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& client_id,
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& client_info,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& invalidation_bootstrap_data,
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const UnackedInvalidationsMap& initial_unacked_invalidations,
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::WeakPtr<InvalidationStateTracker>& invalidation_state_tracker,
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const scoped_refptr<base::SequencedTaskRunner>&
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        invalidation_state_tracker_task_runner,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_system_resources_.set_platform(client_info);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_system_resources_.Start();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Storage resource is implemented as a write-through cache.  We populate
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it with the initial state on startup, so subsequent writes go to disk and
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // update the in-memory cache, while reads just return the cached state.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_system_resources_.storage()->SetInitialState(
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalidation_bootstrap_data);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unacked_invalidations_map_ = initial_unacked_invalidations;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalidation_state_tracker_ = invalidation_state_tracker;
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_ =
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      invalidation_state_tracker_task_runner;
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(invalidation_state_tracker_task_runner_.get());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!delegate_);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = delegate;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  invalidation_client_.reset(create_invalidation_client_callback.Run(
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      &sync_system_resources_,
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      sync_network_channel_->GetInvalidationClientType(),
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      client_id,
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      kApplicationName,
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      this));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalidation_client_->Start();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registration_manager_.reset(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new RegistrationManager(invalidation_client_.get()));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::UpdateCredentials(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& email, const std::string& token) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sync_network_channel_->UpdateCredentials(email, token);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::UpdateRegisteredIds(const ObjectIdSet& ids) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registered_ids_ = ids;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ticl_state_| can go to INVALIDATIONS_ENABLED even without a
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // working XMPP connection (as observed by us), so check it instead
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of GetState() (see http://crbug.com/139424).
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ticl_state_ == INVALIDATIONS_ENABLED && registration_manager_) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoRegistrationUpdate();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::Ready(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ticl_state_ = INVALIDATIONS_ENABLED;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitStateChange();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoRegistrationUpdate();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::Invalidate(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::Invalidation& invalidation,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::AckHandle& ack_handle) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->Acknowledge(ack_handle);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const invalidation::ObjectId& id = invalidation.object_id();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string payload;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // payload() CHECK()'s has_payload(), so we must check it ourselves first.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (invalidation.has_payload())
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    payload = invalidation.payload();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(2) << "Received invalidation with version " << invalidation.version()
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << " for " << ObjectIdToString(id);
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap invalidations;
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Invalidation inv = Invalidation::Init(id, invalidation.version(), payload);
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  inv.SetAckHandler(AsWeakPtr(), base::MessageLoopProxy::current());
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  invalidations.Insert(inv);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DispatchInvalidations(invalidations);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::InvalidateUnknownVersion(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::ObjectId& object_id,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::AckHandle& ack_handle) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "InvalidateUnknownVersion";
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->Acknowledge(ack_handle);
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap invalidations;
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Invalidation unknown_version = Invalidation::InitUnknownVersion(object_id);
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  unknown_version.SetAckHandler(AsWeakPtr(), base::MessageLoopProxy::current());
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  invalidations.Insert(unknown_version);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DispatchInvalidations(invalidations);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This should behave as if we got an invalidation with version
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UNKNOWN_OBJECT_VERSION for all known data types.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::InvalidateAll(
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::AckHandle& ack_handle) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "InvalidateAll";
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  client->Acknowledge(ack_handle);
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap invalidations;
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ObjectIdSet::iterator it = registered_ids_.begin();
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != registered_ids_.end(); ++it) {
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Invalidation unknown_version = Invalidation::InitUnknownVersion(*it);
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    unknown_version.SetAckHandler(AsWeakPtr(),
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                  base::MessageLoopProxy::current());
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    invalidations.Insert(unknown_version);
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DispatchInvalidations(invalidations);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// If a handler is registered, emit right away.  Otherwise, save it for later.
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SyncInvalidationListener::DispatchInvalidations(
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ObjectIdInvalidationMap& invalidations) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap to_save = invalidations;
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap to_emit =
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      invalidations.GetSubsetWithObjectIds(registered_ids_);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SaveInvalidations(to_save);
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EmitSavedInvalidations(to_emit);
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SyncInvalidationListener::SaveInvalidations(
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ObjectIdInvalidationMap& to_save) {
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdSet objects_to_save = to_save.GetObjectIds();
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ObjectIdSet::const_iterator it = objects_to_save.begin();
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != objects_to_save.end(); ++it) {
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    UnackedInvalidationsMap::iterator lookup =
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        unacked_invalidations_map_.find(*it);
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (lookup == unacked_invalidations_map_.end()) {
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      lookup = unacked_invalidations_map_.insert(
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          std::make_pair(*it, UnackedInvalidationSet(*it))).first;
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    lookup->second.AddSet(to_save.ForObject(*it));
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_->PostTask(
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&InvalidationStateTracker::SetSavedInvalidations,
2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 invalidation_state_tracker_,
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 unacked_invalidations_map_));
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SyncInvalidationListener::EmitSavedInvalidations(
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ObjectIdInvalidationMap& to_emit) {
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(2) << "Emitting invalidations: " << to_emit.ToString();
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delegate_->OnInvalidate(to_emit);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::InformRegistrationStatus(
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalidation::InvalidationClient* client,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const invalidation::ObjectId& object_id,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InvalidationListener::RegistrationState new_state) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "InformRegistrationStatus: "
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ObjectIdToString(object_id) << " " << new_state;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_state != InvalidationListener::REGISTERED) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let |registration_manager_| handle the registration backoff policy.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registration_manager_->MarkRegistrationLost(object_id);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::InformRegistrationFailure(
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::ObjectId& object_id,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_transient,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_message) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "InformRegistrationFailure: "
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ObjectIdToString(object_id)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << "is_transient=" << is_transient
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", message=" << error_message;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_transient) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't care about |unknown_hint|; we let
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |registration_manager_| handle the registration backoff policy.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registration_manager_->MarkRegistrationLost(object_id);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Non-transient failures require an action to resolve. This could happen
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // - the server doesn't yet recognize the data type, which could happen for
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   brand-new data types.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // - the user has changed his password and hasn't updated it yet locally.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Either way, block future registration attempts for |object_id|. However,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we don't forget any saved invalidation state since we may use it once the
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error is addressed.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registration_manager_->DisableId(object_id);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::ReissueRegistrations(
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& prefix,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int prefix_length) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "AllRegistrationsLost";
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registration_manager_->MarkAllRegistrationsLost();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::InformError(
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::InvalidationClient* client,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const invalidation::ErrorInfo& error_info) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(client, invalidation_client_.get());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Ticl error " << error_info.error_reason() << ": "
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << error_info.error_message()
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " (transient = " << error_info.is_transient() << ")";
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_info.error_reason() == invalidation::ErrorReason::AUTH_FAILURE) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ticl_state_ = INVALIDATION_CREDENTIALS_REJECTED;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ticl_state_ = TRANSIENT_INVALIDATION_ERROR;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitStateChange();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SyncInvalidationListener::Acknowledge(
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const invalidation::ObjectId& id,
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const syncer::AckHandle& handle) {
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UnackedInvalidationsMap::iterator lookup =
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      unacked_invalidations_map_.find(id);
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (lookup == unacked_invalidations_map_.end()) {
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DLOG(WARNING) << "Received acknowledgement for untracked object ID";
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  lookup->second.Acknowledge(handle);
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_->PostTask(
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&InvalidationStateTracker::SetSavedInvalidations,
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 invalidation_state_tracker_,
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 unacked_invalidations_map_));
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SyncInvalidationListener::Drop(
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const invalidation::ObjectId& id,
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const syncer::AckHandle& handle) {
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UnackedInvalidationsMap::iterator lookup =
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      unacked_invalidations_map_.find(id);
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (lookup == unacked_invalidations_map_.end()) {
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DLOG(WARNING) << "Received drop for untracked object ID";
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  lookup->second.Drop(handle);
3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_->PostTask(
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&InvalidationStateTracker::SetSavedInvalidations,
3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 invalidation_state_tracker_,
3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 unacked_invalidations_map_));
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::WriteState(const std::string& state) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "WriteState";
3326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_->PostTask(
3336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE,
3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&InvalidationStateTracker::SetBootstrapData,
3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 invalidation_state_tracker_,
3366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 state));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::DoRegistrationUpdate() {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ObjectIdSet& unregistered_ids =
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      registration_manager_->UpdateRegisteredIds(registered_ids_);
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (ObjectIdSet::iterator it = unregistered_ids.begin();
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != unregistered_ids.end(); ++it) {
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    unacked_invalidations_map_.erase(*it);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  invalidation_state_tracker_task_runner_->PostTask(
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      FROM_HERE,
3496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&InvalidationStateTracker::SetSavedInvalidations,
3506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 invalidation_state_tracker_,
3516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 unacked_invalidations_map_));
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ObjectIdInvalidationMap object_id_invalidation_map;
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (UnackedInvalidationsMap::iterator map_it =
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       unacked_invalidations_map_.begin();
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       map_it != unacked_invalidations_map_.end(); ++map_it) {
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (registered_ids_.find(map_it->first) == registered_ids_.end()) {
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      continue;
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
3606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    map_it->second.ExportInvalidations(AsWeakPtr(),
3616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       base::MessageLoopProxy::current(),
3626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                       &object_id_invalidation_map);
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // There's no need to run these through DispatchInvalidations(); they've
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // already been saved to storage (that's where we found them) so all we need
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // to do now is emit them.
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EmitSavedInvalidations(object_id_invalidation_map);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SyncInvalidationListener::RequestDetailedStatus(
372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    base::Callback<void(const base::DictionaryValue&)> callback) const {
373a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(CalledOnValidThread());
37423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  sync_network_channel_->RequestDetailedStatus(callback);
375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  callback.Run(*CollectDebugData());
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
37823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)scoped_ptr<base::DictionaryValue>
37923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)SyncInvalidationListener::CollectDebugData() const {
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> return_value(new base::DictionaryValue());
38123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return_value->SetString(
38223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      "SyncInvalidationListener.PushClientState",
38323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      std::string(InvalidatorStateToString(push_client_state_)));
38423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return_value->SetString("SyncInvalidationListener.TiclState",
38523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          std::string(InvalidatorStateToString(ticl_state_)));
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> unacked_map(new base::DictionaryValue());
38723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (UnackedInvalidationsMap::const_iterator it =
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           unacked_invalidations_map_.begin();
389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       it != unacked_invalidations_map_.end();
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       ++it) {
391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    unacked_map->Set((it->first).name(), (it->second).ToValue().release());
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
39323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return_value->Set("SyncInvalidationListener.UnackedInvalidationsMap",
39423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                    unacked_map.release());
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return return_value.Pass();
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::StopForTest() {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stop();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::Stop() {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!invalidation_client_) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  registration_manager_.reset();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_system_resources_.Stop();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalidation_client_->Stop();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalidation_client_.reset();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_ = NULL;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ticl_state_ = DEFAULT_INVALIDATION_ERROR;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_state_ = DEFAULT_INVALIDATION_ERROR;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InvalidatorState SyncInvalidationListener::GetState() const {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ticl_state_ == INVALIDATION_CREDENTIALS_REJECTED ||
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      push_client_state_ == INVALIDATION_CREDENTIALS_REJECTED) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If either the ticl or the push client rejected our credentials,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // return INVALIDATION_CREDENTIALS_REJECTED.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return INVALIDATION_CREDENTIALS_REJECTED;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ticl_state_ == INVALIDATIONS_ENABLED &&
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      push_client_state_ == INVALIDATIONS_ENABLED) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the ticl is ready and the push client notifications are
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // enabled, return INVALIDATIONS_ENABLED.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return INVALIDATIONS_ENABLED;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we have a transient error.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRANSIENT_INVALIDATION_ERROR;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInvalidationListener::EmitStateChange() {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->OnInvalidatorStateChange(GetState());
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::WeakPtr<AckHandler> SyncInvalidationListener::AsWeakPtr() {
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(CalledOnValidThread());
4456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::WeakPtr<AckHandler> weak_ptr = weak_ptr_factory_.GetWeakPtr();
4466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  weak_ptr.get();  // Binds the pointer to this thread.
4476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return weak_ptr;
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SyncInvalidationListener::OnNetworkChannelStateChanged(
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InvalidatorState invalidator_state) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  push_client_state_ = invalidator_state;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EmitStateChange();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncer
458