15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/sync_manager_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/sync_scheduler.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/engine/syncer_types.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/change_reorder_buffer.h"
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "sync/internal_api/public/base/cancelation_signal.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base/model_type.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/base_node.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/configure_reason.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/engine/polling_constants.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/http_post_provider_factory.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/internal_components_factory.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/read_node.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/read_transaction.h"
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "sync/internal_api/public/sync_core_proxy.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/user_share.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/experiments.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/write_node.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/write_transaction.h"
36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "sync/internal_api/sync_core.h"
37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "sync/internal_api/sync_core_proxy_impl.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/syncapi_internal.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/syncapi_server_connection_manager.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/notifier/invalidation_util.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/notifier/invalidator.h"
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "sync/notifier/object_id_invalidation_map.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/proto_value_conversions.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/sync.pb.h"
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "sync/sessions/directory_type_debug_info_emitter.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/in_memory_directory_backing_store.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/on_disk_directory_backing_store.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using sync_pb::GetUpdatesCallerInfo;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using sessions::SyncSessionContext;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::ImmutableWriteTransactionInfo;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncable::SPECIFICS;
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using syncable::UNIQUE_POSITION;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delays for syncer nudges.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDefaultNudgeDelayMilliseconds = 200;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kPreferencesNudgeDelayMilliseconds = 2000;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSyncRefreshDelayMsec = 500;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSyncSchedulerDelayMsec = 250;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason(
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureReason reason) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (reason) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONFIGURE_REASON_RECONFIGURATION:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetUpdatesCallerInfo::RECONFIGURATION;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONFIGURE_REASON_MIGRATION:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetUpdatesCallerInfo::MIGRATION;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONFIGURE_REASON_NEW_CLIENT:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetUpdatesCallerInfo::NEW_CLIENT;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE:
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case CONFIGURE_REASON_CRYPTO:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetUpdatesCallerInfo::UNKNOWN;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class to calculate nudge delays for types.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NudgeStrategy {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TimeDelta GetNudgeDelayTimeDelta(const ModelType& model_type,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          SyncManagerImpl* core) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NudgeDelayStrategy delay_type = GetNudgeDelayStrategy(model_type);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetNudgeDelayTimeDeltaFromType(delay_type,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          model_type,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          core);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Possible types of nudge delay for datatypes.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: These are just hints. If a sync happens then all dirty entries
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would be committed as part of the sync.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum NudgeDelayStrategy {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sync right away.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IMMEDIATE,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sync this change while syncing another change.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ACCOMPANY_ONLY,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The datatype does not use one of the predefined wait times but defines
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // its own wait time logic for nudge.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CUSTOM,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static NudgeDelayStrategy GetNudgeDelayStrategy(const ModelType& type) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case AUTOFILL:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       return ACCOMPANY_ONLY;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case PREFERENCES:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case SESSIONS:
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     case FAVICON_IMAGES:
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     case FAVICON_TRACKING:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       return CUSTOM;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     default:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       return IMMEDIATE;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static TimeDelta GetNudgeDelayTimeDeltaFromType(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const NudgeDelayStrategy& delay_type, const ModelType& model_type,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const SyncManagerImpl* core) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(core);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeDelta delay = TimeDelta::FromMilliseconds(
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       kDefaultNudgeDelayMilliseconds);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (delay_type) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case IMMEDIATE:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       delay = TimeDelta::FromMilliseconds(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kDefaultNudgeDelayMilliseconds);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case ACCOMPANY_ONLY:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       delay = TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       break;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     case CUSTOM:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       switch (model_type) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case PREFERENCES:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           delay = TimeDelta::FromMilliseconds(
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               kPreferencesNudgeDelayMilliseconds);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           break;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case SESSIONS:
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         case FAVICON_IMAGES:
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         case FAVICON_TRACKING:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           delay = core->scheduler()->GetSessionsCommitDelay();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           break;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         default:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           NOTREACHED();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       break;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     default:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NOTREACHED();
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return delay;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncManagerImpl::SyncManagerImpl(const std::string& name)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : name_(name),
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      change_delegate_(NULL),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initialized_(false),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observing_network_connectivity_changes_(false),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      invalidator_state_(DEFAULT_INVALIDATION_ERROR),
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      report_unrecoverable_error_function_(NULL),
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre-fill |notification_info_map_|.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_info_map_.insert(
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::make_pair(ModelTypeFromInt(i), NotificationInfo()));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncManagerImpl::~SyncManagerImpl() {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!initialized_);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncManagerImpl::NotificationInfo::NotificationInfo() : total_count(0) {}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncManagerImpl::NotificationInfo::~NotificationInfo() {}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::DictionaryValue* SyncManagerImpl::NotificationInfo::ToValue() const {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* value = new base::DictionaryValue();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetInteger("totalCount", total_count);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->SetString("payload", payload);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return value;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::VisiblePositionsDiffer(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncable::EntryKernelMutation& mutation) const {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::EntryKernel& a = mutation.original;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::EntryKernel& b = mutation.mutated;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!b.ShouldMaintainPosition())
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!a.ref(UNIQUE_POSITION).Equals(b.ref(UNIQUE_POSITION)))
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (a.ref(syncable::PARENT_ID) != b.ref(syncable::PARENT_ID))
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::VisiblePropertiesDiffer(
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncable::EntryKernelMutation& mutation,
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cryptographer* cryptographer) const {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::EntryKernel& a = mutation.original;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::EntryKernel& b = mutation.mutated;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sync_pb::EntitySpecifics& a_specifics = a.ref(SPECIFICS);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sync_pb::EntitySpecifics& b_specifics = b.ref(SPECIFICS);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(GetModelTypeFromSpecifics(a_specifics),
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            GetModelTypeFromSpecifics(b_specifics));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelType model_type = GetModelTypeFromSpecifics(b_specifics);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Suppress updates to items that aren't tracked by any browser model.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (model_type < FIRST_REAL_MODEL_TYPE ||
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !a.ref(syncable::UNIQUE_SERVER_TAG).empty()) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (a.ref(syncable::IS_DIR) != b.ref(syncable::IS_DIR))
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!AreSpecificsEqual(cryptographer,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         a.ref(syncable::SPECIFICS),
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         b.ref(syncable::SPECIFICS))) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only care if the name has changed if neither specifics is encrypted
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (encrypted nodes blow away the NON_UNIQUE_NAME).
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!a_specifics.has_encrypted() && !b_specifics.has_encrypted() &&
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      a.ref(syncable::NON_UNIQUE_NAME) != b.ref(syncable::NON_UNIQUE_NAME))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (VisiblePositionsDiffer(mutation))
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelTypeSet SyncManagerImpl::InitialSyncEndedTypes() {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return directory()->InitialSyncEndedTypes();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelTypeSet SyncManagerImpl::GetTypesWithEmptyProgressMarkerToken(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelTypeSet types) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelTypeSet result;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ModelTypeSet::Iterator i = types.First(); i.Good(); i.Inc()) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_pb::DataTypeProgressMarker marker;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    directory()->GetDownloadProgress(i.Get(), &marker);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (marker.token().empty())
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.Put(i.Get());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::ConfigureSyncer(
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ConfigureReason reason,
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ModelTypeSet to_download,
261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ModelTypeSet to_purge,
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ModelTypeSet to_journal,
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ModelTypeSet to_unapply,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModelSafeRoutingInfo& new_routing_info,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& ready_task,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Closure& retry_task) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ready_task.is_null());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!retry_task.is_null());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DVLOG(1) << "Configuring -"
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << "\n\t" << "current types: "
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << ModelTypeSetToString(GetRoutingInfoTypes(new_routing_info))
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << "\n\t" << "types to download: "
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << ModelTypeSetToString(to_download)
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << "\n\t" << "types to purge: "
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << ModelTypeSetToString(to_purge)
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << "\n\t" << "types to journal: "
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           << ModelTypeSetToString(to_journal)
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << "\n\t" << "types to unapply: "
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch           << ModelTypeSetToString(to_unapply);
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!PurgeDisabledTypes(to_purge,
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          to_journal,
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          to_unapply)) {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We failed to cleanup the types. Invoke the ready task without actually
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // configuring any types. The caller should detect this as a configuration
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // failure and act appropriately.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ready_task.Run();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigurationParams params(GetSourceFromReason(reason),
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             to_download,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             new_routing_info,
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             ready_task,
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                             retry_task);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->Start(SyncScheduler::CONFIGURATION_MODE);
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scheduler_->ScheduleConfiguration(params);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::Init(
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& database_location,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WeakHandle<JsEventHandler>& event_handler,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sync_server_and_path,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool use_ssl,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpPostProviderFactory> post_factory,
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ExtensionsActivity* extensions_activity,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SyncManager::ChangeDelegate* change_delegate,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncCredentials& credentials,
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& invalidator_client_id,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& restored_key_for_bootstrapping,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& restored_keystore_key_for_bootstrapping,
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    InternalComponentsFactory* internal_components_factory,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Encryptor* encryptor,
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    scoped_ptr<UnrecoverableErrorHandler> unrecoverable_error_handler,
3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ReportUnrecoverableErrorFunction report_unrecoverable_error_function,
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    CancelationSignal* cancelation_signal) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!initialized_);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(post_factory.get());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!credentials.email.empty());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!credentials.sync_token.empty());
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(cancelation_signal);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "SyncManager starting Init...";
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_handle_this_ = MakeWeakHandle(weak_ptr_factory_.GetWeakPtr());
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_delegate_ = change_delegate;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddObserver(&js_sync_manager_observer_);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetJsEventHandler(event_handler);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddObserver(&debug_info_event_listener_);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  database_path_ = database_location.Append(
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncable::Directory::kSyncDatabaseFilename);
340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  unrecoverable_error_handler_ = unrecoverable_error_handler.Pass();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  report_unrecoverable_error_function_ = report_unrecoverable_error_function;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetHasKeystoreKey(
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !restored_keystore_key_for_bootstrapping.empty());
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_encryption_handler_.reset(new SyncEncryptionHandlerImpl(
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &share_,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      encryptor,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restored_key_for_bootstrapping,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      restored_keystore_key_for_bootstrapping));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_encryption_handler_->AddObserver(this);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_encryption_handler_->AddObserver(&debug_info_event_listener_);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_encryption_handler_->AddObserver(&js_sync_encryption_handler_observer_);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath absolute_db_path = database_path_;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(absolute_db_path.IsAbsolute());
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<syncable::DirectoryBackingStore> backing_store =
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      internal_components_factory->BuildDirectoryBackingStore(
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          credentials.email, absolute_db_path).Pass();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(backing_store.get());
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& username = credentials.email;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  share_.directory.reset(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new syncable::Directory(
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          backing_store.release(),
366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          unrecoverable_error_handler_.get(),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          report_unrecoverable_error_function_,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sync_encryption_handler_.get(),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sync_encryption_handler_->GetCryptographerUnsafe()));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Username: " << username;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!OpenDirectory(username)) {
3731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    NotifyInitializationFailure();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Sync manager initialization failed!";
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_manager_.reset(new SyncAPIServerConnectionManager(
3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      sync_server_and_path, port, use_ssl,
380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      post_factory.release(), cancelation_signal));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_manager_->set_client_id(directory()->cache_guid());
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_manager_->AddListener(this);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string sync_id = directory()->cache_guid();
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "Setting sync client ID: " << sync_id;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  allstatus_.SetSyncId(sync_id);
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "Setting invalidator client ID: " << invalidator_client_id;
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  allstatus_.SetInvalidatorClientId(invalidator_client_id);
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_type_registry_.reset(new ModelTypeRegistry(workers, directory()));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  sync_core_.reset(new SyncCore(model_type_registry_.get()));
394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
395a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Bind the SyncCore WeakPtr to this thread.  This helps us crash earlier if
396a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // the pointer is misused in debug mode.
397a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::WeakPtr<SyncCore> weak_core = sync_core_->AsWeakPtr();
398a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  weak_core.get();
399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  sync_core_proxy_.reset(
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      new SyncCoreProxyImpl(base::MessageLoopProxy::current(), weak_core));
402a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build a SyncSessionContext and store the worker in it.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Sync is bringing up SyncSessionContext.";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<SyncEngineEventListener*> listeners;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners.push_back(&allstatus_);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  listeners.push_back(this);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_context_ = internal_components_factory->BuildContext(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_manager_.get(),
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      directory(),
411a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      extensions_activity,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      listeners,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &debug_info_event_listener_,
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      model_type_registry_.get(),
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      invalidator_client_id).Pass();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_context_->set_account_name(credentials.email);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_ = internal_components_factory->BuildScheduler(
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      name_, session_context_.get(), cancelation_signal).Pass();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->Start(SyncScheduler::CONFIGURATION_MODE);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized_ = true;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::AddIPAddressObserver(this);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observing_network_connectivity_changes_ = true;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateCredentials(credentials);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NotifyInitializationSuccess();
4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SyncManagerImpl::NotifyInitializationSuccess() {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnInitializationComplete(
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MakeWeakHandle(debug_info_event_listener_.GetWeakPtr()),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        true, InitialSyncEndedTypes()));
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SyncManagerImpl::NotifyInitializationFailure() {
4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    OnInitializationComplete(
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()),
4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        MakeWeakHandle(debug_info_event_listener_.GetWeakPtr()),
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                        false, ModelTypeSet()));
4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnPassphraseRequired(
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PassphraseRequiredReason reason,
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const sync_pb::EncryptedData& pending_keys) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does nothing.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnPassphraseAccepted() {
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does nothing.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnBootstrapTokenUpdated(
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& bootstrap_token,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BootstrapTokenType type) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == KEYSTORE_BOOTSTRAP_TOKEN)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allstatus_.SetHasKeystoreKey(true);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnEncryptedTypesChanged(ModelTypeSet encrypted_types,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bool encrypt_everything) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetEncryptedTypes(encrypted_types);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnEncryptionComplete() {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does nothing.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnCryptographerStateChanged(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cryptographer* cryptographer) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetCryptographerReady(cryptographer->is_ready());
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys());
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetKeystoreMigrationTime(
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_encryption_handler_->migration_time());
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnPassphraseTypeChanged(
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PassphraseType type,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time explicit_passphrase_time) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetPassphraseType(type);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetKeystoreMigrationTime(
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_encryption_handler_->migration_time());
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::StartSyncingNormally(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModelSafeRoutingInfo& routing_info) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the sync scheduler.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sync): We always want the newest set of routes when we switch back
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to normal mode. Figure out how to enforce set_routing_info is always
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // appropriately set and that it's only modified when switching to normal
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mode.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  session_context_->SetRoutingInfo(routing_info);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->Start(SyncScheduler::NORMAL_MODE);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncable::Directory* SyncManagerImpl::directory() {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return share_.directory.get();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SyncScheduler* SyncManagerImpl::scheduler() const {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scheduler_.get();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncManagerImpl::GetHasInvalidAuthTokenForTest() const {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return connection_manager_->HasInvalidAuthToken();
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SyncManagerImpl::OpenDirectory(const std::string& username) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!initialized_) << "Should only happen once";
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set before Open().
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_observer_ = MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WeakHandle<syncable::TransactionObserver> transaction_observer(
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr()));
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncable::DirOpenResult open_result = syncable::NOT_INITIALIZED;
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  open_result = directory()->Open(username, this, transaction_observer);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (open_result != syncable::OPENED) {
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Could not open share for:" << username;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unapplied datatypes (those that do not have initial sync ended set) get
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-downloaded during any configuration. But, it's possible for a datatype
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to have a progress marker but not have initial sync ended yet, making
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it a candidate for migration. This is a problem, as the DataTypeManager
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // does not support a migration while it's already in the middle of a
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // configuration. As a result, any partially synced datatype can stall the
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DTM, waiting for the configuration to complete, which it never will due
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the migration error. In addition, a partially synced nigori will
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // trigger the migration logic before the backend is initialized, resulting
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in crashes. We therefore detect and purge any partially synced types as
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // part of initialization.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PurgePartiallySyncedTypes())
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::PurgePartiallySyncedTypes() {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelTypeSet partially_synced_types = ModelTypeSet::All();
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partially_synced_types.RemoveAll(InitialSyncEndedTypes());
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  partially_synced_types.RemoveAll(GetTypesWithEmptyProgressMarkerToken(
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ModelTypeSet::All()));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Purging partially synced types "
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           << ModelTypeSetToString(partially_synced_types);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes",
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       partially_synced_types.Size());
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (partially_synced_types.Empty())
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return directory()->PurgeEntriesWithTypeIn(partially_synced_types,
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                             ModelTypeSet(),
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             ModelTypeSet());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::PurgeDisabledTypes(
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ModelTypeSet to_purge,
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ModelTypeSet to_journal,
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ModelTypeSet to_unapply) {
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (to_purge.Empty())
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DVLOG(1) << "Purging disabled types " << ModelTypeSetToString(to_purge);
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(to_purge.HasAll(to_journal));
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(to_purge.HasAll(to_unapply));
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return directory()->PurgeEntriesWithTypeIn(to_purge, to_journal, to_unapply);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncManagerImpl::UpdateCredentials(const SyncCredentials& credentials) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!credentials.email.empty());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!credentials.sync_token.empty());
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observing_network_connectivity_changes_ = true;
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!connection_manager_->SetAuthToken(credentials.sync_token))
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Auth token is known to be invalid, so exit early.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->OnCredentialsUpdated();
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(zea): pass the credential age to the debug info event listener.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::ShutdownOnSyncThread() {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prevent any in-flight method calls from running.  Also
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidates |weak_handle_this_| and |change_observer_|.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  js_mutation_event_observer_.InvalidateWeakPtrs();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_.reset();
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  session_context_.reset();
6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  model_type_registry_.reset();
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (sync_encryption_handler_) {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_encryption_handler_->RemoveObserver(this);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetJsEventHandler(WeakHandle<JsEventHandler>());
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveObserver(&js_sync_manager_observer_);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveObserver(&debug_info_event_listener_);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // |connection_manager_| may end up being NULL here in tests (in synchronous
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // initialization mode).
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Fix this behavior.
627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (connection_manager_)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_manager_->RemoveListener(this);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_manager_.reset();
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observing_network_connectivity_changes_ = false;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (initialized_ && directory()) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    directory()->SaveChanges();
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  share_.directory.reset();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_delegate_ = NULL;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initialized_ = false;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We reset these here, since only now we know they will not be
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // accessed from other threads (since we shut down everything).
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_observer_.Reset();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_handle_this_.Reset();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnIPAddressChanged() {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!observing_network_connectivity_changes_) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "IP address change dropped.";
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "IP address change detected.";
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnNetworkConnectivityChangedImpl();
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnConnectionTypeChanged(
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::NetworkChangeNotifier::ConnectionType) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!observing_network_connectivity_changes_) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Connection type change dropped.";
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Connection type change detected.";
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnNetworkConnectivityChangedImpl();
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnNetworkConnectivityChangedImpl() {
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->OnConnectionStatusChange();
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnServerConnectionEvent(
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ServerConnectionEvent& event) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.connection_code ==
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpResponse::SERVER_CONNECTION_OK) {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OnConnectionStatusChange(CONNECTION_OK));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.connection_code == HttpResponse::SYNC_AUTH_ERROR) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observing_network_connectivity_changes_ = false;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OnConnectionStatusChange(CONNECTION_AUTH_ERROR));
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event.connection_code == HttpResponse::SYNC_SERVER_ERROR) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OnConnectionStatusChange(CONNECTION_SERVER_ERROR));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::HandleTransactionCompleteChangeEvent(
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelTypeSet models_with_changes) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This notification happens immediately after the transaction mutex is
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // released. This allows work to be performed without blocking other threads
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from acquiring a transaction.
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!change_delegate_)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call commit.
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ModelTypeSet::Iterator it = models_with_changes.First();
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it.Good(); it.Inc()) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_delegate_->OnChangesComplete(it.Get());
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_observer_.Call(
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &SyncManager::ChangeObserver::OnChangesComplete,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        it.Get());
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelTypeSet
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncManagerImpl::HandleTransactionEndingChangeEvent(
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ImmutableWriteTransactionInfo& write_transaction_info,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncable::BaseTransaction* trans) {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This notification happens immediately before a syncable WriteTransaction
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // falls out of scope. It happens while the channel mutex is still held,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and while the transaction mutex is held, so it cannot be re-entrant.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!change_delegate_ || change_records_.empty())
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ModelTypeSet();
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will continue the WriteTransaction using a read only wrapper.
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the last chance for read to occur in the WriteTransaction
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that's closing. This special ReadTransaction will not close the
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // underlying transaction.
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTransaction read_trans(GetUserShare(), trans);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelTypeSet models_with_changes;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ChangeRecordMap::const_iterator it = change_records_.begin();
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != change_records_.end(); ++it) {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!it->second.Get().empty());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelType type = ModelTypeFromInt(it->first);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_delegate_->
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnChangesApplied(type, trans->directory()->GetTransactionVersion(type),
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &read_trans, it->second);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_observer_.Call(FROM_HERE,
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &SyncManager::ChangeObserver::OnChangesApplied,
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type, write_transaction_info.Get().id, it->second);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    models_with_changes.Put(type);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_records_.clear();
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return models_with_changes;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::HandleCalculateChangesChangeEventFromSyncApi(
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ImmutableWriteTransactionInfo& write_transaction_info,
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncable::BaseTransaction* trans,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<int64>* entries_changed) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have been notified about a user action changing a sync model.
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, !change_records_.empty()) <<
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "CALCULATE_CHANGES called with unapplied old changes.";
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The mutated model type, or UNSPECIFIED if nothing was mutated.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelTypeSet mutated_model_types;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::ImmutableEntryKernelMutationMap& mutations =
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_transaction_info.Get().mutations;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncable::EntryKernelMutationMap::const_iterator it =
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           mutations.Get().begin(); it != mutations.Get().end(); ++it) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!it->second.mutated.ref(syncable::IS_UNSYNCED)) {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelType model_type =
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetModelTypeFromSpecifics(it->second.mutated.ref(SPECIFICS));
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (model_type < FIRST_REAL_MODEL_TYPE) {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Permanent or underspecified item changed via syncapi.";
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Found real mutation.
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (model_type != UNSPECIFIED) {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mutated_model_types.Put(model_type);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries_changed->push_back(it->second.mutated.ref(syncable::META_HANDLE));
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nudge if necessary.
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mutated_model_types.Empty()) {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (weak_handle_this_.IsInitialized()) {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_handle_this_.Call(FROM_HERE,
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &SyncManagerImpl::RequestNudgeForDataTypes,
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             FROM_HERE,
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             mutated_model_types);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::SetExtraChangeRecordData(int64 id,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelType type, ChangeReorderBuffer* buffer,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cryptographer* cryptographer, const syncable::EntryKernel& original,
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool existed_before, bool exists_now) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is a deletion and the datatype was encrypted, we need to decrypt it
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and attach it to the buffer.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!exists_now && existed_before) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS));
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type == PASSWORDS) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Passwords must use their own legacy ExtraPasswordChangeRecordData.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<sync_pb::PasswordSpecificsData> data(
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DecryptPasswordSpecifics(original_specifics, cryptographer));
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!data) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (original_specifics.has_encrypted()) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // All other datatypes can just create a new unencrypted specifics and
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // attach it.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const sync_pb::EncryptedData& encrypted = original_specifics.encrypted();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!cryptographer->Decrypt(encrypted, &original_specifics)) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer->SetSpecificsForId(id, original_specifics);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::HandleCalculateChangesChangeEventFromSyncer(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ImmutableWriteTransactionInfo& write_transaction_info,
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncable::BaseTransaction* trans,
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<int64>* entries_changed) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only expect one notification per sync step, so change_buffers_ should
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contain no pending entries.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, !change_records_.empty()) <<
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "CALCULATE_CHANGES called with unapplied old changes.";
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeReorderBuffer change_buffers[MODEL_TYPE_COUNT];
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cryptographer* crypto = directory()->GetCryptographer(trans);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncable::ImmutableEntryKernelMutationMap& mutations =
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_transaction_info.Get().mutations;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncable::EntryKernelMutationMap::const_iterator it =
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           mutations.Get().begin(); it != mutations.Get().end(); ++it) {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool existed_before = !it->second.original.ref(syncable::IS_DEL);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool exists_now = !it->second.mutated.ref(syncable::IS_DEL);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Omit items that aren't associated with a model.
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelType type =
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetModelTypeFromSpecifics(it->second.mutated.ref(SPECIFICS));
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type < FIRST_REAL_MODEL_TYPE)
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 handle = it->first;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (exists_now && !existed_before)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      change_buffers[type].PushAddedItem(handle);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (!exists_now && existed_before)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      change_buffers[type].PushDeletedItem(handle);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (exists_now && existed_before &&
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             VisiblePropertiesDiffer(it->second, crypto)) {
8567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      change_buffers[type].PushUpdatedItem(handle);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetExtraChangeRecordData(handle, type, &change_buffers[type], crypto,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             it->second.original, existed_before, exists_now);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTransaction read_trans(GetUserShare(), trans);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!change_buffers[i].IsEmpty()) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (change_buffers[i].GetAllChangesInTreeOrder(&read_trans,
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &(change_records_[i]))) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (size_t j = 0; j < change_records_[i].Get().size(); ++j)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          entries_changed->push_back((change_records_[i].Get())[j].id);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (change_records_[i].Get().empty())
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        change_records_.erase(i);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta SyncManagerImpl::GetNudgeDelayTimeDelta(
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ModelType& model_type) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NudgeStrategy::GetNudgeDelayTimeDelta(model_type, this);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::RequestNudgeForDataTypes(
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& nudge_location,
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ModelTypeSet types) {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  debug_info_event_listener_.OnNudgeFromDatatype(types.First().Get());
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(lipalani) : Calculate the nudge delay based on all types.
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeDelta nudge_delay = NudgeStrategy::GetNudgeDelayTimeDelta(
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      types.First().Get(),
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
891b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scheduler_->ScheduleLocalNudge(nudge_delay,
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 types,
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 nudge_location);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncManagerImpl::OnSyncCycleEvent(const SyncCycleEvent& event) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only send an event if this is due to a cycle ending and this cycle
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // concludes a canonical "sync" process; that is, based on what is known
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // locally we are "all happy" and up-to-date.  There may be new changes on
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the server, but we'll get them on a subsequent sync.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifications are sent at the end of every sync cycle, regardless of
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whether we should sync again.
9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!initialized_) {
907f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DVLOG(1) << "OnSyncCycleCompleted not sent because sync api is not "
908f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)               << "initialized";
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Sending OnSyncCycleCompleted";
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      OnSyncCycleCompleted(event.snapshot));
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncManagerImpl::OnActionableError(const SyncProtocolError& error) {
9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(
9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SyncManager::Observer, observers_,
9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      OnActionableError(error));
9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncManagerImpl::OnRetryTimeChanged(base::Time) {}
9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncManagerImpl::OnThrottledTypesChanged(ModelTypeSet) {}
9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SyncManagerImpl::OnMigrationRequested(ModelTypeSet types) {
9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FOR_EACH_OBSERVER(
9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SyncManager::Observer, observers_,
9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      OnMigrationRequested(types));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
934effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid SyncManagerImpl::OnProtocolEvent(const ProtocolEvent& event) {
935e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  protocol_event_buffer_.RecordProtocolEvent(event);
936effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
937effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                    OnProtocolEvent(event));
938effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
939effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::SetJsEventHandler(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WeakHandle<JsEventHandler>& event_handler) {
942a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  js_sync_manager_observer_.SetJsEventHandler(event_handler);
943a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  js_mutation_event_observer_.SetJsEventHandler(event_handler);
944a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  js_sync_encryption_handler_observer_.SetJsEventHandler(event_handler);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
947c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_ptr<base::ListValue> SyncManagerImpl::GetAllNodesForType(
948c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    syncer::ModelType type) {
949c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DirectoryTypeDebugInfoEmitterMap* emitter_map =
950c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      model_type_registry_->directory_type_debug_info_emitter_map();
951c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DirectoryTypeDebugInfoEmitterMap::iterator it = emitter_map->find(type);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
953c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (it == emitter_map->end()) {
9545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // This can happen in some cases.  The UI thread makes requests of us
9555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // when it doesn't really know which types are enabled or disabled.
9565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    DLOG(WARNING) << "Asked to return debug info for invalid type "
9575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                  << ModelTypeToString(type);
958c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return scoped_ptr<base::ListValue>();
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
961c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return it->second->GetAllNodes();
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnInvalidatorStateChange(InvalidatorState state) {
965eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(thread_checker_.CalledOnValidThread());
966eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& state_str = InvalidatorStateToString(state);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  invalidator_state_ = state;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Invalidator state changed to: " << state_str;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool notifications_enabled =
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (invalidator_state_ == INVALIDATIONS_ENABLED);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  allstatus_.SetNotificationsEnabled(notifications_enabled);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scheduler_->SetNotificationsEnabled(notifications_enabled);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::OnIncomingInvalidation(
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ObjectIdInvalidationMap& invalidation_map) {
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // We should never receive IDs from non-sync objects.
9814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ObjectIdSet ids = invalidation_map.GetObjectIds();
98258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
98358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ModelType type;
98458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!ObjectIdToRealModelType(*it, &type)) {
98558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      DLOG(WARNING) << "Notification has invalid id: " << ObjectIdToString(*it);
98658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
98758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
98858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (invalidation_map.Empty()) {
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Sync received invalidation without any type information.";
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
992b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scheduler_->ScheduleInvalidationNudge(
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec),
99458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        invalidation_map, FROM_HERE);
99558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    debug_info_event_listener_.OnIncomingNotification(invalidation_map);
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
999a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string SyncManagerImpl::GetOwnerName() const { return "SyncManagerImpl"; }
1000a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyncManagerImpl::RefreshTypes(ModelTypeSet types) {
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1003b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (types.Empty()) {
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Sync received refresh request with no types specified.";
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1006b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scheduler_->ScheduleLocalRefreshRequest(
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec),
1008b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        types, FROM_HERE);
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncStatus SyncManagerImpl::GetDetailedStatus() const {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return allstatus_.status();
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncManagerImpl::SaveChanges() {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  directory()->SaveChanges();
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UserShare* SyncManagerImpl::GetUserShare() {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(initialized_);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &share_;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochsyncer::SyncCoreProxy* SyncManagerImpl::GetSyncCoreProxy() {
1026effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(initialized_);
1027a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return sync_core_proxy_.get();
1028effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1029effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
10302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::string SyncManagerImpl::cache_guid() {
10312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(initialized_);
10322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return directory()->cache_guid();
10332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::ReceivedExperiment(Experiments* experiments) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTransaction trans(FROM_HERE, GetUserShare());
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadNode nigori_node(&trans);
103846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Couldn't find Nigori node.";
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found_experiment = false;
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReadNode favicon_sync_node(&trans);
10452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (favicon_sync_node.InitByClientTagLookup(
10462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          syncer::EXPERIMENTS,
1047c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          syncer::kFaviconSyncTag) == BaseNode::INIT_OK) {
1048c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    experiments->favicon_sync_limit =
1049c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        favicon_sync_node.GetExperimentsSpecifics().favicon_sync().
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            favicon_sync_limit();
10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    found_experiment = true;
10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1054ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ReadNode pre_commit_update_avoidance_node(&trans);
1055ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (pre_commit_update_avoidance_node.InitByClientTagLookup(
1056ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          syncer::EXPERIMENTS,
1057ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          syncer::kPreCommitUpdateAvoidanceTag) == BaseNode::INIT_OK) {
1058ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    session_context_->set_server_enabled_pre_commit_update_avoidance(
1059ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        pre_commit_update_avoidance_node.GetExperimentsSpecifics().
1060ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch            pre_commit_update_avoidance().enabled());
1061ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // We don't bother setting found_experiment.  The frontend doesn't need to
1062ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // know about this.
1063ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1064ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReadNode gcm_channel_node(&trans);
10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (gcm_channel_node.InitByClientTagLookup(
10675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::EXPERIMENTS,
10685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::kGCMChannelTag) == BaseNode::INIT_OK &&
10695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      gcm_channel_node.GetExperimentsSpecifics().gcm_channel().has_enabled()) {
10705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    experiments->gcm_channel_state =
10715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (gcm_channel_node.GetExperimentsSpecifics().gcm_channel().enabled() ?
10725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         syncer::Experiments::ENABLED : syncer::Experiments::SUPPRESSED);
10735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    found_experiment = true;
10745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ReadNode enhanced_bookmarks_node(&trans);
10775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (enhanced_bookmarks_node.InitByClientTagLookup(
10785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          syncer::EXPERIMENTS, syncer::kEnhancedBookmarksTag) ==
10795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          BaseNode::INIT_OK &&
10805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enhanced_bookmarks_node.GetExperimentsSpecifics()
10815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          .has_enhanced_bookmarks()) {
10825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const sync_pb::EnhancedBookmarksFlags& enhanced_bookmarks =
10835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        enhanced_bookmarks_node.GetExperimentsSpecifics().enhanced_bookmarks();
10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (enhanced_bookmarks.has_enabled())
10855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      experiments->enhanced_bookmarks_enabled = enhanced_bookmarks.enabled();
10865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (enhanced_bookmarks.has_extension_id()) {
10875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      experiments->enhanced_bookmarks_ext_id =
10885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          enhanced_bookmarks.extension_id();
10895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
10905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    found_experiment = true;
10915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1093effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ReadNode gcm_invalidations_node(&trans);
1094effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (gcm_invalidations_node.InitByClientTagLookup(
1095effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          syncer::EXPERIMENTS, syncer::kGCMInvalidationsTag) ==
1096effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      BaseNode::INIT_OK) {
1097effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const sync_pb::GcmInvalidationsFlags& gcm_invalidations =
1098effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        gcm_invalidations_node.GetExperimentsSpecifics().gcm_invalidations();
1099effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    if (gcm_invalidations.has_enabled()) {
1100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      experiments->gcm_invalidations_enabled = gcm_invalidations.enabled();
1101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      found_experiment = true;
1102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
1103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
1104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found_experiment;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncManagerImpl::HasUnsyncedItems() {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadTransaction trans(FROM_HERE, GetUserShare());
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sync_encryption_handler_.get();
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochScopedVector<syncer::ProtocolEvent>
1118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    SyncManagerImpl::GetBufferedProtocolEvents() {
1119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return protocol_event_buffer_.GetBufferedProtocolEvents();
1120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
1121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
1122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncManagerImpl::RegisterDirectoryTypeDebugInfoObserver(
1123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    syncer::TypeDebugInfoObserver* observer) {
1124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  model_type_registry_->RegisterDirectoryTypeDebugInfoObserver(observer);
1125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncManagerImpl::UnregisterDirectoryTypeDebugInfoObserver(
1128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    syncer::TypeDebugInfoObserver* observer) {
1129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  model_type_registry_->UnregisterDirectoryTypeDebugInfoObserver(observer);
1130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool SyncManagerImpl::HasDirectoryTypeDebugInfoObserver(
1133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    syncer::TypeDebugInfoObserver* observer) {
1134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return model_type_registry_->HasDirectoryTypeDebugInfoObserver(observer);
1135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void SyncManagerImpl::RequestEmitDebugInfo() {
1138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  model_type_registry_->RequestEmitDebugInfo();
1139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
1140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static.
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SyncManagerImpl::GetDefaultNudgeDelay() {
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kDefaultNudgeDelayMilliseconds;
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static.
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SyncManagerImpl::GetPreferencesNudgeDelay() {
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kPreferencesNudgeDelayMilliseconds;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncer
1152