diff options
author | maxbogue <maxbogue@chromium.org> | 2015-10-09 10:42:13 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-09 17:43:56 +0000 |
commit | 786b459e828e3d593d92ccd8f1b53dee26cbe052 (patch) | |
tree | cf0b56aa3954d75a926655d94af8919aa871903c /sync/engine | |
parent | 18930bdc3e8f077a3508121b0ce4e34386878db2 (diff) | |
download | chromium_src-786b459e828e3d593d92ccd8f1b53dee26cbe052.zip chromium_src-786b459e828e3d593d92ccd8f1b53dee26cbe052.tar.gz chromium_src-786b459e828e3d593d92ccd8f1b53dee26cbe052.tar.bz2 |
[Sync] Move ModelTypeProcessor* and rename *Impl to Shared*.
BUG=536895
Review URL: https://codereview.chromium.org/1382743004
Cr-Commit-Position: refs/heads/master@{#353323}
Diffstat (limited to 'sync/engine')
-rw-r--r-- | sync/engine/model_type_entity_unittest.cc | 6 | ||||
-rw-r--r-- | sync/engine/model_type_processor.cc | 15 | ||||
-rw-r--r-- | sync/engine/model_type_processor.h | 40 | ||||
-rw-r--r-- | sync/engine/model_type_processor_impl.cc | 298 | ||||
-rw-r--r-- | sync/engine/model_type_processor_impl.h | 154 | ||||
-rw-r--r-- | sync/engine/model_type_processor_impl_unittest.cc | 706 | ||||
-rw-r--r-- | sync/engine/model_type_worker.cc | 2 | ||||
-rw-r--r-- | sync/engine/model_type_worker_unittest.cc | 2 |
8 files changed, 5 insertions, 1218 deletions
diff --git a/sync/engine/model_type_entity_unittest.cc b/sync/engine/model_type_entity_unittest.cc index 5f3e666..5efe72b 100644 --- a/sync/engine/model_type_entity_unittest.cc +++ b/sync/engine/model_type_entity_unittest.cc @@ -17,12 +17,12 @@ namespace syncer_v2 { // Some simple sanity tests for the ModelTypeEntity. // // A lot of the more complicated sync logic is implemented in the -// ModelTypeProcessorImpl that owns the ModelTypeEntity. We can't unit test it -// here. +// SharedModelTypeProcessor that owns the ModelTypeEntity. We can't unit test +// it here. // // Instead, we focus on simple tests to make sure that variables are getting // properly intialized and flags properly set. Anything more complicated would -// be a redundant and incomplete version of the ModelTypeProcessorImpl tests. +// be a redundant and incomplete version of the SharedModelTypeProcessor tests. class ModelTypeEntityTest : public ::testing::Test { public: ModelTypeEntityTest() diff --git a/sync/engine/model_type_processor.cc b/sync/engine/model_type_processor.cc deleted file mode 100644 index c4c2407..0000000 --- a/sync/engine/model_type_processor.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 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/engine/model_type_processor.h" - -namespace syncer_v2 { - -ModelTypeProcessor::ModelTypeProcessor() { -} - -ModelTypeProcessor::~ModelTypeProcessor() { -} - -} // namespace syncer diff --git a/sync/engine/model_type_processor.h b/sync/engine/model_type_processor.h deleted file mode 100644 index 0cb8581..0000000 --- a/sync/engine/model_type_processor.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014 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. - -#ifndef SYNC_ENGINE_MODEL_TYPE_PROCESSOR_H_ -#define SYNC_ENGINE_MODEL_TYPE_PROCESSOR_H_ - -#include "base/memory/scoped_ptr.h" -#include "sync/base/sync_export.h" -#include "sync/engine/commit_queue.h" -#include "sync/internal_api/public/non_blocking_sync_common.h" - -namespace syncer_v2 { - -// Interface used by sync backend to issue requests to a synced data type. -class SYNC_EXPORT_PRIVATE ModelTypeProcessor { - public: - ModelTypeProcessor(); - virtual ~ModelTypeProcessor(); - - // Callback used to process the handshake response. - virtual void OnConnect(scoped_ptr<CommitQueue> commit_queue) = 0; - - // Informs this object that some of its commit requests have been - // successfully serviced. - virtual void OnCommitCompleted( - const DataTypeState& type_state, - const CommitResponseDataList& response_list) = 0; - - // Informs this object that there are some incoming updates is should - // handle. - virtual void OnUpdateReceived( - const DataTypeState& type_state, - const UpdateResponseDataList& response_list, - const UpdateResponseDataList& pending_updates) = 0; -}; - -} // namespace syncer - -#endif // SYNC_ENGINE_MODEL_TYPE_PROCESSOR_H_ diff --git a/sync/engine/model_type_processor_impl.cc b/sync/engine/model_type_processor_impl.cc deleted file mode 100644 index 2b02906..0000000 --- a/sync/engine/model_type_processor_impl.cc +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2014 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/engine/model_type_processor_impl.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/thread_task_runner_handle.h" -#include "sync/engine/commit_queue.h" -#include "sync/engine/model_type_entity.h" -#include "sync/internal_api/public/activation_context.h" -#include "sync/syncable/syncable_util.h" - -namespace syncer_v2 { - -ModelTypeProcessorImpl::ModelTypeProcessorImpl( - syncer::ModelType type, - base::WeakPtr<ModelTypeStore> store) - : type_(type), - is_enabled_(false), - is_connected_(false), - store_(store), - weak_ptr_factory_for_ui_(this), - weak_ptr_factory_for_sync_(this) {} - -ModelTypeProcessorImpl::~ModelTypeProcessorImpl() { -} - -void ModelTypeProcessorImpl::Start(StartCallback callback) { - DCHECK(CalledOnValidThread()); - DVLOG(1) << "Starting " << ModelTypeToString(type_); - - is_enabled_ = true; - - // TODO: At some point, this should be loaded from storage. - data_type_state_.progress_marker.set_data_type_id( - GetSpecificsFieldNumberFromModelType(type_)); - - scoped_ptr<ActivationContext> activation_context = - make_scoped_ptr(new ActivationContext); - activation_context->data_type_state = data_type_state_; - activation_context->saved_pending_updates = GetPendingUpdates(); - activation_context->type_task_runner = base::ThreadTaskRunnerHandle::Get(); - activation_context->type_processor = weak_ptr_factory_for_sync_.GetWeakPtr(); - - callback.Run(/*syncer::SyncError(), */ activation_context.Pass()); -} - -bool ModelTypeProcessorImpl::IsEnabled() const { - DCHECK(CalledOnValidThread()); - return is_enabled_; -} - -bool ModelTypeProcessorImpl::IsConnected() const { - DCHECK(CalledOnValidThread()); - return is_connected_; -} - -// TODO(stanisc): crbug.com/537027: This needs to be called from -// DataTypeController when the type is disabled -void ModelTypeProcessorImpl::Disable() { - DCHECK(CalledOnValidThread()); - is_enabled_ = false; - Stop(); - ClearSyncState(); -} - -void ModelTypeProcessorImpl::Stop() { - DCHECK(CalledOnValidThread()); - DVLOG(1) << "Stopping " << ModelTypeToString(type_); - is_connected_ = false; - weak_ptr_factory_for_sync_.InvalidateWeakPtrs(); - worker_.reset(); - - ClearTransientSyncState(); -} - -base::WeakPtr<ModelTypeProcessorImpl> ModelTypeProcessorImpl::AsWeakPtrForUI() { - DCHECK(CalledOnValidThread()); - return weak_ptr_factory_for_ui_.GetWeakPtr(); -} - -void ModelTypeProcessorImpl::OnConnect(scoped_ptr<CommitQueue> worker) { - DCHECK(CalledOnValidThread()); - DVLOG(1) << "Successfully connected " << ModelTypeToString(type_); - - is_connected_ = true; - worker_ = worker.Pass(); - - FlushPendingCommitRequests(); -} - -void ModelTypeProcessorImpl::Put(const std::string& client_tag, - const sync_pb::EntitySpecifics& specifics) { - DCHECK_EQ(type_, syncer::GetModelTypeFromSpecifics(specifics)); - - const std::string client_tag_hash( - syncer::syncable::GenerateSyncableHash(type_, client_tag)); - - EntityMap::const_iterator it = entities_.find(client_tag_hash); - if (it == entities_.end()) { - scoped_ptr<ModelTypeEntity> entity(ModelTypeEntity::NewLocalItem( - client_tag, specifics, base::Time::Now())); - entities_.insert(client_tag_hash, entity.Pass()); - } else { - ModelTypeEntity* entity = it->second; - entity->MakeLocalChange(specifics); - } - - FlushPendingCommitRequests(); -} - -void ModelTypeProcessorImpl::Delete(const std::string& client_tag) { - const std::string client_tag_hash( - syncer::syncable::GenerateSyncableHash(type_, client_tag)); - - EntityMap::const_iterator it = entities_.find(client_tag_hash); - if (it == entities_.end()) { - // That's unusual, but not necessarily a bad thing. - // Missing is as good as deleted as far as the model is concerned. - DLOG(WARNING) << "Attempted to delete missing item." - << " client tag: " << client_tag; - } else { - ModelTypeEntity* entity = it->second; - entity->Delete(); - } - - FlushPendingCommitRequests(); -} - -void ModelTypeProcessorImpl::FlushPendingCommitRequests() { - CommitRequestDataList commit_requests; - - // Don't bother sending anything if there's no one to send to. - if (!IsConnected()) - return; - - // Don't send anything if the type is not ready to handle commits. - if (!data_type_state_.initial_sync_done) - return; - - // TODO(rlarocque): Do something smarter than iterate here. - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - if (it->second->RequiresCommitRequest()) { - CommitRequestData request; - it->second->InitializeCommitRequestData(&request); - commit_requests.push_back(request); - it->second->SetCommitRequestInProgress(); - } - } - - if (!commit_requests.empty()) - worker_->EnqueueForCommit(commit_requests); -} - -void ModelTypeProcessorImpl::OnCommitCompleted( - const DataTypeState& type_state, - const CommitResponseDataList& response_list) { - data_type_state_ = type_state; - - for (CommitResponseDataList::const_iterator list_it = response_list.begin(); - list_it != response_list.end(); ++list_it) { - const CommitResponseData& response_data = *list_it; - const std::string& client_tag_hash = response_data.client_tag_hash; - - EntityMap::const_iterator it = entities_.find(client_tag_hash); - if (it == entities_.end()) { - NOTREACHED() << "Received commit response for missing item." - << " type: " << type_ << " client_tag: " << client_tag_hash; - return; - } else { - it->second->ReceiveCommitResponse(response_data.id, - response_data.sequence_number, - response_data.response_version, - data_type_state_.encryption_key_name); - } - } -} - -void ModelTypeProcessorImpl::OnUpdateReceived( - const DataTypeState& data_type_state, - const UpdateResponseDataList& response_list, - const UpdateResponseDataList& pending_updates) { - bool got_new_encryption_requirements = data_type_state_.encryption_key_name != - data_type_state.encryption_key_name; - - data_type_state_ = data_type_state; - - for (UpdateResponseDataList::const_iterator list_it = response_list.begin(); - list_it != response_list.end(); ++list_it) { - const UpdateResponseData& response_data = *list_it; - const std::string& client_tag_hash = response_data.client_tag_hash; - - // If we're being asked to apply an update to this entity, this overrides - // the previous pending updates. - pending_updates_map_.erase(client_tag_hash); - - EntityMap::const_iterator it = entities_.find(client_tag_hash); - if (it == entities_.end()) { - scoped_ptr<ModelTypeEntity> entity = - ModelTypeEntity::FromServerUpdate(response_data.id, - response_data.client_tag_hash, - response_data.non_unique_name, - response_data.response_version, - response_data.specifics, - response_data.deleted, - response_data.ctime, - response_data.mtime, - response_data.encryption_key_name); - entities_.insert(client_tag_hash, entity.Pass()); - } else { - ModelTypeEntity* entity = it->second; - entity->ApplyUpdateFromServer(response_data.response_version, - response_data.deleted, - response_data.specifics, - response_data.mtime, - response_data.encryption_key_name); - - // TODO: Do something special when conflicts are detected. - } - - // If the received entity has out of date encryption, we schedule another - // commit to fix it. - if (data_type_state_.encryption_key_name != - response_data.encryption_key_name) { - DVLOG(2) << ModelTypeToString(type_) << ": Requesting re-encrypt commit " - << response_data.encryption_key_name << " -> " - << data_type_state_.encryption_key_name; - EntityMap::const_iterator it2 = entities_.find(client_tag_hash); - it2->second->UpdateDesiredEncryptionKey( - data_type_state_.encryption_key_name); - } - } - - // Save pending updates in the appropriate data structure. - for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin(); - list_it != pending_updates.end(); ++list_it) { - const UpdateResponseData& update = *list_it; - const std::string& client_tag_hash = update.client_tag_hash; - - UpdateMap::const_iterator lookup_it = - pending_updates_map_.find(client_tag_hash); - if (lookup_it == pending_updates_map_.end()) { - pending_updates_map_.insert( - client_tag_hash, make_scoped_ptr(new UpdateResponseData(update))); - } else if (lookup_it->second->response_version <= update.response_version) { - pending_updates_map_.erase(lookup_it); - pending_updates_map_.insert( - client_tag_hash, make_scoped_ptr(new UpdateResponseData(update))); - } else { - // Received update is stale, do not overwrite existing. - } - } - - if (got_new_encryption_requirements) { - for (EntityMap::const_iterator it = entities_.begin(); - it != entities_.end(); ++it) { - it->second->UpdateDesiredEncryptionKey( - data_type_state_.encryption_key_name); - } - } - - // We may have new reasons to commit by the time this function is done. - FlushPendingCommitRequests(); - - // TODO: Inform the model of the new or updated data. - // TODO: Persist the new data on disk. -} - -UpdateResponseDataList ModelTypeProcessorImpl::GetPendingUpdates() { - UpdateResponseDataList pending_updates_list; - for (UpdateMap::const_iterator it = pending_updates_map_.begin(); - it != pending_updates_map_.end(); - ++it) { - pending_updates_list.push_back(*it->second); - } - return pending_updates_list; -} - -void ModelTypeProcessorImpl::ClearTransientSyncState() { - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - it->second->ClearTransientSyncState(); - } -} - -void ModelTypeProcessorImpl::ClearSyncState() { - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); - ++it) { - it->second->ClearSyncState(); - } - pending_updates_map_.clear(); - data_type_state_ = DataTypeState(); -} - -} // namespace syncer diff --git a/sync/engine/model_type_processor_impl.h b/sync/engine/model_type_processor_impl.h deleted file mode 100644 index 80dc15d..0000000 --- a/sync/engine/model_type_processor_impl.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2014 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. - -#ifndef SYNC_ENGINE_MODEL_TYPE_SYNC_PROXY_IMPL_H_ -#define SYNC_ENGINE_MODEL_TYPE_SYNC_PROXY_IMPL_H_ - -#include "base/containers/scoped_ptr_map.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "sync/base/sync_export.h" -#include "sync/engine/model_type_processor.h" -#include "sync/internal_api/public/base/model_type.h" -#include "sync/internal_api/public/non_blocking_sync_common.h" -#include "sync/protocol/sync.pb.h" - -namespace syncer_v2 { -struct ActivationContext; -class CommitQueue; -class ModelTypeEntity; -class ModelTypeStore; - -// A sync component embedded on the synced type's thread that helps to handle -// communication between sync and model type threads. -class SYNC_EXPORT_PRIVATE ModelTypeProcessorImpl : public ModelTypeProcessor, - base::NonThreadSafe { - public: - ModelTypeProcessorImpl(syncer::ModelType type, - base::WeakPtr<ModelTypeStore> store); - ~ModelTypeProcessorImpl() override; - - typedef base::Callback<void( - /*syncer::SyncError,*/ scoped_ptr<ActivationContext>)> StartCallback; - - // Called by DataTypeController to begins asynchronous operation of preparing - // the model to sync. Once the model is ready to be activated with Sync the - // callback will be invoked with the activation context. If the model is - // already ready it is safe to call the callback right away. Otherwise the - // callback needs to be stored and called when the model is ready. - void Start(StartCallback callback); - - // Called by DataTypeController to inform the model that the sync is - // stopping for the model type. - void Stop(); - - // Returns true if the datatype is enabled. - // TODO(stanisc): crbug.com/537027: There is no explicit call to indicate - // that the datatype is enabled. The flag is set to true when Start is called - // and reset to false when Disable is called. - bool IsEnabled() const; - - // TODO(stanisc): crbug.com/537027: This needs to be called from - // DataTypeController when the type is disabled - // Severs all ties to the sync thread and may delete local sync state. - // Another call to Enable() can be used to re-establish this connection. - void Disable(); - - // Callback used to process the handshake response from the sync thread. - void OnConnect(scoped_ptr<CommitQueue> worker) override; - - // Returns true if the handshake with sync thread is complete. - bool IsConnected() const; - - // Requests that an item be stored in sync. - void Put(const std::string& client_tag, - const sync_pb::EntitySpecifics& specifics); - - // Deletes an item from sync. - void Delete(const std::string& client_tag); - - // Informs this object that some of its commit requests have been - // successfully serviced. - void OnCommitCompleted(const DataTypeState& type_state, - const CommitResponseDataList& response_list) override; - - // Informs this object that there are some incoming updates is should - // handle. - void OnUpdateReceived(const DataTypeState& type_state, - const UpdateResponseDataList& response_list, - const UpdateResponseDataList& pending_updates) override; - - // Returns the list of pending updates. - // - // This is used as a helper function, but it's public mainly for testing. - // The current test harness setup doesn't allow us to test the data that the - // proxy sends to the worker during initialization, so we use this to inspect - // its state instead. - UpdateResponseDataList GetPendingUpdates(); - - // Returns the long-lived WeakPtr that is intended to be registered with the - // ProfileSyncService. - base::WeakPtr<ModelTypeProcessorImpl> AsWeakPtrForUI(); - - private: - typedef base::ScopedPtrMap<std::string, scoped_ptr<ModelTypeEntity>> - EntityMap; - typedef base::ScopedPtrMap<std::string, scoped_ptr<UpdateResponseData>> - UpdateMap; - - // Sends all commit requests that are due to be sent to the sync thread. - void FlushPendingCommitRequests(); - - // Clears any state related to outstanding communications with the - // CommitQueue. Used when we want to disconnect from - // the current worker. - void ClearTransientSyncState(); - - // Clears any state related to our communications with the current sync - // account. Useful when a user signs out of the current account. - void ClearSyncState(); - - syncer::ModelType type_; - DataTypeState data_type_state_; - - // Whether or not sync is enabled by this type's DataTypeController. - bool is_enabled_; - - // Whether or not this object has completed its initial handshake with the - // SyncContextProxy. - bool is_connected_; - - // Reference to the CommitQueue. - // - // The interface hides the posting of tasks across threads as well as the - // CommitQueue's implementation. Both of these features are - // useful in tests. - scoped_ptr<CommitQueue> worker_; - - // The set of sync entities known to this object. - EntityMap entities_; - - // A set of updates that can not be applied at this time. These are never - // used by the model. They are kept here only so we can save and restore - // them across restarts, and keep them in sync with our progress markers. - UpdateMap pending_updates_map_; - - // Store is supplied by model type implementation. ModelTypeProcessorImpl - // uses store for persisting sync related data (entity state and data type - // state). - base::WeakPtr<ModelTypeStore> store_; - - // We use two different WeakPtrFactories because we want the pointers they - // issue to have different lifetimes. When asked to disconnect from the sync - // thread, we want to make sure that no tasks generated as part of the - // now-obsolete connection to affect us. But we also want the WeakPtr we - // sent to the UI thread to remain valid. - base::WeakPtrFactory<ModelTypeProcessorImpl> weak_ptr_factory_for_ui_; - base::WeakPtrFactory<ModelTypeProcessorImpl> weak_ptr_factory_for_sync_; -}; - -} // namespace syncer - -#endif // SYNC_ENGINE_MODEL_TYPE_SYNC_PROXY_IMPL_H_ diff --git a/sync/engine/model_type_processor_impl_unittest.cc b/sync/engine/model_type_processor_impl_unittest.cc deleted file mode 100644 index 31fd29f..0000000 --- a/sync/engine/model_type_processor_impl_unittest.cc +++ /dev/null @@ -1,706 +0,0 @@ -// Copyright 2014 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/engine/model_type_processor_impl.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "sync/engine/commit_queue.h" -#include "sync/internal_api/public/activation_context.h" -#include "sync/internal_api/public/base/model_type.h" -#include "sync/internal_api/public/non_blocking_sync_common.h" -#include "sync/protocol/sync.pb.h" -#include "sync/syncable/syncable_util.h" -#include "sync/test/engine/mock_commit_queue.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace syncer_v2 { - -static const syncer::ModelType kModelType = syncer::PREFERENCES; - -// Tests the sync engine parts of ModelTypeProcessorImpl. -// -// The ModelTypeProcessorImpl contains a non-trivial amount of code dedicated -// to turning the sync engine on and off again. That code is fairly well -// tested in the NonBlockingDataTypeController unit tests and it doesn't need -// to be re-tested here. -// -// These tests skip past initialization and focus on steady state sync engine -// behvior. This is where we test how the type sync proxy responds to the -// model's requests to make changes to its data, the messages incoming from the -// sync server, and what happens when the two conflict. -// -// Inputs: -// - Initial state from permanent storage. (TODO) -// - Create, update or delete requests from the model. -// - Update responses and commit responses from the server. -// -// Outputs: -// - Writes to permanent storage. (TODO) -// - Callbacks into the model. (TODO) -// - Requests to the sync thread. Tested with MockCommitQueue. -class ModelTypeProcessorImplTest : public ::testing::Test { - public: - ModelTypeProcessorImplTest(); - ~ModelTypeProcessorImplTest() override; - - // Initialize to a "ready-to-commit" state. - void InitializeToReadyState(); - - // Start our ModelTypeProcessorImpl, which will be unable to commit until it - // receives notification that initial sync has completed. - void Start(); - - // Stop and disconnect the CommitQueue from our ModelTypeProcessorImpl. - void Stop(); - - // Disable sync for this ModelTypeProcessorImpl. Should cause sync state to - // be discarded. - void Disable(); - - // Restart sync after Stop() or Disable(). - void Restart(); - - // Local data modification. Emulates signals from the model thread. - void WriteItem(const std::string& tag, const std::string& value); - void DeleteItem(const std::string& tag); - - // Emulates an "initial sync done" message from the - // CommitQueue. - void OnInitialSyncDone(); - - // Emulate updates from the server. - // This harness has some functionality to help emulate server behavior. - // See the definitions of these methods for more information. - void UpdateFromServer(int64 version_offset, - const std::string& tag, - const std::string& value); - void TombstoneFromServer(int64 version_offset, const std::string& tag); - - // Emulate the receipt of pending updates from the server. - // Pending updates are usually caused by a temporary decryption failure. - void PendingUpdateFromServer(int64 version_offset, - const std::string& tag, - const std::string& value, - const std::string& key_name); - - // Returns true if the proxy has an pending update with specified tag. - bool HasPendingUpdate(const std::string& tag) const; - - // Returns the pending update with the specified tag. - UpdateResponseData GetPendingUpdate(const std::string& tag) const; - - // Returns the number of pending updates. - size_t GetNumPendingUpdates() const; - - // Read emitted commit requests as batches. - size_t GetNumCommitRequestLists(); - CommitRequestDataList GetNthCommitRequestList(size_t n); - - // Read emitted commit requests by tag, most recent only. - bool HasCommitRequestForTag(const std::string& tag); - CommitRequestData GetLatestCommitRequestForTag(const std::string& tag); - - // Sends the type sync proxy a successful commit response. - void SuccessfulCommitResponse(const CommitRequestData& request_data); - - // Sends the type sync proxy an updated DataTypeState to let it know that - // the desired encryption key has changed. - void UpdateDesiredEncryptionKey(const std::string& key_name); - - // Sets the key_name that the mock CommitQueue will claim is in use - // when receiving items. - void SetServerEncryptionKey(const std::string& key_name); - - private: - static std::string GenerateTagHash(const std::string& tag); - static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, - const std::string& value); - static sync_pb::EntitySpecifics GenerateEncryptedSpecifics( - const std::string& tag, - const std::string& value, - const std::string& key_name); - - int64 GetServerVersion(const std::string& tag); - void SetServerVersion(const std::string& tag, int64 version); - - void StartDone(/*syncer::SyncError,*/ scoped_ptr<ActivationContext> context); - - // The current mock queue which might be owned by either |mock_queue_ptr_| or - // |type_processor_|. - MockCommitQueue* mock_queue_; - scoped_ptr<MockCommitQueue> mock_queue_ptr_; - scoped_ptr<ModelTypeProcessorImpl> type_processor_; - - DataTypeState data_type_state_; - // This sets ThreadTaskRunnerHandle on the current thread. - base::MessageLoop message_loop_; -}; - -ModelTypeProcessorImplTest::ModelTypeProcessorImplTest() - : mock_queue_(new MockCommitQueue()), - mock_queue_ptr_(mock_queue_), - type_processor_( - new ModelTypeProcessorImpl(kModelType, - base::WeakPtr<ModelTypeStore>())) {} - -ModelTypeProcessorImplTest::~ModelTypeProcessorImplTest() { -} - -void ModelTypeProcessorImplTest::InitializeToReadyState() { - // TODO(rlarocque): This should be updated to inject on-disk state. - // At the time this code was written, there was no support for on-disk - // state so this was the only way to inject a data_type_state into - // the |type_processor_|. - Start(); - OnInitialSyncDone(); -} - -void ModelTypeProcessorImplTest::Start() { - type_processor_->Start(base::Bind(&ModelTypeProcessorImplTest::StartDone, - base::Unretained(this))); -} - -void ModelTypeProcessorImplTest::Stop() { - type_processor_->Stop(); - mock_queue_ = NULL; - mock_queue_ptr_.reset(); -} - -void ModelTypeProcessorImplTest::Disable() { - type_processor_->Disable(); - mock_queue_ = NULL; - mock_queue_ptr_.reset(); -} - -void ModelTypeProcessorImplTest::Restart() { - DCHECK(!type_processor_->IsConnected()); - - // Prepare a new MockCommitQueue instance, just as we would - // if this happened in the real world. - mock_queue_ptr_.reset(new MockCommitQueue()); - mock_queue_ = mock_queue_ptr_.get(); - // Restart sync with the new CommitQueue. - Start(); -} - -void ModelTypeProcessorImplTest::StartDone( - /*syncer::SyncError,*/ scoped_ptr<ActivationContext> context) { - // Hand off ownership of |mock_queue_ptr_|, while keeping - // an unsafe pointer to it. This is why we can only connect once. - DCHECK(mock_queue_ptr_); - context->type_processor->OnConnect(mock_queue_ptr_.Pass()); -} - -void ModelTypeProcessorImplTest::WriteItem(const std::string& tag, - const std::string& value) { - const std::string tag_hash = GenerateTagHash(tag); - type_processor_->Put(tag, GenerateSpecifics(tag, value)); -} - -void ModelTypeProcessorImplTest::DeleteItem(const std::string& tag) { - type_processor_->Delete(tag); -} - -void ModelTypeProcessorImplTest::OnInitialSyncDone() { - data_type_state_.initial_sync_done = true; - UpdateResponseDataList empty_update_list; - - type_processor_->OnUpdateReceived(data_type_state_, empty_update_list, - empty_update_list); -} - -void ModelTypeProcessorImplTest::UpdateFromServer(int64 version_offset, - const std::string& tag, - const std::string& value) { - const std::string tag_hash = GenerateTagHash(tag); - UpdateResponseData data = mock_queue_->UpdateFromServer( - version_offset, tag_hash, GenerateSpecifics(tag, value)); - - UpdateResponseDataList list; - list.push_back(data); - type_processor_->OnUpdateReceived(data_type_state_, list, - UpdateResponseDataList()); -} - -void ModelTypeProcessorImplTest::PendingUpdateFromServer( - int64 version_offset, - const std::string& tag, - const std::string& value, - const std::string& key_name) { - const std::string tag_hash = GenerateTagHash(tag); - UpdateResponseData data = mock_queue_->UpdateFromServer( - version_offset, tag_hash, - GenerateEncryptedSpecifics(tag, value, key_name)); - - UpdateResponseDataList list; - list.push_back(data); - type_processor_->OnUpdateReceived(data_type_state_, UpdateResponseDataList(), - list); -} - -void ModelTypeProcessorImplTest::TombstoneFromServer(int64 version_offset, - const std::string& tag) { - // Overwrite the existing server version if this is the new highest version. - std::string tag_hash = GenerateTagHash(tag); - - UpdateResponseData data = - mock_queue_->TombstoneFromServer(version_offset, tag_hash); - - UpdateResponseDataList list; - list.push_back(data); - type_processor_->OnUpdateReceived(data_type_state_, list, - UpdateResponseDataList()); -} - -bool ModelTypeProcessorImplTest::HasPendingUpdate( - const std::string& tag) const { - const std::string client_tag_hash = GenerateTagHash(tag); - const UpdateResponseDataList list = type_processor_->GetPendingUpdates(); - for (UpdateResponseDataList::const_iterator it = list.begin(); - it != list.end(); ++it) { - if (it->client_tag_hash == client_tag_hash) - return true; - } - return false; -} - -UpdateResponseData ModelTypeProcessorImplTest::GetPendingUpdate( - const std::string& tag) const { - DCHECK(HasPendingUpdate(tag)); - const std::string client_tag_hash = GenerateTagHash(tag); - const UpdateResponseDataList list = type_processor_->GetPendingUpdates(); - for (UpdateResponseDataList::const_iterator it = list.begin(); - it != list.end(); ++it) { - if (it->client_tag_hash == client_tag_hash) - return *it; - } - NOTREACHED(); - return UpdateResponseData(); -} - -size_t ModelTypeProcessorImplTest::GetNumPendingUpdates() const { - return type_processor_->GetPendingUpdates().size(); -} - -void ModelTypeProcessorImplTest::SuccessfulCommitResponse( - const CommitRequestData& request_data) { - CommitResponseDataList list; - list.push_back(mock_queue_->SuccessfulCommitResponse(request_data)); - type_processor_->OnCommitCompleted(data_type_state_, list); -} - -void ModelTypeProcessorImplTest::UpdateDesiredEncryptionKey( - const std::string& key_name) { - data_type_state_.encryption_key_name = key_name; - type_processor_->OnUpdateReceived(data_type_state_, UpdateResponseDataList(), - UpdateResponseDataList()); -} - -void ModelTypeProcessorImplTest::SetServerEncryptionKey( - const std::string& key_name) { - mock_queue_->SetServerEncryptionKey(key_name); -} - -std::string ModelTypeProcessorImplTest::GenerateTagHash( - const std::string& tag) { - return syncer::syncable::GenerateSyncableHash(kModelType, tag); -} - -sync_pb::EntitySpecifics ModelTypeProcessorImplTest::GenerateSpecifics( - const std::string& tag, - const std::string& value) { - sync_pb::EntitySpecifics specifics; - specifics.mutable_preference()->set_name(tag); - specifics.mutable_preference()->set_value(value); - return specifics; -} - -// These tests never decrypt anything, so we can get away with faking the -// encryption for now. -sync_pb::EntitySpecifics ModelTypeProcessorImplTest::GenerateEncryptedSpecifics( - const std::string& tag, - const std::string& value, - const std::string& key_name) { - sync_pb::EntitySpecifics specifics; - syncer::AddDefaultFieldValue(kModelType, &specifics); - specifics.mutable_encrypted()->set_key_name(key_name); - specifics.mutable_encrypted()->set_blob("BLOB" + key_name); - return specifics; -} - -size_t ModelTypeProcessorImplTest::GetNumCommitRequestLists() { - return mock_queue_->GetNumCommitRequestLists(); -} - -CommitRequestDataList ModelTypeProcessorImplTest::GetNthCommitRequestList( - size_t n) { - return mock_queue_->GetNthCommitRequestList(n); -} - -bool ModelTypeProcessorImplTest::HasCommitRequestForTag( - const std::string& tag) { - const std::string tag_hash = GenerateTagHash(tag); - return mock_queue_->HasCommitRequestForTagHash(tag_hash); -} - -CommitRequestData ModelTypeProcessorImplTest::GetLatestCommitRequestForTag( - const std::string& tag) { - const std::string tag_hash = GenerateTagHash(tag); - return mock_queue_->GetLatestCommitRequestForTagHash(tag_hash); -} - -// Creates a new item locally. -// Thoroughly tests the data generated by a local item creation. -TEST_F(ModelTypeProcessorImplTest, CreateLocalItem) { - InitializeToReadyState(); - EXPECT_EQ(0U, GetNumCommitRequestLists()); - - WriteItem("tag1", "value1"); - - // Verify the commit request this operation has triggered. - EXPECT_EQ(1U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_data = GetLatestCommitRequestForTag("tag1"); - - EXPECT_TRUE(tag1_data.id.empty()); - EXPECT_EQ(kUncommittedVersion, tag1_data.base_version); - EXPECT_FALSE(tag1_data.ctime.is_null()); - EXPECT_FALSE(tag1_data.mtime.is_null()); - EXPECT_EQ("tag1", tag1_data.non_unique_name); - EXPECT_FALSE(tag1_data.deleted); - EXPECT_EQ("tag1", tag1_data.specifics.preference().name()); - EXPECT_EQ("value1", tag1_data.specifics.preference().value()); -} - -// Creates a new local item then modifies it. -// Thoroughly tests data generated by modification of server-unknown item. -TEST_F(ModelTypeProcessorImplTest, CreateAndModifyLocalItem) { - InitializeToReadyState(); - EXPECT_EQ(0U, GetNumCommitRequestLists()); - - WriteItem("tag1", "value1"); - EXPECT_EQ(1U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v1_data = GetLatestCommitRequestForTag("tag1"); - - WriteItem("tag1", "value2"); - EXPECT_EQ(2U, GetNumCommitRequestLists()); - - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v2_data = GetLatestCommitRequestForTag("tag1"); - - // Test some of the relations between old and new commit requests. - EXPECT_EQ(tag1_v1_data.specifics.preference().value(), "value1"); - EXPECT_GT(tag1_v2_data.sequence_number, tag1_v1_data.sequence_number); - - // Perform a thorough examination of the update-generated request. - EXPECT_TRUE(tag1_v2_data.id.empty()); - EXPECT_EQ(kUncommittedVersion, tag1_v2_data.base_version); - EXPECT_FALSE(tag1_v2_data.ctime.is_null()); - EXPECT_FALSE(tag1_v2_data.mtime.is_null()); - EXPECT_EQ("tag1", tag1_v2_data.non_unique_name); - EXPECT_FALSE(tag1_v2_data.deleted); - EXPECT_EQ("tag1", tag1_v2_data.specifics.preference().name()); - EXPECT_EQ("value2", tag1_v2_data.specifics.preference().value()); -} - -// Deletes an item we've never seen before. -// Should have no effect and not crash. -TEST_F(ModelTypeProcessorImplTest, DeleteUnknown) { - InitializeToReadyState(); - - DeleteItem("tag1"); - EXPECT_EQ(0U, GetNumCommitRequestLists()); -} - -// Creates an item locally then deletes it. -// -// In this test, no commit responses are received, so the deleted item is -// server-unknown as far as the model thread is concerned. That behavior -// is race-dependent; other tests are used to test other races. -TEST_F(ModelTypeProcessorImplTest, DeleteServerUnknown) { - InitializeToReadyState(); - - WriteItem("tag1", "value1"); - EXPECT_EQ(1U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v1_data = GetLatestCommitRequestForTag("tag1"); - - DeleteItem("tag1"); - EXPECT_EQ(2U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v2_data = GetLatestCommitRequestForTag("tag1"); - - EXPECT_GT(tag1_v2_data.sequence_number, tag1_v1_data.sequence_number); - - EXPECT_TRUE(tag1_v2_data.id.empty()); - EXPECT_EQ(kUncommittedVersion, tag1_v2_data.base_version); - EXPECT_TRUE(tag1_v2_data.deleted); -} - -// Creates an item locally then deletes it. -// -// The item is created locally then enqueued for commit. The sync thread -// successfully commits it, but, before the commit response is picked up -// by the model thread, the item is deleted by the model thread. -TEST_F(ModelTypeProcessorImplTest, DeleteServerUnknown_RacyCommitResponse) { - InitializeToReadyState(); - - WriteItem("tag1", "value1"); - EXPECT_EQ(1U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v1_data = GetLatestCommitRequestForTag("tag1"); - - DeleteItem("tag1"); - EXPECT_EQ(2U, GetNumCommitRequestLists()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - - // This commit happened while the deletion was in progress, but the commit - // response didn't arrive on our thread until after the delete was issued to - // the sync thread. It will update some metadata, but won't do much else. - SuccessfulCommitResponse(tag1_v1_data); - - // TODO(rlarocque): Verify the state of the item is correct once we get - // storage hooked up in these tests. For example, verify the item is still - // marked as deleted. -} - -// Creates two different sync items. -// Verifies that the second has no effect on the first. -TEST_F(ModelTypeProcessorImplTest, TwoIndependentItems) { - InitializeToReadyState(); - EXPECT_EQ(0U, GetNumCommitRequestLists()); - - WriteItem("tag1", "value1"); - - // There should be one commit request for this item only. - ASSERT_EQ(1U, GetNumCommitRequestLists()); - EXPECT_EQ(1U, GetNthCommitRequestList(0).size()); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - - WriteItem("tag2", "value2"); - - // The second write should trigger another single-item commit request. - ASSERT_EQ(2U, GetNumCommitRequestLists()); - EXPECT_EQ(1U, GetNthCommitRequestList(1).size()); - ASSERT_TRUE(HasCommitRequestForTag("tag2")); -} - -// Starts the type sync proxy with no local state. -// Verify that it waits until initial sync is complete before requesting -// commits. -TEST_F(ModelTypeProcessorImplTest, NoCommitsUntilInitialSyncDone) { - Start(); - - WriteItem("tag1", "value1"); - EXPECT_EQ(0U, GetNumCommitRequestLists()); - - OnInitialSyncDone(); - EXPECT_EQ(1U, GetNumCommitRequestLists()); - EXPECT_TRUE(HasCommitRequestForTag("tag1")); -} - -// Test proper handling of disconnect and reconnect. -// -// Creates items in various states of commit and verifies they re-attempt to -// commit on reconnect. -TEST_F(ModelTypeProcessorImplTest, Stop) { - InitializeToReadyState(); - - // The first item is fully committed. - WriteItem("tag1", "value1"); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - SuccessfulCommitResponse(GetLatestCommitRequestForTag("tag1")); - - // The second item has a commit request in progress. - WriteItem("tag2", "value2"); - EXPECT_TRUE(HasCommitRequestForTag("tag2")); - - Stop(); - - // The third item is added after stopping. - WriteItem("tag3", "value3"); - - Restart(); - - EXPECT_EQ(1U, GetNumCommitRequestLists()); - EXPECT_EQ(2U, GetNthCommitRequestList(0).size()); - - // The first item was already in sync. - EXPECT_FALSE(HasCommitRequestForTag("tag1")); - - // The second item's commit was interrupted and should be retried. - EXPECT_TRUE(HasCommitRequestForTag("tag2")); - - // The third item's commit was not started until the reconnect. - EXPECT_TRUE(HasCommitRequestForTag("tag3")); -} - -// Test proper handling of disable and re-enable. -// -// Creates items in various states of commit and verifies they re-attempt to -// commit on re-enable. -TEST_F(ModelTypeProcessorImplTest, Disable) { - InitializeToReadyState(); - - // The first item is fully committed. - WriteItem("tag1", "value1"); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - SuccessfulCommitResponse(GetLatestCommitRequestForTag("tag1")); - - // The second item has a commit request in progress. - WriteItem("tag2", "value2"); - EXPECT_TRUE(HasCommitRequestForTag("tag2")); - - Disable(); - - // The third item is added after disable. - WriteItem("tag3", "value3"); - - // Now we re-enable. - Restart(); - - // There should be nothing to commit right away, since we need to - // re-initialize the client state first. - EXPECT_EQ(0U, GetNumCommitRequestLists()); - - // Once we're ready to commit, all three local items should consider - // themselves uncommitted and pending for commit. - OnInitialSyncDone(); - EXPECT_EQ(1U, GetNumCommitRequestLists()); - EXPECT_EQ(3U, GetNthCommitRequestList(0).size()); - EXPECT_TRUE(HasCommitRequestForTag("tag1")); - EXPECT_TRUE(HasCommitRequestForTag("tag2")); - EXPECT_TRUE(HasCommitRequestForTag("tag3")); -} - -// Test receipt of pending updates. -TEST_F(ModelTypeProcessorImplTest, ReceivePendingUpdates) { - InitializeToReadyState(); - - EXPECT_FALSE(HasPendingUpdate("tag1")); - EXPECT_EQ(0U, GetNumPendingUpdates()); - - // Receive a pending update. - PendingUpdateFromServer(5, "tag1", "value1", "key1"); - EXPECT_EQ(1U, GetNumPendingUpdates()); - ASSERT_TRUE(HasPendingUpdate("tag1")); - UpdateResponseData data1 = GetPendingUpdate("tag1"); - EXPECT_EQ(5, data1.response_version); - - // Receive an updated version of a pending update. - // It should overwrite the existing item. - PendingUpdateFromServer(10, "tag1", "value15", "key1"); - EXPECT_EQ(1U, GetNumPendingUpdates()); - ASSERT_TRUE(HasPendingUpdate("tag1")); - UpdateResponseData data2 = GetPendingUpdate("tag1"); - EXPECT_EQ(15, data2.response_version); - - // Receive a stale version of a pending update. - // It should have no effect. - PendingUpdateFromServer(-3, "tag1", "value12", "key1"); - EXPECT_EQ(1U, GetNumPendingUpdates()); - ASSERT_TRUE(HasPendingUpdate("tag1")); - UpdateResponseData data3 = GetPendingUpdate("tag1"); - EXPECT_EQ(15, data3.response_version); -} - -// Test that Disable clears pending update state. -TEST_F(ModelTypeProcessorImplTest, DisableWithPendingUpdates) { - InitializeToReadyState(); - - PendingUpdateFromServer(5, "tag1", "value1", "key1"); - EXPECT_EQ(1U, GetNumPendingUpdates()); - ASSERT_TRUE(HasPendingUpdate("tag1")); - - Disable(); - Restart(); - - EXPECT_EQ(0U, GetNumPendingUpdates()); - EXPECT_FALSE(HasPendingUpdate("tag1")); -} - -// Test that Stop does not clear pending update state. -TEST_F(ModelTypeProcessorImplTest, StopWithPendingUpdates) { - InitializeToReadyState(); - - PendingUpdateFromServer(5, "tag1", "value1", "key1"); - EXPECT_EQ(1U, GetNumPendingUpdates()); - ASSERT_TRUE(HasPendingUpdate("tag1")); - - Stop(); - Restart(); - - EXPECT_EQ(1U, GetNumPendingUpdates()); - EXPECT_TRUE(HasPendingUpdate("tag1")); -} - -// Test re-encrypt everything when desired encryption key changes. -TEST_F(ModelTypeProcessorImplTest, ReEncryptCommitsWithNewKey) { - InitializeToReadyState(); - - // Commit an item. - WriteItem("tag1", "value1"); - ASSERT_TRUE(HasCommitRequestForTag("tag1")); - const CommitRequestData& tag1_v1_data = GetLatestCommitRequestForTag("tag1"); - SuccessfulCommitResponse(tag1_v1_data); - - // Create another item and don't wait for its commit response. - WriteItem("tag2", "value2"); - - ASSERT_EQ(2U, GetNumCommitRequestLists()); - - // Receive notice that the account's desired encryption key has changed. - UpdateDesiredEncryptionKey("k1"); - - // That should trigger a new commit request. - ASSERT_EQ(3U, GetNumCommitRequestLists()); - EXPECT_EQ(2U, GetNthCommitRequestList(2).size()); - - const CommitRequestData& tag1_enc = GetLatestCommitRequestForTag("tag1"); - const CommitRequestData& tag2_enc = GetLatestCommitRequestForTag("tag2"); - - SuccessfulCommitResponse(tag1_enc); - SuccessfulCommitResponse(tag2_enc); - - // And that should be the end of it. - ASSERT_EQ(3U, GetNumCommitRequestLists()); -} - -// Test receipt of updates with new and old keys. -TEST_F(ModelTypeProcessorImplTest, ReEncryptUpdatesWithNewKey) { - InitializeToReadyState(); - - // Receive an unencrpted update. - UpdateFromServer(5, "no_enc", "value1"); - - ASSERT_EQ(0U, GetNumCommitRequestLists()); - - // Set desired encryption key to k2 to force updates to some items. - UpdateDesiredEncryptionKey("k2"); - - ASSERT_EQ(1U, GetNumCommitRequestLists()); - EXPECT_EQ(1U, GetNthCommitRequestList(0).size()); - EXPECT_TRUE(HasCommitRequestForTag("no_enc")); - - // Receive an update that was encrypted with key k1. - SetServerEncryptionKey("k1"); - UpdateFromServer(10, "enc_k1", "value1"); - - // Receipt of updates encrypted with old key also forces a re-encrypt commit. - ASSERT_EQ(2U, GetNumCommitRequestLists()); - EXPECT_EQ(1U, GetNthCommitRequestList(1).size()); - EXPECT_TRUE(HasCommitRequestForTag("enc_k1")); - - // Receive an update that was encrypted with key k2. - SetServerEncryptionKey("k2"); - UpdateFromServer(15, "enc_k2", "value1"); - - // That was the correct key, so no re-encryption is required. - EXPECT_EQ(2U, GetNumCommitRequestLists()); - EXPECT_FALSE(HasCommitRequestForTag("enc_k2")); -} - -} // namespace syncer diff --git a/sync/engine/model_type_worker.cc b/sync/engine/model_type_worker.cc index 2ffb33d..ca6f738 100644 --- a/sync/engine/model_type_worker.cc +++ b/sync/engine/model_type_worker.cc @@ -11,8 +11,8 @@ #include "base/strings/stringprintf.h" #include "sync/engine/commit_contribution.h" #include "sync/engine/entity_tracker.h" -#include "sync/engine/model_type_processor.h" #include "sync/engine/non_blocking_type_commit_contribution.h" +#include "sync/internal_api/public/model_type_processor.h" #include "sync/syncable/syncable_util.h" #include "sync/util/cryptographer.h" #include "sync/util/time.h" diff --git a/sync/engine/model_type_worker_unittest.cc b/sync/engine/model_type_worker_unittest.cc index 87701d1..7662241 100644 --- a/sync/engine/model_type_worker_unittest.cc +++ b/sync/engine/model_type_worker_unittest.cc @@ -6,8 +6,8 @@ #include "base/strings/stringprintf.h" #include "sync/engine/commit_contribution.h" -#include "sync/engine/model_type_processor.h" #include "sync/internal_api/public/base/model_type.h" +#include "sync/internal_api/public/model_type_processor.h" #include "sync/internal_api/public/non_blocking_sync_common.h" #include "sync/protocol/sync.pb.h" #include "sync/sessions/status_controller.h" |