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

Unified Diff: sync/internal_api/sync_manager_impl.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sync/internal_api/sync_manager_impl.h ('k') | sync/internal_api/sync_manager_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sync/internal_api/sync_manager_impl.cc
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc
deleted file mode 100644
index cc59e645b06d03c999a4206cb3ea9d19bb22156a..0000000000000000000000000000000000000000
--- a/sync/internal_api/sync_manager_impl.cc
+++ /dev/null
@@ -1,1037 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sync/internal_api/sync_manager_impl.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string>
-#include <utility>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram.h"
-#include "base/observer_list.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/values.h"
-#include "sync/engine/sync_scheduler.h"
-#include "sync/engine/syncer_types.h"
-#include "sync/internal_api/change_reorder_buffer.h"
-#include "sync/internal_api/model_type_connector_proxy.h"
-#include "sync/internal_api/public/base/cancelation_signal.h"
-#include "sync/internal_api/public/base/invalidation_interface.h"
-#include "sync/internal_api/public/base/model_type.h"
-#include "sync/internal_api/public/base_node.h"
-#include "sync/internal_api/public/configure_reason.h"
-#include "sync/internal_api/public/engine/polling_constants.h"
-#include "sync/internal_api/public/http_post_provider_factory.h"
-#include "sync/internal_api/public/internal_components_factory.h"
-#include "sync/internal_api/public/read_node.h"
-#include "sync/internal_api/public/read_transaction.h"
-#include "sync/internal_api/public/user_share.h"
-#include "sync/internal_api/public/util/experiments.h"
-#include "sync/internal_api/public/write_node.h"
-#include "sync/internal_api/public/write_transaction.h"
-#include "sync/internal_api/syncapi_internal.h"
-#include "sync/internal_api/syncapi_server_connection_manager.h"
-#include "sync/protocol/proto_value_conversions.h"
-#include "sync/protocol/sync.pb.h"
-#include "sync/sessions/directory_type_debug_info_emitter.h"
-#include "sync/syncable/directory.h"
-#include "sync/syncable/entry.h"
-#include "sync/syncable/in_memory_directory_backing_store.h"
-#include "sync/syncable/on_disk_directory_backing_store.h"
-
-using base::TimeDelta;
-using sync_pb::GetUpdatesCallerInfo;
-
-class GURL;
-
-namespace syncer {
-
-using sessions::SyncSessionContext;
-using syncable::ImmutableWriteTransactionInfo;
-using syncable::SPECIFICS;
-using syncable::UNIQUE_POSITION;
-
-namespace {
-
-GetUpdatesCallerInfo::GetUpdatesSource GetSourceFromReason(
- ConfigureReason reason) {
- switch (reason) {
- case CONFIGURE_REASON_RECONFIGURATION:
- return GetUpdatesCallerInfo::RECONFIGURATION;
- case CONFIGURE_REASON_MIGRATION:
- return GetUpdatesCallerInfo::MIGRATION;
- case CONFIGURE_REASON_NEW_CLIENT:
- return GetUpdatesCallerInfo::NEW_CLIENT;
- case CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE:
- case CONFIGURE_REASON_CRYPTO:
- case CONFIGURE_REASON_CATCH_UP:
- return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE;
- case CONFIGURE_REASON_PROGRAMMATIC:
- return GetUpdatesCallerInfo::PROGRAMMATIC;
- case CONFIGURE_REASON_UNKNOWN:
- NOTREACHED();
- }
- return GetUpdatesCallerInfo::UNKNOWN;
-}
-
-} // namespace
-
-SyncManagerImpl::SyncManagerImpl(const std::string& name)
- : name_(name),
- change_delegate_(NULL),
- initialized_(false),
- observing_network_connectivity_changes_(false),
- weak_ptr_factory_(this) {
- // Pre-fill |notification_info_map_|.
- for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
- notification_info_map_.insert(
- std::make_pair(ModelTypeFromInt(i), NotificationInfo()));
- }
-}
-
-SyncManagerImpl::~SyncManagerImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
- CHECK(!initialized_);
-}
-
-SyncManagerImpl::NotificationInfo::NotificationInfo() : total_count(0) {}
-SyncManagerImpl::NotificationInfo::~NotificationInfo() {}
-
-base::DictionaryValue* SyncManagerImpl::NotificationInfo::ToValue() const {
- base::DictionaryValue* value = new base::DictionaryValue();
- value->SetInteger("totalCount", total_count);
- value->SetString("payload", payload);
- return value;
-}
-
-bool SyncManagerImpl::VisiblePositionsDiffer(
- const syncable::EntryKernelMutation& mutation) const {
- const syncable::EntryKernel& a = mutation.original;
- const syncable::EntryKernel& b = mutation.mutated;
- if (!b.ShouldMaintainPosition())
- return false;
- if (!a.ref(UNIQUE_POSITION).Equals(b.ref(UNIQUE_POSITION)))
- return true;
- if (a.ref(syncable::PARENT_ID) != b.ref(syncable::PARENT_ID))
- return true;
- return false;
-}
-
-bool SyncManagerImpl::VisiblePropertiesDiffer(
- const syncable::EntryKernelMutation& mutation,
- Cryptographer* cryptographer) const {
- const syncable::EntryKernel& a = mutation.original;
- const syncable::EntryKernel& b = mutation.mutated;
- const sync_pb::EntitySpecifics& a_specifics = a.ref(SPECIFICS);
- const sync_pb::EntitySpecifics& b_specifics = b.ref(SPECIFICS);
- DCHECK_EQ(GetModelTypeFromSpecifics(a_specifics),
- GetModelTypeFromSpecifics(b_specifics));
- ModelType model_type = GetModelTypeFromSpecifics(b_specifics);
- // Suppress updates to items that aren't tracked by any browser model.
- if (model_type < FIRST_REAL_MODEL_TYPE ||
- !a.ref(syncable::UNIQUE_SERVER_TAG).empty()) {
- return false;
- }
- if (a.ref(syncable::IS_DIR) != b.ref(syncable::IS_DIR))
- return true;
- if (!AreSpecificsEqual(cryptographer,
- a.ref(syncable::SPECIFICS),
- b.ref(syncable::SPECIFICS))) {
- return true;
- }
- if (!AreAttachmentMetadataEqual(a.ref(syncable::ATTACHMENT_METADATA),
- b.ref(syncable::ATTACHMENT_METADATA))) {
- return true;
- }
- // We only care if the name has changed if neither specifics is encrypted
- // (encrypted nodes blow away the NON_UNIQUE_NAME).
- if (!a_specifics.has_encrypted() && !b_specifics.has_encrypted() &&
- a.ref(syncable::NON_UNIQUE_NAME) != b.ref(syncable::NON_UNIQUE_NAME))
- return true;
- if (VisiblePositionsDiffer(mutation))
- return true;
- return false;
-}
-
-ModelTypeSet SyncManagerImpl::InitialSyncEndedTypes() {
- DCHECK(initialized_);
- return model_type_registry_->GetInitialSyncEndedTypes();
-}
-
-ModelTypeSet SyncManagerImpl::GetTypesWithEmptyProgressMarkerToken(
- ModelTypeSet types) {
- ModelTypeSet result;
- for (ModelTypeSet::Iterator i = types.First(); i.Good(); i.Inc()) {
- sync_pb::DataTypeProgressMarker marker;
- directory()->GetDownloadProgress(i.Get(), &marker);
-
- if (marker.token().empty())
- result.Put(i.Get());
- }
- return result;
-}
-
-void SyncManagerImpl::ConfigureSyncer(
- ConfigureReason reason,
- ModelTypeSet to_download,
- ModelTypeSet to_purge,
- ModelTypeSet to_journal,
- ModelTypeSet to_unapply,
- const ModelSafeRoutingInfo& new_routing_info,
- const base::Closure& ready_task,
- const base::Closure& retry_task) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!ready_task.is_null());
- DCHECK(initialized_);
-
- DVLOG(1) << "Configuring -"
- << "\n\t" << "current types: "
- << ModelTypeSetToString(GetRoutingInfoTypes(new_routing_info))
- << "\n\t" << "types to download: "
- << ModelTypeSetToString(to_download)
- << "\n\t" << "types to purge: "
- << ModelTypeSetToString(to_purge)
- << "\n\t" << "types to journal: "
- << ModelTypeSetToString(to_journal)
- << "\n\t" << "types to unapply: "
- << ModelTypeSetToString(to_unapply);
- if (!PurgeDisabledTypes(to_purge,
- to_journal,
- to_unapply)) {
- // We failed to cleanup the types. Invoke the ready task without actually
- // configuring any types. The caller should detect this as a configuration
- // failure and act appropriately.
- ready_task.Run();
- return;
- }
-
- ConfigurationParams params(GetSourceFromReason(reason),
- to_download,
- new_routing_info,
- ready_task,
- retry_task);
-
- scheduler_->Start(SyncScheduler::CONFIGURATION_MODE, base::Time());
- scheduler_->ScheduleConfiguration(params);
-}
-
-void SyncManagerImpl::Init(InitArgs* args) {
- CHECK(!initialized_);
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(args->post_factory.get());
- DCHECK(!args->credentials.account_id.empty());
- DCHECK(!args->credentials.sync_token.empty());
- DCHECK(!args->credentials.scope_set.empty());
- DCHECK(args->cancelation_signal);
- DVLOG(1) << "SyncManager starting Init...";
-
- weak_handle_this_ = MakeWeakHandle(weak_ptr_factory_.GetWeakPtr());
-
- change_delegate_ = args->change_delegate;
-
- AddObserver(&js_sync_manager_observer_);
- SetJsEventHandler(args->event_handler);
-
- AddObserver(&debug_info_event_listener_);
-
- database_path_ = args->database_location.Append(
- syncable::Directory::kSyncDatabaseFilename);
- report_unrecoverable_error_function_ =
- args->report_unrecoverable_error_function;
-
- allstatus_.SetHasKeystoreKey(
- !args->restored_keystore_key_for_bootstrapping.empty());
- sync_encryption_handler_.reset(new SyncEncryptionHandlerImpl(
- &share_, args->encryptor, args->restored_key_for_bootstrapping,
- args->restored_keystore_key_for_bootstrapping));
- sync_encryption_handler_->AddObserver(this);
- sync_encryption_handler_->AddObserver(&debug_info_event_listener_);
- sync_encryption_handler_->AddObserver(&js_sync_encryption_handler_observer_);
-
- base::FilePath absolute_db_path = database_path_;
- DCHECK(absolute_db_path.IsAbsolute());
-
- std::unique_ptr<syncable::DirectoryBackingStore> backing_store =
- args->internal_components_factory->BuildDirectoryBackingStore(
- InternalComponentsFactory::STORAGE_ON_DISK,
- args->credentials.account_id, absolute_db_path);
-
- DCHECK(backing_store.get());
- share_.directory.reset(
- new syncable::Directory(
- backing_store.release(),
- args->unrecoverable_error_handler,
- report_unrecoverable_error_function_,
- sync_encryption_handler_.get(),
- sync_encryption_handler_->GetCryptographerUnsafe()));
- share_.sync_credentials = args->credentials;
-
- // UserShare is accessible to a lot of code that doesn't need access to the
- // sync token so clear sync_token from the UserShare.
- share_.sync_credentials.sync_token = "";
-
- DVLOG(1) << "Username: " << args->credentials.email;
- DVLOG(1) << "AccountId: " << args->credentials.account_id;
- if (!OpenDirectory(args->credentials.account_id)) {
- NotifyInitializationFailure();
- LOG(ERROR) << "Sync manager initialization failed!";
- return;
- }
-
- // Now that we have opened the Directory we can restore any previously saved
- // nigori specifics.
- if (args->saved_nigori_state) {
- sync_encryption_handler_->RestoreNigori(*args->saved_nigori_state);
- args->saved_nigori_state.reset();
- }
-
- connection_manager_.reset(new SyncAPIServerConnectionManager(
- args->service_url.host() + args->service_url.path(),
- args->service_url.EffectiveIntPort(),
- args->service_url.SchemeIsCryptographic(), args->post_factory.release(),
- args->cancelation_signal));
- connection_manager_->set_client_id(directory()->cache_guid());
- connection_manager_->AddListener(this);
-
- std::string sync_id = directory()->cache_guid();
-
- DVLOG(1) << "Setting sync client ID: " << sync_id;
- allstatus_.SetSyncId(sync_id);
- DVLOG(1) << "Setting invalidator client ID: " << args->invalidator_client_id;
- allstatus_.SetInvalidatorClientId(args->invalidator_client_id);
-
- model_type_registry_.reset(
- new ModelTypeRegistry(args->workers, directory(), this));
- sync_encryption_handler_->AddObserver(model_type_registry_.get());
-
- // Build a SyncSessionContext and store the worker in it.
- DVLOG(1) << "Sync is bringing up SyncSessionContext.";
- std::vector<SyncEngineEventListener*> listeners;
- listeners.push_back(&allstatus_);
- listeners.push_back(this);
- session_context_ = args->internal_components_factory->BuildContext(
- connection_manager_.get(), directory(), args->extensions_activity,
- listeners, &debug_info_event_listener_, model_type_registry_.get(),
- args->invalidator_client_id);
- scheduler_ = args->internal_components_factory->BuildScheduler(
- name_, session_context_.get(), args->cancelation_signal);
-
- scheduler_->Start(SyncScheduler::CONFIGURATION_MODE, base::Time());
-
- initialized_ = true;
-
- net::NetworkChangeNotifier::AddIPAddressObserver(this);
- net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
- observing_network_connectivity_changes_ = true;
-
- UpdateCredentials(args->credentials);
-
- NotifyInitializationSuccess();
-}
-
-void SyncManagerImpl::NotifyInitializationSuccess() {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnInitializationComplete(
- MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()),
- MakeWeakHandle(debug_info_event_listener_.GetWeakPtr()),
- true, InitialSyncEndedTypes()));
-}
-
-void SyncManagerImpl::NotifyInitializationFailure() {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnInitializationComplete(
- MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()),
- MakeWeakHandle(debug_info_event_listener_.GetWeakPtr()),
- false, ModelTypeSet()));
-}
-
-void SyncManagerImpl::OnPassphraseRequired(
- PassphraseRequiredReason reason,
- const sync_pb::EncryptedData& pending_keys) {
- // Does nothing.
-}
-
-void SyncManagerImpl::OnPassphraseAccepted() {
- // Does nothing.
-}
-
-void SyncManagerImpl::OnBootstrapTokenUpdated(
- const std::string& bootstrap_token,
- BootstrapTokenType type) {
- if (type == KEYSTORE_BOOTSTRAP_TOKEN)
- allstatus_.SetHasKeystoreKey(true);
-}
-
-void SyncManagerImpl::OnEncryptedTypesChanged(ModelTypeSet encrypted_types,
- bool encrypt_everything) {
- allstatus_.SetEncryptedTypes(encrypted_types);
-}
-
-void SyncManagerImpl::OnEncryptionComplete() {
- // Does nothing.
-}
-
-void SyncManagerImpl::OnCryptographerStateChanged(
- Cryptographer* cryptographer) {
- allstatus_.SetCryptographerReady(cryptographer->is_ready());
- allstatus_.SetCryptoHasPendingKeys(cryptographer->has_pending_keys());
- allstatus_.SetKeystoreMigrationTime(
- sync_encryption_handler_->migration_time());
-}
-
-void SyncManagerImpl::OnPassphraseTypeChanged(
- PassphraseType type,
- base::Time explicit_passphrase_time) {
- allstatus_.SetPassphraseType(type);
- allstatus_.SetKeystoreMigrationTime(
- sync_encryption_handler_->migration_time());
-}
-
-void SyncManagerImpl::OnLocalSetPassphraseEncryption(
- const SyncEncryptionHandler::NigoriState& nigori_state) {
-}
-
-void SyncManagerImpl::StartSyncingNormally(
- const ModelSafeRoutingInfo& routing_info,
- base::Time last_poll_time) {
- // Start the sync scheduler.
- // TODO(sync): We always want the newest set of routes when we switch back
- // to normal mode. Figure out how to enforce set_routing_info is always
- // appropriately set and that it's only modified when switching to normal
- // mode.
- DCHECK(thread_checker_.CalledOnValidThread());
- session_context_->SetRoutingInfo(routing_info);
- scheduler_->Start(SyncScheduler::NORMAL_MODE,
- last_poll_time);
-}
-
-syncable::Directory* SyncManagerImpl::directory() {
- return share_.directory.get();
-}
-
-const SyncScheduler* SyncManagerImpl::scheduler() const {
- return scheduler_.get();
-}
-
-bool SyncManagerImpl::GetHasInvalidAuthTokenForTest() const {
- return connection_manager_->HasInvalidAuthToken();
-}
-
-bool SyncManagerImpl::OpenDirectory(const std::string& username) {
- DCHECK(!initialized_) << "Should only happen once";
-
- // Set before Open().
- change_observer_ = MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr());
- WeakHandle<syncable::TransactionObserver> transaction_observer(
- MakeWeakHandle(js_mutation_event_observer_.AsWeakPtr()));
-
- syncable::DirOpenResult open_result = syncable::NOT_INITIALIZED;
- open_result = directory()->Open(username, this, transaction_observer);
- if (open_result != syncable::OPENED) {
- LOG(ERROR) << "Could not open share for:" << username;
- return false;
- }
-
- // Unapplied datatypes (those that do not have initial sync ended set) get
- // re-downloaded during any configuration. But, it's possible for a datatype
- // to have a progress marker but not have initial sync ended yet, making
- // it a candidate for migration. This is a problem, as the DataTypeManager
- // does not support a migration while it's already in the middle of a
- // configuration. As a result, any partially synced datatype can stall the
- // DTM, waiting for the configuration to complete, which it never will due
- // to the migration error. In addition, a partially synced nigori will
- // trigger the migration logic before the backend is initialized, resulting
- // in crashes. We therefore detect and purge any partially synced types as
- // part of initialization.
- if (!PurgePartiallySyncedTypes())
- return false;
-
- return true;
-}
-
-bool SyncManagerImpl::PurgePartiallySyncedTypes() {
- ModelTypeSet partially_synced_types = ModelTypeSet::All();
- partially_synced_types.RemoveAll(directory()->InitialSyncEndedTypes());
- partially_synced_types.RemoveAll(GetTypesWithEmptyProgressMarkerToken(
- ModelTypeSet::All()));
-
- DVLOG(1) << "Purging partially synced types "
- << ModelTypeSetToString(partially_synced_types);
- UMA_HISTOGRAM_COUNTS("Sync.PartiallySyncedTypes",
- partially_synced_types.Size());
- if (partially_synced_types.Empty())
- return true;
- return directory()->PurgeEntriesWithTypeIn(partially_synced_types,
- ModelTypeSet(),
- ModelTypeSet());
-}
-
-bool SyncManagerImpl::PurgeDisabledTypes(
- ModelTypeSet to_purge,
- ModelTypeSet to_journal,
- ModelTypeSet to_unapply) {
- if (to_purge.Empty())
- return true;
- DVLOG(1) << "Purging disabled types " << ModelTypeSetToString(to_purge);
- DCHECK(to_purge.HasAll(to_journal));
- DCHECK(to_purge.HasAll(to_unapply));
- return directory()->PurgeEntriesWithTypeIn(to_purge, to_journal, to_unapply);
-}
-
-void SyncManagerImpl::UpdateCredentials(const SyncCredentials& credentials) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(initialized_);
- DCHECK(!credentials.account_id.empty());
- DCHECK(!credentials.sync_token.empty());
- DCHECK(!credentials.scope_set.empty());
- session_context_->set_account_name(credentials.email);
-
- observing_network_connectivity_changes_ = true;
- if (!connection_manager_->SetAuthToken(credentials.sync_token))
- return; // Auth token is known to be invalid, so exit early.
-
- scheduler_->OnCredentialsUpdated();
-
- // TODO(zea): pass the credential age to the debug info event listener.
-}
-
-void SyncManagerImpl::AddObserver(SyncManager::Observer* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void SyncManagerImpl::RemoveObserver(SyncManager::Observer* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observers_.RemoveObserver(observer);
-}
-
-void SyncManagerImpl::ShutdownOnSyncThread(ShutdownReason reason) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Prevent any in-flight method calls from running. Also
- // invalidates |weak_handle_this_| and |change_observer_|.
- weak_ptr_factory_.InvalidateWeakPtrs();
- js_mutation_event_observer_.InvalidateWeakPtrs();
-
- scheduler_.reset();
- session_context_.reset();
-
- if (model_type_registry_)
- sync_encryption_handler_->RemoveObserver(model_type_registry_.get());
-
- model_type_registry_.reset();
-
- if (sync_encryption_handler_) {
- sync_encryption_handler_->RemoveObserver(&debug_info_event_listener_);
- sync_encryption_handler_->RemoveObserver(this);
- }
-
- SetJsEventHandler(WeakHandle<JsEventHandler>());
- RemoveObserver(&js_sync_manager_observer_);
-
- RemoveObserver(&debug_info_event_listener_);
-
- // |connection_manager_| may end up being NULL here in tests (in synchronous
- // initialization mode).
- //
- // TODO(akalin): Fix this behavior.
- if (connection_manager_)
- connection_manager_->RemoveListener(this);
- connection_manager_.reset();
-
- net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
- net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
- observing_network_connectivity_changes_ = false;
-
- if (initialized_ && directory()) {
- directory()->SaveChanges();
- }
-
- share_.directory.reset();
-
- change_delegate_ = NULL;
-
- initialized_ = false;
-
- // We reset these here, since only now we know they will not be
- // accessed from other threads (since we shut down everything).
- change_observer_.Reset();
- weak_handle_this_.Reset();
-}
-
-void SyncManagerImpl::OnIPAddressChanged() {
- if (!observing_network_connectivity_changes_) {
- DVLOG(1) << "IP address change dropped.";
- return;
- }
- DVLOG(1) << "IP address change detected.";
- OnNetworkConnectivityChangedImpl();
-}
-
-void SyncManagerImpl::OnConnectionTypeChanged(
- net::NetworkChangeNotifier::ConnectionType) {
- if (!observing_network_connectivity_changes_) {
- DVLOG(1) << "Connection type change dropped.";
- return;
- }
- DVLOG(1) << "Connection type change detected.";
- OnNetworkConnectivityChangedImpl();
-}
-
-void SyncManagerImpl::OnNetworkConnectivityChangedImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
- scheduler_->OnConnectionStatusChange();
-}
-
-void SyncManagerImpl::OnServerConnectionEvent(
- const ServerConnectionEvent& event) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (event.connection_code ==
- HttpResponse::SERVER_CONNECTION_OK) {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnConnectionStatusChange(CONNECTION_OK));
- }
-
- if (event.connection_code == HttpResponse::SYNC_AUTH_ERROR) {
- observing_network_connectivity_changes_ = false;
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnConnectionStatusChange(CONNECTION_AUTH_ERROR));
- }
-
- if (event.connection_code == HttpResponse::SYNC_SERVER_ERROR) {
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnConnectionStatusChange(CONNECTION_SERVER_ERROR));
- }
-}
-
-void SyncManagerImpl::HandleTransactionCompleteChangeEvent(
- ModelTypeSet models_with_changes) {
- // This notification happens immediately after the transaction mutex is
- // released. This allows work to be performed without blocking other threads
- // from acquiring a transaction.
- if (!change_delegate_)
- return;
-
- // Call commit.
- for (ModelTypeSet::Iterator it = models_with_changes.First();
- it.Good(); it.Inc()) {
- change_delegate_->OnChangesComplete(it.Get());
- change_observer_.Call(
- FROM_HERE,
- &SyncManager::ChangeObserver::OnChangesComplete,
- it.Get());
- }
-}
-
-ModelTypeSet
-SyncManagerImpl::HandleTransactionEndingChangeEvent(
- const ImmutableWriteTransactionInfo& write_transaction_info,
- syncable::BaseTransaction* trans) {
- // This notification happens immediately before a syncable WriteTransaction
- // falls out of scope. It happens while the channel mutex is still held,
- // and while the transaction mutex is held, so it cannot be re-entrant.
- if (!change_delegate_ || change_records_.empty())
- return ModelTypeSet();
-
- // This will continue the WriteTransaction using a read only wrapper.
- // This is the last chance for read to occur in the WriteTransaction
- // that's closing. This special ReadTransaction will not close the
- // underlying transaction.
- ReadTransaction read_trans(GetUserShare(), trans);
-
- ModelTypeSet models_with_changes;
- for (ChangeRecordMap::const_iterator it = change_records_.begin();
- it != change_records_.end(); ++it) {
- DCHECK(!it->second.Get().empty());
- ModelType type = ModelTypeFromInt(it->first);
- change_delegate_->
- OnChangesApplied(type, trans->directory()->GetTransactionVersion(type),
- &read_trans, it->second);
- change_observer_.Call(FROM_HERE,
- &SyncManager::ChangeObserver::OnChangesApplied,
- type, write_transaction_info.Get().id, it->second);
- models_with_changes.Put(type);
- }
- change_records_.clear();
- return models_with_changes;
-}
-
-void SyncManagerImpl::HandleCalculateChangesChangeEventFromSyncApi(
- const ImmutableWriteTransactionInfo& write_transaction_info,
- syncable::BaseTransaction* trans,
- std::vector<int64_t>* entries_changed) {
- // We have been notified about a user action changing a sync model.
- LOG_IF(WARNING, !change_records_.empty()) <<
- "CALCULATE_CHANGES called with unapplied old changes.";
-
- // The mutated model type, or UNSPECIFIED if nothing was mutated.
- ModelTypeSet mutated_model_types;
-
- const syncable::ImmutableEntryKernelMutationMap& mutations =
- write_transaction_info.Get().mutations;
- for (syncable::EntryKernelMutationMap::const_iterator it =
- mutations.Get().begin(); it != mutations.Get().end(); ++it) {
- if (!it->second.mutated.ref(syncable::IS_UNSYNCED)) {
- continue;
- }
-
- ModelType model_type =
- GetModelTypeFromSpecifics(it->second.mutated.ref(SPECIFICS));
- if (model_type < FIRST_REAL_MODEL_TYPE) {
- NOTREACHED() << "Permanent or underspecified item changed via syncapi.";
- continue;
- }
-
- // Found real mutation.
- if (model_type != UNSPECIFIED) {
- mutated_model_types.Put(model_type);
- entries_changed->push_back(it->second.mutated.ref(syncable::META_HANDLE));
- }
- }
-
- // Nudge if necessary.
- if (!mutated_model_types.Empty()) {
- if (weak_handle_this_.IsInitialized()) {
- weak_handle_this_.Call(FROM_HERE,
- &SyncManagerImpl::RequestNudgeForDataTypes,
- FROM_HERE,
- mutated_model_types);
- } else {
- NOTREACHED();
- }
- }
-}
-
-void SyncManagerImpl::SetExtraChangeRecordData(
- int64_t id,
- ModelType type,
- ChangeReorderBuffer* buffer,
- Cryptographer* cryptographer,
- const syncable::EntryKernel& original,
- bool existed_before,
- bool exists_now) {
- // If this is a deletion and the datatype was encrypted, we need to decrypt it
- // and attach it to the buffer.
- if (!exists_now && existed_before) {
- sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS));
- if (type == PASSWORDS) {
- // Passwords must use their own legacy ExtraPasswordChangeRecordData.
- std::unique_ptr<sync_pb::PasswordSpecificsData> data(
- DecryptPasswordSpecifics(original_specifics, cryptographer));
- if (!data) {
- NOTREACHED();
- return;
- }
- buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data));
- } else if (original_specifics.has_encrypted()) {
- // All other datatypes can just create a new unencrypted specifics and
- // attach it.
- const sync_pb::EncryptedData& encrypted = original_specifics.encrypted();
- if (!cryptographer->Decrypt(encrypted, &original_specifics)) {
- NOTREACHED();
- return;
- }
- }
- buffer->SetSpecificsForId(id, original_specifics);
- }
-}
-
-void SyncManagerImpl::HandleCalculateChangesChangeEventFromSyncer(
- const ImmutableWriteTransactionInfo& write_transaction_info,
- syncable::BaseTransaction* trans,
- std::vector<int64_t>* entries_changed) {
- // We only expect one notification per sync step, so change_buffers_ should
- // contain no pending entries.
- LOG_IF(WARNING, !change_records_.empty()) <<
- "CALCULATE_CHANGES called with unapplied old changes.";
-
- ChangeReorderBuffer change_buffers[MODEL_TYPE_COUNT];
-
- Cryptographer* crypto = directory()->GetCryptographer(trans);
- const syncable::ImmutableEntryKernelMutationMap& mutations =
- write_transaction_info.Get().mutations;
- for (syncable::EntryKernelMutationMap::const_iterator it =
- mutations.Get().begin(); it != mutations.Get().end(); ++it) {
- bool existed_before = !it->second.original.ref(syncable::IS_DEL);
- bool exists_now = !it->second.mutated.ref(syncable::IS_DEL);
-
- // Omit items that aren't associated with a model.
- ModelType type =
- GetModelTypeFromSpecifics(it->second.mutated.ref(SPECIFICS));
- if (type < FIRST_REAL_MODEL_TYPE)
- continue;
-
- int64_t handle = it->first;
- if (exists_now && !existed_before)
- change_buffers[type].PushAddedItem(handle);
- else if (!exists_now && existed_before)
- change_buffers[type].PushDeletedItem(handle);
- else if (exists_now && existed_before &&
- VisiblePropertiesDiffer(it->second, crypto))
- change_buffers[type].PushUpdatedItem(handle);
-
- SetExtraChangeRecordData(handle, type, &change_buffers[type], crypto,
- it->second.original, existed_before, exists_now);
- }
-
- ReadTransaction read_trans(GetUserShare(), trans);
- for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) {
- if (!change_buffers[i].IsEmpty()) {
- if (change_buffers[i].GetAllChangesInTreeOrder(&read_trans,
- &(change_records_[i]))) {
- for (size_t j = 0; j < change_records_[i].Get().size(); ++j)
- entries_changed->push_back((change_records_[i].Get())[j].id);
- }
- if (change_records_[i].Get().empty())
- change_records_.erase(i);
- }
- }
-}
-
-void SyncManagerImpl::RequestNudgeForDataTypes(
- const tracked_objects::Location& nudge_location,
- ModelTypeSet types) {
- debug_info_event_listener_.OnNudgeFromDatatype(types.First().Get());
-
- scheduler_->ScheduleLocalNudge(types, nudge_location);
-}
-
-void SyncManagerImpl::NudgeForInitialDownload(syncer::ModelType type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- scheduler_->ScheduleInitialSyncNudge(type);
-}
-
-void SyncManagerImpl::NudgeForCommit(syncer::ModelType type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- RequestNudgeForDataTypes(FROM_HERE, ModelTypeSet(type));
-}
-
-void SyncManagerImpl::NudgeForRefresh(syncer::ModelType type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- RefreshTypes(ModelTypeSet(type));
-}
-
-void SyncManagerImpl::OnSyncCycleEvent(const SyncCycleEvent& event) {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Only send an event if this is due to a cycle ending and this cycle
- // concludes a canonical "sync" process; that is, based on what is known
- // locally we are "all happy" and up to date. There may be new changes on
- // the server, but we'll get them on a subsequent sync.
- //
- // Notifications are sent at the end of every sync cycle, regardless of
- // whether we should sync again.
- if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
- if (!initialized_) {
- DVLOG(1) << "OnSyncCycleCompleted not sent because sync api is not "
- << "initialized";
- return;
- }
-
- DVLOG(1) << "Sending OnSyncCycleCompleted";
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnSyncCycleCompleted(event.snapshot));
- }
-}
-
-void SyncManagerImpl::OnActionableError(const SyncProtocolError& error) {
- FOR_EACH_OBSERVER(
- SyncManager::Observer, observers_,
- OnActionableError(error));
-}
-
-void SyncManagerImpl::OnRetryTimeChanged(base::Time) {}
-
-void SyncManagerImpl::OnThrottledTypesChanged(ModelTypeSet) {}
-
-void SyncManagerImpl::OnMigrationRequested(ModelTypeSet types) {
- FOR_EACH_OBSERVER(
- SyncManager::Observer, observers_,
- OnMigrationRequested(types));
-}
-
-void SyncManagerImpl::OnProtocolEvent(const ProtocolEvent& event) {
- protocol_event_buffer_.RecordProtocolEvent(event);
- FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
- OnProtocolEvent(event));
-}
-
-void SyncManagerImpl::SetJsEventHandler(
- const WeakHandle<JsEventHandler>& event_handler) {
- js_sync_manager_observer_.SetJsEventHandler(event_handler);
- js_mutation_event_observer_.SetJsEventHandler(event_handler);
- js_sync_encryption_handler_observer_.SetJsEventHandler(event_handler);
-}
-
-std::unique_ptr<base::ListValue> SyncManagerImpl::GetAllNodesForType(
- syncer::ModelType type) {
- DirectoryTypeDebugInfoEmitterMap* emitter_map =
- model_type_registry_->directory_type_debug_info_emitter_map();
- DirectoryTypeDebugInfoEmitterMap::iterator it = emitter_map->find(type);
-
- if (it == emitter_map->end()) {
- // This can happen in some cases. The UI thread makes requests of us
- // when it doesn't really know which types are enabled or disabled.
- DLOG(WARNING) << "Asked to return debug info for invalid type "
- << ModelTypeToString(type);
- return std::unique_ptr<base::ListValue>(new base::ListValue());
- }
-
- return it->second->GetAllNodes();
-}
-
-void SyncManagerImpl::SetInvalidatorEnabled(bool invalidator_enabled) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- DVLOG(1) << "Invalidator enabled state is now: " << invalidator_enabled;
- allstatus_.SetNotificationsEnabled(invalidator_enabled);
- scheduler_->SetNotificationsEnabled(invalidator_enabled);
-}
-
-void SyncManagerImpl::OnIncomingInvalidation(
- syncer::ModelType type,
- std::unique_ptr<InvalidationInterface> invalidation) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- allstatus_.IncrementNotificationsReceived();
- scheduler_->ScheduleInvalidationNudge(type, std::move(invalidation),
- FROM_HERE);
-}
-
-void SyncManagerImpl::RefreshTypes(ModelTypeSet types) {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (types.Empty()) {
- LOG(WARNING) << "Sync received refresh request with no types specified.";
- } else {
- scheduler_->ScheduleLocalRefreshRequest(
- types, FROM_HERE);
- }
-}
-
-SyncStatus SyncManagerImpl::GetDetailedStatus() const {
- return allstatus_.status();
-}
-
-void SyncManagerImpl::SaveChanges() {
- directory()->SaveChanges();
-}
-
-UserShare* SyncManagerImpl::GetUserShare() {
- DCHECK(initialized_);
- return &share_;
-}
-
-std::unique_ptr<syncer_v2::ModelTypeConnector>
-SyncManagerImpl::GetModelTypeConnectorProxy() {
- DCHECK(initialized_);
- return base::WrapUnique(new syncer_v2::ModelTypeConnectorProxy(
- base::ThreadTaskRunnerHandle::Get(), model_type_registry_->AsWeakPtr()));
-}
-
-const std::string SyncManagerImpl::cache_guid() {
- DCHECK(initialized_);
- return directory()->cache_guid();
-}
-
-bool SyncManagerImpl::ReceivedExperiment(Experiments* experiments) {
- ReadTransaction trans(FROM_HERE, GetUserShare());
- ReadNode nigori_node(&trans);
- if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) {
- DVLOG(1) << "Couldn't find Nigori node.";
- return false;
- }
- bool found_experiment = false;
-
- ReadNode favicon_sync_node(&trans);
- if (favicon_sync_node.InitByClientTagLookup(
- syncer::EXPERIMENTS,
- syncer::kFaviconSyncTag) == BaseNode::INIT_OK) {
- experiments->favicon_sync_limit =
- favicon_sync_node.GetExperimentsSpecifics().favicon_sync().
- favicon_sync_limit();
- found_experiment = true;
- }
-
- ReadNode pre_commit_update_avoidance_node(&trans);
- if (pre_commit_update_avoidance_node.InitByClientTagLookup(
- syncer::EXPERIMENTS,
- syncer::kPreCommitUpdateAvoidanceTag) == BaseNode::INIT_OK) {
- session_context_->set_server_enabled_pre_commit_update_avoidance(
- pre_commit_update_avoidance_node.GetExperimentsSpecifics().
- pre_commit_update_avoidance().enabled());
- // We don't bother setting found_experiment. The frontend doesn't need to
- // know about this.
- }
-
- ReadNode gcm_invalidations_node(&trans);
- if (gcm_invalidations_node.InitByClientTagLookup(
- syncer::EXPERIMENTS, syncer::kGCMInvalidationsTag) ==
- BaseNode::INIT_OK) {
- const sync_pb::GcmInvalidationsFlags& gcm_invalidations =
- gcm_invalidations_node.GetExperimentsSpecifics().gcm_invalidations();
- if (gcm_invalidations.has_enabled()) {
- experiments->gcm_invalidations_enabled = gcm_invalidations.enabled();
- found_experiment = true;
- }
- }
-
- return found_experiment;
-}
-
-bool SyncManagerImpl::HasUnsyncedItems() {
- ReadTransaction trans(FROM_HERE, GetUserShare());
- return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0);
-}
-
-SyncEncryptionHandler* SyncManagerImpl::GetEncryptionHandler() {
- return sync_encryption_handler_.get();
-}
-
-ScopedVector<syncer::ProtocolEvent>
- SyncManagerImpl::GetBufferedProtocolEvents() {
- return protocol_event_buffer_.GetBufferedProtocolEvents();
-}
-
-void SyncManagerImpl::RegisterDirectoryTypeDebugInfoObserver(
- syncer::TypeDebugInfoObserver* observer) {
- model_type_registry_->RegisterDirectoryTypeDebugInfoObserver(observer);
-}
-
-void SyncManagerImpl::UnregisterDirectoryTypeDebugInfoObserver(
- syncer::TypeDebugInfoObserver* observer) {
- model_type_registry_->UnregisterDirectoryTypeDebugInfoObserver(observer);
-}
-
-bool SyncManagerImpl::HasDirectoryTypeDebugInfoObserver(
- syncer::TypeDebugInfoObserver* observer) {
- return model_type_registry_->HasDirectoryTypeDebugInfoObserver(observer);
-}
-
-void SyncManagerImpl::RequestEmitDebugInfo() {
- model_type_registry_->RequestEmitDebugInfo();
-}
-
-void SyncManagerImpl::ClearServerData(const ClearServerDataCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- scheduler_->Start(SyncScheduler::CLEAR_SERVER_DATA_MODE, base::Time());
- ClearParams params(callback);
- scheduler_->ScheduleClearServerData(params);
-}
-
-void SyncManagerImpl::OnCookieJarChanged(bool account_mismatch,
- bool empty_jar) {
- DCHECK(thread_checker_.CalledOnValidThread());
- session_context_->set_cookie_jar_mismatch(account_mismatch);
- session_context_->set_cookie_jar_empty(empty_jar);
-}
-
-} // namespace syncer
« no previous file with comments | « sync/internal_api/sync_manager_impl.h ('k') | sync/internal_api/sync_manager_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698