diff options
author | Ben Murdoch <benm@google.com> | 2014-04-16 11:17:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2014-04-16 11:17:03 +0100 |
commit | a02191e04bc25c4935f804f2c080ae28663d096d (patch) | |
tree | 3cf38961650b5734763e473336009287244306ac /sync | |
parent | 8bad47e0f7d0c250a0443923cceb52f4a4abcd40 (diff) | |
download | chromium_org-a02191e04bc25c4935f804f2c080ae28663d096d.tar.gz |
Merge from Chromium at DEPS revision 263965
This commit was generated by merge_to_master.py.
Change-Id: Ia1121eddd985123f160afde6372525c3d25975bf
Diffstat (limited to 'sync')
66 files changed, 701 insertions, 654 deletions
diff --git a/sync/PRESUBMIT.py b/sync/PRESUBMIT.py index 80e88922f9..f82e95a543 100644 --- a/sync/PRESUBMIT.py +++ b/sync/PRESUBMIT.py @@ -13,6 +13,6 @@ def GetPreferredTryMasters(project, change): 'tryserver.chromium': { 'linux_chromium_rel': set(['defaulttests']), 'mac_chromium_rel': set(['defaulttests']), - 'win_rel': set(['sync_integration_tests']), + 'win_chromium_rel': set(['defaulttests']), } } diff --git a/sync/api/attachments/attachment_service_proxy.cc b/sync/api/attachments/attachment_service_proxy.cc index 065f467b54..b95a41faa3 100644 --- a/sync/api/attachments/attachment_service_proxy.cc +++ b/sync/api/attachments/attachment_service_proxy.cc @@ -36,16 +36,26 @@ void ProxyDropCallback( } // namespace -AttachmentServiceProxy::AttachmentServiceProxy() {} +AttachmentServiceProxy::AttachmentServiceProxy() { +} AttachmentServiceProxy::AttachmentServiceProxy( const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, - base::WeakPtr<syncer::AttachmentService> wrapped) - : wrapped_task_runner_(wrapped_task_runner), wrapped_(wrapped) { + const base::WeakPtr<syncer::AttachmentService>& wrapped) + : wrapped_task_runner_(wrapped_task_runner), core_(new Core(wrapped)) { DCHECK(wrapped_task_runner_); } -AttachmentServiceProxy::~AttachmentServiceProxy() {} +AttachmentServiceProxy::AttachmentServiceProxy( + const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, + const scoped_refptr<Core>& core) + : wrapped_task_runner_(wrapped_task_runner), core_(core) { + DCHECK(wrapped_task_runner_); + DCHECK(core_); +} + +AttachmentServiceProxy::~AttachmentServiceProxy() { +} void AttachmentServiceProxy::GetOrDownloadAttachments( const AttachmentIdList& attachment_ids, @@ -56,7 +66,7 @@ void AttachmentServiceProxy::GetOrDownloadAttachments( wrapped_task_runner_->PostTask( FROM_HERE, base::Bind(&AttachmentService::GetOrDownloadAttachments, - wrapped_, + core_, attachment_ids, proxy_callback)); } @@ -69,7 +79,7 @@ void AttachmentServiceProxy::DropAttachments( &ProxyDropCallback, base::MessageLoopProxy::current(), callback); wrapped_task_runner_->PostTask(FROM_HERE, base::Bind(&AttachmentService::DropAttachments, - wrapped_, + core_, attachment_ids, proxy_callback)); } @@ -78,14 +88,14 @@ void AttachmentServiceProxy::OnSyncDataAdd(const SyncData& sync_data) { DCHECK(wrapped_task_runner_); wrapped_task_runner_->PostTask( FROM_HERE, - base::Bind(&AttachmentService::OnSyncDataAdd, wrapped_, sync_data)); + base::Bind(&AttachmentService::OnSyncDataAdd, core_, sync_data)); } void AttachmentServiceProxy::OnSyncDataDelete(const SyncData& sync_data) { DCHECK(wrapped_task_runner_); wrapped_task_runner_->PostTask( FROM_HERE, - base::Bind(&AttachmentService::OnSyncDataDelete, wrapped_, sync_data)); + base::Bind(&AttachmentService::OnSyncDataDelete, core_, sync_data)); } void AttachmentServiceProxy::OnSyncDataUpdate( @@ -95,9 +105,58 @@ void AttachmentServiceProxy::OnSyncDataUpdate( wrapped_task_runner_->PostTask( FROM_HERE, base::Bind(&AttachmentService::OnSyncDataUpdate, - wrapped_, + core_, old_attachment_ids, updated_sync_data)); } +AttachmentServiceProxy::Core::Core( + const base::WeakPtr<syncer::AttachmentService>& wrapped) + : wrapped_(wrapped) { +} + +AttachmentServiceProxy::Core::~Core() { +} + +void AttachmentServiceProxy::Core::GetOrDownloadAttachments( + const AttachmentIdList& attachment_ids, + const GetOrDownloadCallback& callback) { + if (!wrapped_) { + return; + } + wrapped_->GetOrDownloadAttachments(attachment_ids, callback); +} + +void AttachmentServiceProxy::Core::DropAttachments( + const AttachmentIdList& attachment_ids, + const DropCallback& callback) { + if (!wrapped_) { + return; + } + wrapped_->DropAttachments(attachment_ids, callback); +} + +void AttachmentServiceProxy::Core::OnSyncDataAdd(const SyncData& sync_data) { + if (!wrapped_) { + return; + } + wrapped_->OnSyncDataAdd(sync_data); +} + +void AttachmentServiceProxy::Core::OnSyncDataDelete(const SyncData& sync_data) { + if (!wrapped_) { + return; + } + wrapped_->OnSyncDataDelete(sync_data); +} + +void AttachmentServiceProxy::Core::OnSyncDataUpdate( + const AttachmentIdList& old_attachment_ids, + const SyncData& updated_sync_data) { + if (!wrapped_) { + return; + } + wrapped_->OnSyncDataUpdate(old_attachment_ids, updated_sync_data); +} + } // namespace syncer diff --git a/sync/api/attachments/attachment_service_proxy.h b/sync/api/attachments/attachment_service_proxy.h index 5bec1b3206..70856255cf 100644 --- a/sync/api/attachments/attachment_service_proxy.h +++ b/sync/api/attachments/attachment_service_proxy.h @@ -20,7 +20,8 @@ namespace syncer { class SyncData; // AttachmentServiceProxy wraps an AttachmentService allowing multiple threads -// to share the wrapped AttachmentService. +// to share the wrapped AttachmentService and invoke its methods in the +// appropriate thread. // // Callbacks passed to methods on this class will be invoked in the same thread // from which the method was called. @@ -29,10 +30,10 @@ class SyncData; // holds a WeakPtr to the wrapped object. Once the the wrapped object is // destroyed, method calls on this object will be no-ops. // -// Users of this class should take care to destroy the wrapped object on the -// correct thread (wrapped_task_runner). +// Users of this class should take care to destroy the wrapped object on the +// correct thread (wrapped_task_runner). // -// This class is thread-safe. +// This class is thread-safe and is designed to be passed by const-ref. class SYNC_EXPORT AttachmentServiceProxy : public AttachmentService { public: // Default copy and assignment are welcome. @@ -42,16 +43,19 @@ class SYNC_EXPORT AttachmentServiceProxy : public AttachmentService { // Construct an AttachmentServiceProxy that forwards calls to |wrapped| on the // |wrapped_task_runner| thread. + // + // Note, this object does not own |wrapped|. When |wrapped| is destroyed, + // calls to this object become no-ops. AttachmentServiceProxy( const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, - base::WeakPtr<syncer::AttachmentService> wrapped); + const base::WeakPtr<syncer::AttachmentService>& wrapped); virtual ~AttachmentServiceProxy(); // AttachmentService implementation. - virtual void GetOrDownloadAttachments(const AttachmentIdList& attachment_ids, - const GetOrDownloadCallback& callback) - OVERRIDE; + virtual void GetOrDownloadAttachments( + const AttachmentIdList& attachment_ids, + const GetOrDownloadCallback& callback) OVERRIDE; virtual void DropAttachments(const AttachmentIdList& attachment_ids, const DropCallback& callback) OVERRIDE; virtual void OnSyncDataAdd(const SyncData& sync_data) OVERRIDE; @@ -59,10 +63,55 @@ class SYNC_EXPORT AttachmentServiceProxy : public AttachmentService { virtual void OnSyncDataUpdate(const AttachmentIdList& old_attachment_ids, const SyncData& updated_sync_data) OVERRIDE; + protected: + // Core does the work of proxying calls to AttachmentService methods from one + // thread to another so AttachmentServiceProxy can be an easy-to-use, + // non-ref-counted A ref-counted class. + // + // Callback from AttachmentService are proxied back using free functions + // defined in the .cc file (ProxyFooCallback functions). + // + // Core is ref-counted because we want to allow AttachmentServiceProxy to be + // copy-constructable while allowing for different implementations of Core + // (e.g. one type of core might own the wrapped AttachmentService). + // + // Calls to objects of this class become no-ops once its wrapped object is + // destroyed. + class SYNC_EXPORT Core : public AttachmentService, + public base::RefCountedThreadSafe<Core> { + public: + // Construct an AttachmentServiceProxyCore that forwards calls to |wrapped|. + Core(const base::WeakPtr<syncer::AttachmentService>& wrapped); + + // AttachmentService implementation. + virtual void GetOrDownloadAttachments( + const AttachmentIdList& attachment_ids, + const GetOrDownloadCallback& callback) OVERRIDE; + virtual void DropAttachments(const AttachmentIdList& attachment_ids, + const DropCallback& callback) OVERRIDE; + virtual void OnSyncDataAdd(const SyncData& sync_data) OVERRIDE; + virtual void OnSyncDataDelete(const SyncData& sync_data) OVERRIDE; + virtual void OnSyncDataUpdate(const AttachmentIdList& old_attachment_ids, + const SyncData& updated_sync_data) OVERRIDE; + + protected: + friend class base::RefCountedThreadSafe<Core>; + virtual ~Core(); + + private: + base::WeakPtr<AttachmentService> wrapped_; + + DISALLOW_COPY_AND_ASSIGN(Core); + }; + + // Used in tests to create an AttachmentServiceProxy with a custom Core. + AttachmentServiceProxy( + const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, + const scoped_refptr<Core>& core); + private: scoped_refptr<base::SequencedTaskRunner> wrapped_task_runner_; - // wrapped_ must only be dereferenced on the wrapped_task_runner_ thread. - base::WeakPtr<AttachmentService> wrapped_; + scoped_refptr<Core> core_; }; } // namespace syncer diff --git a/sync/api/attachments/attachment_service_proxy_for_test.cc b/sync/api/attachments/attachment_service_proxy_for_test.cc new file mode 100644 index 0000000000..7f9f873b28 --- /dev/null +++ b/sync/api/attachments/attachment_service_proxy_for_test.cc @@ -0,0 +1,52 @@ +// 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/api/attachments/attachment_service_proxy_for_test.h" + +#include "base/message_loop/message_loop_proxy.h" +#include "sync/api/attachments/fake_attachment_service.h" + +namespace syncer { + +AttachmentServiceProxyForTest::OwningCore::OwningCore( + scoped_ptr<AttachmentService> wrapped, + scoped_ptr<base::WeakPtrFactory<AttachmentService> > weak_ptr_factory) + : Core(weak_ptr_factory->GetWeakPtr()), + wrapped_(wrapped.Pass()), + weak_ptr_factory_(weak_ptr_factory.Pass()) { + DCHECK(wrapped_); +} + +AttachmentServiceProxyForTest::OwningCore::~OwningCore() { +} + +// Static. +AttachmentServiceProxy AttachmentServiceProxyForTest::Create() { + scoped_ptr<AttachmentService> wrapped(FakeAttachmentService::CreateForTest()); + // This class's base class, AttachmentServiceProxy, must be initialized with a + // WeakPtr to an AttachmentService. Because the base class ctor must be + // invoked before any of this class's members are initialized, we create the + // WeakPtrFactory here and pass it to the ctor so that it may initialize its + // base class and own the WeakPtrFactory. + // + // We must pass by scoped_ptr because WeakPtrFactory has no copy constructor. + scoped_ptr<base::WeakPtrFactory<AttachmentService> > weak_ptr_factory( + new base::WeakPtrFactory<AttachmentService>(wrapped.get())); + + scoped_refptr<Core> core_for_test( + new OwningCore(wrapped.Pass(), weak_ptr_factory.Pass())); + return AttachmentServiceProxyForTest(base::MessageLoopProxy::current(), + core_for_test); +} + +AttachmentServiceProxyForTest::~AttachmentServiceProxyForTest() { +} + +AttachmentServiceProxyForTest::AttachmentServiceProxyForTest( + const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, + const scoped_refptr<Core>& core) + : AttachmentServiceProxy(wrapped_task_runner, core) { +} + +} // namespace syncer diff --git a/sync/api/attachments/attachment_service_proxy_for_test.h b/sync/api/attachments/attachment_service_proxy_for_test.h new file mode 100644 index 0000000000..916e788d74 --- /dev/null +++ b/sync/api/attachments/attachment_service_proxy_for_test.h @@ -0,0 +1,50 @@ +// 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_API_ATTACHMENTS_ATTACHMENT_SERVICE_PROXY_FOR_TEST_H_ +#define SYNC_API_ATTACHMENTS_ATTACHMENT_SERVICE_PROXY_FOR_TEST_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "sync/api/attachments/attachment_service_proxy.h" +#include "sync/base/sync_export.h" + +namespace syncer { + +// An self-contained AttachmentServiceProxy to reduce boilerplate code in tests. +// +// Constructs and owns an AttachmentService suitable for use in tests. Assumes +// the current thread has a MessageLoop. +class SYNC_EXPORT AttachmentServiceProxyForTest + : public AttachmentServiceProxy { + public: + static AttachmentServiceProxy Create(); + virtual ~AttachmentServiceProxyForTest(); + + private: + // A Core that owns the wrapped AttachmentService. + class OwningCore : public AttachmentServiceProxy::Core { + public: + OwningCore( + scoped_ptr<AttachmentService>, + scoped_ptr<base::WeakPtrFactory<AttachmentService> > weak_ptr_factory); + + private: + scoped_ptr<AttachmentService> wrapped_; + // WeakPtrFactory for wrapped_. See Create() for why this is a scoped_ptr. + scoped_ptr<base::WeakPtrFactory<AttachmentService> > weak_ptr_factory_; + + virtual ~OwningCore(); + + DISALLOW_COPY_AND_ASSIGN(OwningCore); + }; + + AttachmentServiceProxyForTest( + const scoped_refptr<base::SequencedTaskRunner>& wrapped_task_runner, + const scoped_refptr<Core>& core); +}; + +} // namespace syncer + +#endif // SYNC_API_ATTACHMENTS_ATTACHMENT_SERVICE_PROXY_FOR_TEST_H_ diff --git a/sync/api/sync_change_unittest.cc b/sync/api/sync_change_unittest.cc index 5f937ab7c9..a09776ed80 100644 --- a/sync/api/sync_change_unittest.cc +++ b/sync/api/sync_change_unittest.cc @@ -7,8 +7,11 @@ #include <string> #include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" #include "base/time/time.h" #include "base/values.h" +#include "sync/api/attachments/attachment_id.h" +#include "sync/api/attachments/attachment_service_proxy_for_test.h" #include "sync/protocol/preference_specifics.pb.h" #include "sync/protocol/proto_value_conversions.h" #include "sync/protocol/sync.pb.h" @@ -21,7 +24,10 @@ typedef std::vector<SyncChange> SyncChangeList; namespace { -typedef testing::Test SyncChangeTest; +class SyncChangeTest : public testing::Test { + private: + base::MessageLoop message_loop; +}; TEST_F(SyncChangeTest, LocalDelete) { SyncChange::SyncChangeType change_type = SyncChange::ACTION_DELETE; @@ -82,28 +88,43 @@ TEST_F(SyncChangeTest, SyncerChanges) { sync_pb::PreferenceSpecifics* pref_specifics = update_specifics.mutable_preference(); pref_specifics->set_name("update"); - change_list.push_back(SyncChange( - FROM_HERE, - SyncChange::ACTION_UPDATE, - SyncData::CreateRemoteData(1, update_specifics, base::Time()))); + change_list.push_back( + SyncChange(FROM_HERE, + SyncChange::ACTION_UPDATE, + SyncData::CreateRemoteData( + 1, + update_specifics, + base::Time(), + syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create()))); // Create an add. sync_pb::EntitySpecifics add_specifics; pref_specifics = add_specifics.mutable_preference(); pref_specifics->set_name("add"); - change_list.push_back(SyncChange( - FROM_HERE, - SyncChange::ACTION_ADD, - SyncData::CreateRemoteData(2, add_specifics, base::Time()))); + change_list.push_back( + SyncChange(FROM_HERE, + SyncChange::ACTION_ADD, + SyncData::CreateRemoteData( + 2, + add_specifics, + base::Time(), + syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create()))); // Create a delete. sync_pb::EntitySpecifics delete_specifics; pref_specifics = delete_specifics.mutable_preference(); pref_specifics->set_name("add"); - change_list.push_back(SyncChange( - FROM_HERE, - SyncChange::ACTION_DELETE, - SyncData::CreateRemoteData(3, delete_specifics, base::Time()))); + change_list.push_back( + SyncChange(FROM_HERE, + SyncChange::ACTION_DELETE, + SyncData::CreateRemoteData( + 3, + delete_specifics, + base::Time(), + syncer::AttachmentIdList(), + syncer::AttachmentServiceProxyForTest::Create()))); ASSERT_EQ(3U, change_list.size()); diff --git a/sync/api/sync_data.cc b/sync/api/sync_data.cc index 5d84941227..fa48ea5edc 100644 --- a/sync/api/sync_data.cc +++ b/sync/api/sync_data.cc @@ -143,17 +143,6 @@ SyncData SyncData::CreateRemoteData( id, &entity, &attachments, modification_time, attachment_service); } -// Static. -SyncData SyncData::CreateRemoteData(int64 id, - const sync_pb::EntitySpecifics& specifics, - const base::Time& modification_time) { - return CreateRemoteData(id, - specifics, - modification_time, - AttachmentIdList(), - AttachmentServiceProxy()); -} - bool SyncData::IsValid() const { return is_valid_; } const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const { diff --git a/sync/api/sync_data.h b/sync/api/sync_data.h index 717b1e1175..bb99b74457 100644 --- a/sync/api/sync_data.h +++ b/sync/api/sync_data.h @@ -11,6 +11,7 @@ #include "base/basictypes.h" #include "base/callback.h" +#include "base/memory/ref_counted.h" #include "base/stl_util.h" #include "base/time/time.h" #include "sync/api/attachments/attachment.h" @@ -64,18 +65,12 @@ class SYNC_EXPORT SyncData { const AttachmentList& attachments); // Helper method for creating SyncData objects originating from the syncer. - // - // TODO(maniscalco): Replace all calls to 3-arg CreateRemoteData with calls to - // the 5-arg version (bug 353296). static SyncData CreateRemoteData( int64 id, const sync_pb::EntitySpecifics& specifics, const base::Time& last_modified_time, const AttachmentIdList& attachment_ids, const syncer::AttachmentServiceProxy& attachment_service); - static SyncData CreateRemoteData(int64 id, - const sync_pb::EntitySpecifics& specifics, - const base::Time& last_modified_time); // Whether this SyncData holds valid data. The only way to have a SyncData // without valid data is to use the default constructor. diff --git a/sync/api/sync_data_unittest.cc b/sync/api/sync_data_unittest.cc index 7ca39bf221..4eab286a95 100644 --- a/sync/api/sync_data_unittest.cc +++ b/sync/api/sync_data_unittest.cc @@ -120,16 +120,6 @@ TEST_F(SyncDataTest, CreateRemoteData) { EXPECT_TRUE(data.GetAttachmentIds().empty()); } -TEST_F(SyncDataTest, CreateRemoteData_WithoutAttachmentService) { - specifics.mutable_preference(); - SyncData data = SyncData::CreateRemoteData(kId, specifics, kLastModifiedTime); - EXPECT_TRUE(data.IsValid()); - EXPECT_FALSE(data.IsLocal()); - EXPECT_EQ(kId, SyncDataRemote(data).GetId()); - EXPECT_EQ(kLastModifiedTime, SyncDataRemote(data).GetModifiedTime()); - EXPECT_TRUE(data.GetSpecifics().has_preference()); -} - // TODO(maniscalco): Add test cases that verify GetLocalAttachmentsForUpload and // DropAttachments calls are passed through to the underlying AttachmentService. diff --git a/sync/engine/all_status.cc b/sync/engine/all_status.cc index d73f206eae..3deda48fb2 100644 --- a/sync/engine/all_status.cc +++ b/sync/engine/all_status.cc @@ -71,22 +71,6 @@ SyncStatus AllStatus::CalcSyncing(const SyncCycleEvent &event) const { snapshot.model_neutral_state().num_local_overwrites; status.num_server_overwrites_total += snapshot.model_neutral_state().num_server_overwrites; - if (snapshot.model_neutral_state().num_updates_downloaded_total == 0) { - ++status.empty_get_updates; - } else { - ++status.nonempty_get_updates; - } - if (snapshot.model_neutral_state().num_successful_commits == 0) { - ++status.sync_cycles_without_commits; - } else { - ++status.sync_cycles_with_commits; - } - if (snapshot.model_neutral_state().num_successful_commits == 0 && - snapshot.model_neutral_state().num_updates_downloaded_total == 0) { - ++status.useless_sync_cycles; - } else { - ++status.useful_sync_cycles; - } } return status; } diff --git a/sync/engine/backoff_delay_provider.cc b/sync/engine/backoff_delay_provider.cc index f8e2750876..bff3fd61c6 100644 --- a/sync/engine/backoff_delay_provider.cc +++ b/sync/engine/backoff_delay_provider.cc @@ -97,6 +97,11 @@ TimeDelta BackoffDelayProvider::GetInitialDelay( return short_initial_backoff_; } + // If a datatype decides the GetUpdates must be retried (e.g. because the + // context has been updated since the request), use the short delay. + if (state.last_download_updates_result == DATATYPE_TRIGGERED_RETRY) + return short_initial_backoff_; + // When the server tells us we have a conflict, then we should download the // latest updates so we can see the conflict ourselves, resolve it locally, // then try again to commit. Running another sync cycle will do all these @@ -105,9 +110,8 @@ TimeDelta BackoffDelayProvider::GetInitialDelay( // TODO(sync): We shouldn't need to handle this in BackoffDelayProvider. // There should be a way to deal with protocol errors before we get to this // point. - if (state.commit_result == SERVER_RETURN_CONFLICT) { + if (state.commit_result == SERVER_RETURN_CONFLICT) return short_initial_backoff_; - } return default_initial_backoff_; } diff --git a/sync/engine/backoff_delay_provider_unittest.cc b/sync/engine/backoff_delay_provider_unittest.cc index 1bf17cbd5f..2e5818665f 100644 --- a/sync/engine/backoff_delay_provider_unittest.cc +++ b/sync/engine/backoff_delay_provider_unittest.cc @@ -57,6 +57,10 @@ TEST_F(BackoffDelayProviderTest, GetInitialDelay) { EXPECT_EQ(kInitialBackoffRetrySeconds, delay->GetInitialDelay(state).InSeconds()); + state.last_download_updates_result = DATATYPE_TRIGGERED_RETRY; + EXPECT_EQ(kInitialBackoffImmediateRetrySeconds, + delay->GetInitialDelay(state).InSeconds()); + state.last_download_updates_result = SYNCER_OK; // Note that updating credentials triggers a canary job, trumping // the initial delay, but in theory we still expect this function to treat @@ -99,6 +103,10 @@ TEST_F(BackoffDelayProviderTest, GetInitialDelayWithOverride) { EXPECT_EQ(kInitialBackoffShortRetrySeconds, delay->GetInitialDelay(state).InSeconds()); + state.last_download_updates_result = DATATYPE_TRIGGERED_RETRY; + EXPECT_EQ(kInitialBackoffImmediateRetrySeconds, + delay->GetInitialDelay(state).InSeconds()); + state.last_download_updates_result = SYNCER_OK; // Note that updating credentials triggers a canary job, trumping // the initial delay, but in theory we still expect this function to treat diff --git a/sync/engine/directory_update_handler.cc b/sync/engine/directory_update_handler.cc index 55095202fa..72cdf121d2 100644 --- a/sync/engine/directory_update_handler.cc +++ b/sync/engine/directory_update_handler.cc @@ -37,19 +37,12 @@ void DirectoryUpdateHandler::GetDataTypeContext( dir_->GetDataTypeContext(&trans, type_, context); } -void DirectoryUpdateHandler::ProcessGetUpdatesResponse( +SyncerError DirectoryUpdateHandler::ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, sessions::StatusController* status) { syncable::ModelNeutralWriteTransaction trans(FROM_HERE, SYNCER, dir_); - UpdateSyncEntities(&trans, applicable_updates, status); - - if (IsValidProgressMarker(progress_marker)) { - ExpireEntriesIfNeeded(&trans, progress_marker); - UpdateProgressMarker(progress_marker); - } - if (mutated_context.has_context()) { sync_pb::DataTypeContext local_context; dir_->GetDataTypeContext(&trans, type_, &local_context); @@ -61,8 +54,21 @@ void DirectoryUpdateHandler::ProcessGetUpdatesResponse( local_context.context() != mutated_context.context()) { dir_->SetDataTypeContext(&trans, type_, mutated_context); // TODO(zea): trigger the datatype's UpdateDataTypeContext method. + } else if (mutated_context.version() < local_context.version()) { + // A GetUpdates using the old context was in progress when the context was + // set. Fail this get updates cycle, to force a retry. + DVLOG(1) << "GU Context conflict detected, forcing GU retry."; + return DATATYPE_TRIGGERED_RETRY; } } + + UpdateSyncEntities(&trans, applicable_updates, status); + + if (IsValidProgressMarker(progress_marker)) { + ExpireEntriesIfNeeded(&trans, progress_marker); + UpdateProgressMarker(progress_marker); + } + return SYNCER_OK; } void DirectoryUpdateHandler::ApplyUpdates(sessions::StatusController* status) { diff --git a/sync/engine/directory_update_handler.h b/sync/engine/directory_update_handler.h index 74c7046771..ef5052dee6 100644 --- a/sync/engine/directory_update_handler.h +++ b/sync/engine/directory_update_handler.h @@ -52,7 +52,7 @@ class SYNC_EXPORT_PRIVATE DirectoryUpdateHandler : public UpdateHandler { sync_pb::DataTypeProgressMarker* progress_marker) const OVERRIDE; virtual void GetDataTypeContext(sync_pb::DataTypeContext* context) const OVERRIDE; - virtual void ProcessGetUpdatesResponse( + virtual SyncerError ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, diff --git a/sync/engine/directory_update_handler_unittest.cc b/sync/engine/directory_update_handler_unittest.cc index 6d1b35a199..ec8cc35f39 100644 --- a/sync/engine/directory_update_handler_unittest.cc +++ b/sync/engine/directory_update_handler_unittest.cc @@ -195,14 +195,14 @@ TEST_F(DirectoryUpdateHandlerProcessUpdateTest, // Test the receipt of a non-bookmark item. TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ReceiveNonBookmarkItem) { - DirectoryUpdateHandler handler(dir(), PREFERENCES, ui_worker()); + DirectoryUpdateHandler handler(dir(), AUTOFILL, ui_worker()); sync_pb::GetUpdatesResponse gu_response; sessions::StatusController status; std::string root = syncable::GetNullId().GetServerId(); syncable::Id server_id = syncable::Id::CreateFromServerId("xyz"); scoped_ptr<sync_pb::SyncEntity> e = - CreateUpdate(SyncableIdToProto(server_id), root, PREFERENCES); + CreateUpdate(SyncableIdToProto(server_id), root, AUTOFILL); e->set_server_defined_unique_tag("9PGRuKdX5sHyGMB17CvYTXuC43I="); // Add it to the applicable updates list. @@ -283,7 +283,9 @@ TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) { updates.push_back(e2.get()); // Process and apply updates. - handler.ProcessGetUpdatesResponse(progress, context, updates, &status); + EXPECT_EQ( + SYNCER_OK, + handler.ProcessGetUpdatesResponse(progress, context, updates, &status)); handler.ApplyUpdates(&status); // Verify none is deleted because they are unapplied during GC. @@ -293,14 +295,93 @@ TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) { // Process and apply again. Old entry is deleted but not root. progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 20); - handler.ProcessGetUpdatesResponse( - progress, context, SyncEntityList(), &status); + EXPECT_EQ(SYNCER_OK, + handler.ProcessGetUpdatesResponse( + progress, context, SyncEntityList(), &status)); handler.ApplyUpdates(&status); EXPECT_TRUE(EntryExists(type_root->id_string())); EXPECT_FALSE(EntryExists(e1->id_string())); EXPECT_TRUE(EntryExists(e2->id_string())); } +TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) { + DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker()); + sessions::StatusController status; + int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS); + + sync_pb::DataTypeProgressMarker progress; + progress.set_data_type_id( + GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); + progress.set_token("token"); + + sync_pb::DataTypeContext old_context; + old_context.set_version(1); + old_context.set_context("data"); + old_context.set_data_type_id(field_number); + + scoped_ptr<sync_pb::SyncEntity> type_root = + CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("root")), + syncable::GetNullId().GetServerId(), + SYNCED_NOTIFICATIONS); + type_root->set_server_defined_unique_tag( + ModelTypeToRootTag(SYNCED_NOTIFICATIONS)); + type_root->set_folder(true); + scoped_ptr<sync_pb::SyncEntity> e1 = + CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e1")), + type_root->id_string(), + SYNCED_NOTIFICATIONS); + + SyncEntityList updates; + updates.push_back(type_root.get()); + updates.push_back(e1.get()); + + // The first response should be processed fine. + EXPECT_EQ(SYNCER_OK, + handler.ProcessGetUpdatesResponse( + progress, old_context, updates, &status)); + handler.ApplyUpdates(&status); + + EXPECT_TRUE(EntryExists(type_root->id_string())); + EXPECT_TRUE(EntryExists(e1->id_string())); + + { + sync_pb::DataTypeContext dir_context; + syncable::ReadTransaction trans(FROM_HERE, dir()); + trans.directory()->GetDataTypeContext( + &trans, SYNCED_NOTIFICATIONS, &dir_context); + EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); + } + + sync_pb::DataTypeContext new_context; + new_context.set_version(0); + new_context.set_context("old"); + new_context.set_data_type_id(field_number); + + scoped_ptr<sync_pb::SyncEntity> e2 = + CreateUpdate(SyncableIdToProto(syncable::Id::CreateFromServerId("e2")), + type_root->id_string(), + SYNCED_NOTIFICATIONS); + updates.clear(); + updates.push_back(e2.get()); + + // The second response, with an old context version, should result in an + // error and the updates should be dropped. + EXPECT_EQ(DATATYPE_TRIGGERED_RETRY, + handler.ProcessGetUpdatesResponse( + progress, new_context, updates, &status)); + handler.ApplyUpdates(&status); + + EXPECT_FALSE(EntryExists(e2->id_string())); + + { + sync_pb::DataTypeContext dir_context; + syncable::ReadTransaction trans(FROM_HERE, dir()); + trans.directory()->GetDataTypeContext( + &trans, SYNCED_NOTIFICATIONS, &dir_context); + EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); + } +} + // A test harness for tests that focus on applying updates. // // Update application is performed when we want to take updates that were diff --git a/sync/engine/get_updates_processor.cc b/sync/engine/get_updates_processor.cc index d0aa9b989f..8666e0a25c 100644 --- a/sync/engine/get_updates_processor.cc +++ b/sync/engine/get_updates_processor.cc @@ -284,9 +284,10 @@ SyncerError GetUpdatesProcessor::ProcessResponse( } status->set_num_server_changes_remaining(gu_response.changes_remaining()); - if (!ProcessGetUpdatesResponse(request_types, gu_response, status)) { - return SERVER_RESPONSE_VALIDATION_FAILED; - } + syncer::SyncerError result = + ProcessGetUpdatesResponse(request_types, gu_response, status); + if (result != syncer::SYNCER_OK) + return result; if (gu_response.changes_remaining() == 0) { return SYNCER_OK; @@ -295,7 +296,7 @@ SyncerError GetUpdatesProcessor::ProcessResponse( } } -bool GetUpdatesProcessor::ProcessGetUpdatesResponse( +syncer::SyncerError GetUpdatesProcessor::ProcessGetUpdatesResponse( ModelTypeSet gu_types, const sync_pb::GetUpdatesResponse& gu_response, sessions::StatusController* status_controller) { @@ -309,7 +310,7 @@ bool GetUpdatesProcessor::ProcessGetUpdatesResponse( &progress_index_by_type); if (gu_types.Size() != progress_index_by_type.size()) { NOTREACHED() << "Missing progress markers in GetUpdates response."; - return false; + return syncer::SERVER_RESPONSE_VALIDATION_FAILED; } TypeToIndexMap context_by_type; @@ -334,11 +335,14 @@ bool GetUpdatesProcessor::ProcessGetUpdatesResponse( context.CopyFrom(gu_response.context_mutations(context_iter->second)); if (update_handler_iter != update_handler_map_->end()) { - update_handler_iter->second->ProcessGetUpdatesResponse( - gu_response.new_progress_marker(progress_marker_iter->second), - context, - updates_iter->second, - status_controller); + syncer::SyncerError result = + update_handler_iter->second->ProcessGetUpdatesResponse( + gu_response.new_progress_marker(progress_marker_iter->second), + context, + updates_iter->second, + status_controller); + if (result != syncer::SYNCER_OK) + return result; } else { DLOG(WARNING) << "Ignoring received updates of a type we can't handle. " @@ -349,7 +353,7 @@ bool GetUpdatesProcessor::ProcessGetUpdatesResponse( DCHECK(progress_marker_iter == progress_index_by_type.end() && updates_iter == updates_by_type.end()); - return true; + return syncer::SYNCER_OK; } void GetUpdatesProcessor::ApplyUpdates( diff --git a/sync/engine/get_updates_processor.h b/sync/engine/get_updates_processor.h index 40a5c3aca7..e66d100927 100644 --- a/sync/engine/get_updates_processor.h +++ b/sync/engine/get_updates_processor.h @@ -82,7 +82,7 @@ class SYNC_EXPORT_PRIVATE GetUpdatesProcessor { sessions::StatusController* status); // Processes a GetUpdates responses for each type. - bool ProcessGetUpdatesResponse( + syncer::SyncerError ProcessGetUpdatesResponse( ModelTypeSet gu_types, const sync_pb::GetUpdatesResponse& gu_response, sessions::StatusController* status_controller); diff --git a/sync/engine/non_blocking_type_processor_core.cc b/sync/engine/non_blocking_type_processor_core.cc index c1bc60ad0d..ea0f91889a 100644 --- a/sync/engine/non_blocking_type_processor_core.cc +++ b/sync/engine/non_blocking_type_processor_core.cc @@ -44,7 +44,7 @@ void NonBlockingTypeProcessorCore::GetDataTypeContext( context->Clear(); } -void NonBlockingTypeProcessorCore::ProcessGetUpdatesResponse( +SyncerError NonBlockingTypeProcessorCore::ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, @@ -53,6 +53,7 @@ void NonBlockingTypeProcessorCore::ProcessGetUpdatesResponse( // TODO(rlarocque): Implement this properly. crbug.com/351005. DVLOG(1) << "Processing updates response for: " << ModelTypeToString(type_); progress_marker_ = progress_marker; + return SYNCER_OK; } void NonBlockingTypeProcessorCore::ApplyUpdates( diff --git a/sync/engine/non_blocking_type_processor_core.h b/sync/engine/non_blocking_type_processor_core.h index 0c1cc1c0bf..c9cec886b4 100644 --- a/sync/engine/non_blocking_type_processor_core.h +++ b/sync/engine/non_blocking_type_processor_core.h @@ -59,7 +59,7 @@ class SYNC_EXPORT NonBlockingTypeProcessorCore sync_pb::DataTypeProgressMarker* progress_marker) const OVERRIDE; virtual void GetDataTypeContext(sync_pb::DataTypeContext* context) const OVERRIDE; - virtual void ProcessGetUpdatesResponse( + virtual SyncerError ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, diff --git a/sync/engine/update_handler.h b/sync/engine/update_handler.h index 29bdbc9dee..e4c9abc24b 100644 --- a/sync/engine/update_handler.h +++ b/sync/engine/update_handler.h @@ -8,6 +8,7 @@ #include <vector> #include "sync/base/sync_export.h" +#include "sync/internal_api/public/util/syncer_error.h" namespace sync_pb { class DataTypeContext; @@ -49,7 +50,10 @@ class SYNC_EXPORT_PRIVATE UpdateHandler { // // In this context, "applicable_updates" means the set of updates belonging to // this type. - virtual void ProcessGetUpdatesResponse( + // + // Returns SYNCER_OK if the all data was processed successfully, a syncer + // error otherwise. + virtual SyncerError ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, diff --git a/sync/internal_api/js_sync_encryption_handler_observer.cc b/sync/internal_api/js_sync_encryption_handler_observer.cc index d6bd50ecf5..a000fa674f 100644 --- a/sync/internal_api/js_sync_encryption_handler_observer.cc +++ b/sync/internal_api/js_sync_encryption_handler_observer.cc @@ -12,7 +12,6 @@ #include "base/values.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/util/sync_string_conversions.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" #include "sync/js/js_event_handler.h" #include "sync/util/cryptographer.h" diff --git a/sync/internal_api/js_sync_manager_observer.cc b/sync/internal_api/js_sync_manager_observer.cc index b5f84524ad..1361c8b8fe 100644 --- a/sync/internal_api/js_sync_manager_observer.cc +++ b/sync/internal_api/js_sync_manager_observer.cc @@ -14,7 +14,6 @@ #include "sync/internal_api/public/change_record.h" #include "sync/internal_api/public/sessions/sync_session_snapshot.h" #include "sync/internal_api/public/util/sync_string_conversions.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" #include "sync/js/js_event_handler.h" diff --git a/sync/internal_api/non_blocking_type_processor.cc b/sync/internal_api/non_blocking_type_processor.cc index 242c42f257..8fd0d2775d 100644 --- a/sync/internal_api/non_blocking_type_processor.cc +++ b/sync/internal_api/non_blocking_type_processor.cc @@ -6,6 +6,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "sync/engine/non_blocking_type_processor_core.h" +#include "sync/internal_api/public/sync_core_proxy.h" namespace syncer { @@ -25,9 +26,9 @@ ModelType NonBlockingTypeProcessor::GetModelType() const { return type_; } -void NonBlockingTypeProcessor::Enable(SyncCoreProxy core_proxy_) { +void NonBlockingTypeProcessor::Enable(SyncCoreProxy* core_proxy) { DCHECK(CalledOnValidThread()); - core_proxy_.ConnectTypeToCore( + core_proxy->ConnectTypeToCore( GetModelType(), AsWeakPtr()); } diff --git a/sync/internal_api/public/engine/sync_status.cc b/sync/internal_api/public/engine/sync_status.cc index 6291b290a4..b1687e31d5 100644 --- a/sync/internal_api/public/engine/sync_status.cc +++ b/sync/internal_api/public/engine/sync_status.cc @@ -21,12 +21,6 @@ SyncStatus::SyncStatus() num_commits_total(0), num_local_overwrites_total(0), num_server_overwrites_total(0), - nonempty_get_updates(0), - empty_get_updates(0), - sync_cycles_with_commits(0), - sync_cycles_without_commits(0), - useless_sync_cycles(0), - useful_sync_cycles(0), nudge_source_notification(0), nudge_source_local(0), nudge_source_local_refresh(0), diff --git a/sync/internal_api/public/engine/sync_status.h b/sync/internal_api/public/engine/sync_status.h index 124dac6b0e..c32be00b41 100644 --- a/sync/internal_api/public/engine/sync_status.h +++ b/sync/internal_api/public/engine/sync_status.h @@ -65,18 +65,6 @@ struct SYNC_EXPORT SyncStatus { int num_local_overwrites_total; int num_server_overwrites_total; - // Count of empty and non empty getupdates; - int nonempty_get_updates; - int empty_get_updates; - - // Count of sync cycles that successfully committed items; - int sync_cycles_with_commits; - int sync_cycles_without_commits; - - // Count of useless and useful syncs we perform. - int useless_sync_cycles; - int useful_sync_cycles; - // Nudge counts for each possible source int nudge_source_notification; int nudge_source_local; diff --git a/sync/internal_api/public/non_blocking_type_processor.h b/sync/internal_api/public/non_blocking_type_processor.h index a9079d5a03..0198c2763e 100644 --- a/sync/internal_api/public/non_blocking_type_processor.h +++ b/sync/internal_api/public/non_blocking_type_processor.h @@ -5,17 +5,16 @@ #ifndef SYNC_ENGINE_NON_BLOCKING_TYPE_PROCESSOR_H_ #define SYNC_ENGINE_NON_BLOCKING_TYPE_PROCESSOR_H_ -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" #include "base/threading/non_thread_safe.h" #include "sync/base/sync_export.h" #include "sync/internal_api/public/base/model_type.h" -#include "sync/internal_api/public/sync_core_proxy.h" #include "sync/protocol/sync.pb.h" namespace syncer { +class SyncCoreProxy; class NonBlockingTypeProcessorCore; // A sync component embedded on the synced type's thread that helps to handle @@ -32,7 +31,7 @@ class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessor : base::NonThreadSafe { ModelType GetModelType() const; // Starts the handshake with the sync thread. - void Enable(SyncCoreProxy core_proxy_); + void Enable(SyncCoreProxy* core_proxy); // Severs all ties to the sync thread. // Another call to Enable() can be used to re-establish this connection. diff --git a/sync/internal_api/public/read_transaction.h b/sync/internal_api/public/read_transaction.h index 02e2633d8e..3a3dc8d8ac 100644 --- a/sync/internal_api/public/read_transaction.h +++ b/sync/internal_api/public/read_transaction.h @@ -13,6 +13,10 @@ namespace tracked_objects { class Location; } // namespace tracked_objects +namespace sync_pb { +class DataTypeContext; +} + namespace syncer { struct UserShare; @@ -35,7 +39,11 @@ class SYNC_EXPORT ReadTransaction : public BaseTransaction { // Return |transaction_version| of |type| stored in sync directory's // persisted info. - int64 GetModelVersion(ModelType type); + int64 GetModelVersion(ModelType type) const; + + // Fills |context| with the datatype context associated with |type|. + void GetDataTypeContext(ModelType type, + sync_pb::DataTypeContext* context) const; private: void* operator new(size_t size); // Transaction is meant for stack use only. diff --git a/sync/internal_api/public/sync_core_proxy.h b/sync/internal_api/public/sync_core_proxy.h index dd5a4ac08b..8750b421b6 100644 --- a/sync/internal_api/public/sync_core_proxy.h +++ b/sync/internal_api/public/sync_core_proxy.h @@ -5,49 +5,30 @@ #ifndef SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_PROXY_H_ #define SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_PROXY_H_ -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" -#include "sync/base/sync_export.h" #include "sync/internal_api/public/base/model_type.h" namespace syncer { -class SyncCore; class NonBlockingTypeProcessor; -// Encapsulates a reference to the sync core and the thread it's running on. -// Used by sync's data types to connect with the sync core. +// Interface for the datatype integration logic from non-sync threads. // -// It is epxected that this object will be copied to and used on many different -// threads. It is small and safe to pass by value. +// See SyncCoreProxyImpl for an actual implementation. class SYNC_EXPORT_PRIVATE SyncCoreProxy { public: - SyncCoreProxy( - scoped_refptr<base::SequencedTaskRunner> sync_task_runner, - base::WeakPtr<SyncCore> sync_core); - ~SyncCoreProxy(); + SyncCoreProxy(); + virtual ~SyncCoreProxy(); // Attempts to connect a non-blocking type to the sync core. // - // This may fail under some unusual circumstances, like shutdown. Due to the - // nature of WeakPtrs and cross-thread communication, the caller will be - // unable to distinguish a slow success from failure. - // // Must be called from the thread where the data type lives. - void ConnectTypeToCore( + virtual void ConnectTypeToCore( syncer::ModelType type, - base::WeakPtr<NonBlockingTypeProcessor> type_processor); - - // Constructs and returns a useless instance of this object. - static SyncCoreProxy GetInvalidSyncCoreProxyForTest(); - - private: - // A SequencedTaskRunner representing the thread where the SyncCore lives. - scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; + base::WeakPtr<NonBlockingTypeProcessor> type_processor) = 0; - // The SyncCore this object is wrapping. - base::WeakPtr<SyncCore> sync_core_; + // Creates a clone of this SyncCoreProxy. + virtual scoped_ptr<SyncCoreProxy> Clone() = 0; }; } // namespace syncer diff --git a/sync/internal_api/public/sync_manager.h b/sync/internal_api/public/sync_manager.h index d10b9989eb..74885864a0 100644 --- a/sync/internal_api/public/sync_manager.h +++ b/sync/internal_api/public/sync_manager.h @@ -22,6 +22,7 @@ #include "sync/internal_api/public/engine/model_safe_worker.h" #include "sync/internal_api/public/engine/sync_status.h" #include "sync/internal_api/public/events/protocol_event.h" +#include "sync/internal_api/public/sync_core_proxy.h" #include "sync/internal_api/public/sync_encryption_handler.h" #include "sync/internal_api/public/util/report_unrecoverable_error_function.h" #include "sync/internal_api/public/util/unrecoverable_error_handler.h" @@ -44,7 +45,7 @@ class HttpPostProviderFactory; class InternalComponentsFactory; class JsBackend; class JsEventHandler; -class SyncCore; +class SyncCoreProxy; class SyncEncryptionHandler; class ProtocolEvent; class SyncScheduler; @@ -334,7 +335,7 @@ class SYNC_EXPORT SyncManager : public syncer::InvalidationHandler { virtual UserShare* GetUserShare() = 0; // Returns an instance of the main interface for non-blocking sync types. - virtual base::WeakPtr<syncer::SyncCore> GetSyncCore() = 0; + virtual syncer::SyncCoreProxy* GetSyncCoreProxy() = 0; // Returns the cache_guid of the currently open database. // Requires that the SyncManager be initialized. diff --git a/sync/internal_api/public/test/fake_sync_manager.h b/sync/internal_api/public/test/fake_sync_manager.h index fae4c8eab6..55e4f3b3c5 100644 --- a/sync/internal_api/public/test/fake_sync_manager.h +++ b/sync/internal_api/public/test/fake_sync_manager.h @@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "sync/internal_api/public/sync_manager.h" +#include "sync/internal_api/public/test/null_sync_core_proxy.h" #include "sync/internal_api/public/test/test_user_share.h" #include "sync/notifier/invalidator_registrar.h" @@ -119,7 +120,7 @@ class FakeSyncManager : public SyncManager { virtual void SaveChanges() OVERRIDE; virtual void ShutdownOnSyncThread() OVERRIDE; virtual UserShare* GetUserShare() OVERRIDE; - virtual base::WeakPtr<syncer::SyncCore> GetSyncCore() OVERRIDE; + virtual syncer::SyncCoreProxy* GetSyncCoreProxy() OVERRIDE; virtual const std::string cache_guid() OVERRIDE; virtual bool ReceivedExperiment(Experiments* experiments) OVERRIDE; virtual bool HasUnsyncedItems() OVERRIDE; @@ -163,6 +164,8 @@ class FakeSyncManager : public SyncManager { TestUserShare test_user_share_; + NullSyncCoreProxy null_sync_core_proxy_; + DISALLOW_COPY_AND_ASSIGN(FakeSyncManager); }; diff --git a/sync/internal_api/public/test/null_sync_core_proxy.h b/sync/internal_api/public/test/null_sync_core_proxy.h new file mode 100644 index 0000000000..410a9927b3 --- /dev/null +++ b/sync/internal_api/public/test/null_sync_core_proxy.h @@ -0,0 +1,31 @@ +// 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_INTERNAL_API_PUBLIC_TEST_NULL_SYNC_CORE_PROXY_H_ +#define SYNC_INTERNAL_API_PUBLIC_TEST_NULL_SYNC_CORE_PROXY_H_ + +#include "sync/internal_api/public/sync_core_proxy.h" +#include "base/memory/weak_ptr.h" + +namespace syncer { + +class NonBlockingTypeProcessor; + +// A non-functional implementation of SyncCoreProxy. +// +// It supports Clone(), but not much else. Useful for testing. +class NullSyncCoreProxy : public SyncCoreProxy { + public: + NullSyncCoreProxy(); + virtual ~NullSyncCoreProxy(); + + virtual void ConnectTypeToCore( + syncer::ModelType type, + base::WeakPtr<NonBlockingTypeProcessor> processor) OVERRIDE; + virtual scoped_ptr<SyncCoreProxy> Clone() OVERRIDE; +}; + +} // namespace syncer + +#endif // SYNC_INTERNAL_API_PUBLIC_TEST_NULL_SYNC_CORE_PROXY_H_ diff --git a/sync/internal_api/public/util/syncer_error.cc b/sync/internal_api/public/util/syncer_error.cc index e7cb66fbf4..81805d22aa 100644 --- a/sync/internal_api/public/util/syncer_error.cc +++ b/sync/internal_api/public/util/syncer_error.cc @@ -28,6 +28,7 @@ const char* GetSyncerErrorString(SyncerError value) { ENUM_CASE(SERVER_RESPONSE_VALIDATION_FAILED); ENUM_CASE(SERVER_RETURN_DISABLED_BY_ADMIN); ENUM_CASE(SERVER_MORE_TO_DOWNLOAD); + ENUM_CASE(DATATYPE_TRIGGERED_RETRY); ENUM_CASE(SYNCER_OK); } NOTREACHED(); diff --git a/sync/internal_api/public/util/syncer_error.h b/sync/internal_api/public/util/syncer_error.h index 02da22c193..1a5ec79301 100644 --- a/sync/internal_api/public/util/syncer_error.h +++ b/sync/internal_api/public/util/syncer_error.h @@ -31,6 +31,9 @@ enum SYNC_EXPORT_PRIVATE SyncerError { SERVER_RESPONSE_VALIDATION_FAILED, SERVER_RETURN_DISABLED_BY_ADMIN, + // A datatype decided the sync cycle needed to be performed again. + DATATYPE_TRIGGERED_RETRY, + SERVER_MORE_TO_DOWNLOAD, SYNCER_OK diff --git a/sync/internal_api/read_transaction.cc b/sync/internal_api/read_transaction.cc index 81e53400d2..ebc56ecc40 100644 --- a/sync/internal_api/read_transaction.cc +++ b/sync/internal_api/read_transaction.cc @@ -36,8 +36,15 @@ syncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const { return transaction_; } -int64 ReadTransaction::GetModelVersion(ModelType type) { +int64 ReadTransaction::GetModelVersion(ModelType type) const { return transaction_->directory()->GetTransactionVersion(type); } +void ReadTransaction::GetDataTypeContext( + ModelType type, + sync_pb::DataTypeContext* context) const { + return transaction_->directory()->GetDataTypeContext( + transaction_, type, context); +} + } // namespace syncer diff --git a/sync/internal_api/sync_core_proxy.cc b/sync/internal_api/sync_core_proxy.cc index 5ba3135f6d..4e6f7f6573 100644 --- a/sync/internal_api/sync_core_proxy.cc +++ b/sync/internal_api/sync_core_proxy.cc @@ -4,37 +4,10 @@ #include "sync/internal_api/public/sync_core_proxy.h" -#include "base/bind.h" -#include "base/location.h" -#include "base/message_loop/message_loop_proxy.h" -#include "sync/internal_api/sync_core.h" - namespace syncer { -SyncCoreProxy::SyncCoreProxy( - scoped_refptr<base::SequencedTaskRunner> sync_task_runner, - base::WeakPtr<SyncCore> sync_core) - : sync_task_runner_(sync_task_runner), - sync_core_(sync_core) {} +SyncCoreProxy::SyncCoreProxy() {} SyncCoreProxy::~SyncCoreProxy() {} -void SyncCoreProxy::ConnectTypeToCore( - ModelType type, - base::WeakPtr<NonBlockingTypeProcessor> type_processor) { - VLOG(1) << "ConnectSyncTypeToCore: " << ModelTypeToString(type); - sync_task_runner_->PostTask( - FROM_HERE, - base::Bind(&SyncCore::ConnectSyncTypeToCore, - sync_core_, - type, - base::MessageLoopProxy::current(), - type_processor)); -} - -SyncCoreProxy SyncCoreProxy::GetInvalidSyncCoreProxyForTest() { - return SyncCoreProxy(scoped_refptr<base::SequencedTaskRunner>(), - base::WeakPtr<SyncCore>()); -} - } // namespace syncer diff --git a/sync/internal_api/sync_core_proxy_impl.cc b/sync/internal_api/sync_core_proxy_impl.cc new file mode 100644 index 0000000000..bfdd1462aa --- /dev/null +++ b/sync/internal_api/sync_core_proxy_impl.cc @@ -0,0 +1,40 @@ +// 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/internal_api/sync_core_proxy_impl.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/message_loop/message_loop_proxy.h" +#include "sync/internal_api/sync_core.h" + +namespace syncer { + +SyncCoreProxyImpl::SyncCoreProxyImpl( + scoped_refptr<base::SequencedTaskRunner> sync_task_runner, + base::WeakPtr<SyncCore> sync_core) + : sync_task_runner_(sync_task_runner), + sync_core_(sync_core) {} + +SyncCoreProxyImpl::~SyncCoreProxyImpl() {} + +void SyncCoreProxyImpl::ConnectTypeToCore( + ModelType type, + base::WeakPtr<NonBlockingTypeProcessor> type_processor) { + VLOG(1) << "ConnectTypeToCore: " << ModelTypeToString(type); + sync_task_runner_->PostTask( + FROM_HERE, + base::Bind(&SyncCore::ConnectSyncTypeToCore, + sync_core_, + type, + base::MessageLoopProxy::current(), + type_processor)); +} + +scoped_ptr<SyncCoreProxy> SyncCoreProxyImpl::Clone() { + return scoped_ptr<SyncCoreProxy>( + new SyncCoreProxyImpl(sync_task_runner_, sync_core_)); +} + +} // namespace syncer diff --git a/sync/internal_api/sync_core_proxy_impl.h b/sync/internal_api/sync_core_proxy_impl.h new file mode 100644 index 0000000000..7ccb26a722 --- /dev/null +++ b/sync/internal_api/sync_core_proxy_impl.h @@ -0,0 +1,55 @@ +// 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_INTERNAL_API_SYNC_CORE_PROXY_IMPL_H_ +#define SYNC_INTERNAL_API_SYNC_CORE_PROXY_IMPL_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "sync/base/sync_export.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/internal_api/public/sync_core_proxy.h" + +namespace syncer { + +class SyncCore; +class NonBlockingTypeProcessor; + +// Encapsulates a reference to the sync core and the thread it's running on. +// Used by sync's data types to connect with the sync core. +// +// It is epxected that this object will be copied to and used on many different +// threads. It is small and safe to pass by value. +class SYNC_EXPORT_PRIVATE SyncCoreProxyImpl : public SyncCoreProxy { + public: + SyncCoreProxyImpl( + scoped_refptr<base::SequencedTaskRunner> sync_task_runner, + base::WeakPtr<SyncCore> sync_core); + virtual ~SyncCoreProxyImpl(); + + // Attempts to connect a non-blocking type to the sync core. + // + // This may fail under some unusual circumstances, like shutdown. Due to the + // nature of WeakPtrs and cross-thread communication, the caller will be + // unable to distinguish a slow success from failure. + // + // Must be called from the thread where the data type lives. + virtual void ConnectTypeToCore( + syncer::ModelType type, + base::WeakPtr<NonBlockingTypeProcessor> type_processor) OVERRIDE; + + virtual scoped_ptr<SyncCoreProxy> Clone() OVERRIDE; + + private: + // A SequencedTaskRunner representing the thread where the SyncCore lives. + scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; + + // The SyncCore this object is wrapping. + base::WeakPtr<SyncCore> sync_core_; +}; + +} // namespace syncer + +#endif // SYNC_INTERNAL_API_SYNC_CORE_PROXY_IMPL_H_ diff --git a/sync/internal_api/sync_core_proxy_unittest.cc b/sync/internal_api/sync_core_proxy_impl_unittest.cc index d6885bfcb4..a3e228c9f4 100644 --- a/sync/internal_api/sync_core_proxy_unittest.cc +++ b/sync/internal_api/sync_core_proxy_impl_unittest.cc @@ -8,16 +8,16 @@ #include "base/sequenced_task_runner.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/non_blocking_type_processor.h" -#include "sync/internal_api/public/sync_core_proxy.h" #include "sync/internal_api/sync_core.h" +#include "sync/internal_api/sync_core_proxy_impl.h" #include "sync/sessions/model_type_registry.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { -class SyncCoreProxyTest : public ::testing::Test { +class SyncCoreProxyImplTest : public ::testing::Test { public: - SyncCoreProxyTest() + SyncCoreProxyImplTest() : sync_task_runner_(base::MessageLoopProxy::current()), type_task_runner_(base::MessageLoopProxy::current()), core_(new SyncCore(®istry_)), @@ -31,8 +31,8 @@ class SyncCoreProxyTest : public ::testing::Test { core_.reset(); } - SyncCoreProxy GetProxy() { - return core_proxy_; + SyncCoreProxy* GetProxy() { + return &core_proxy_; } private: @@ -41,11 +41,11 @@ class SyncCoreProxyTest : public ::testing::Test { scoped_refptr<base::SequencedTaskRunner> type_task_runner_; ModelTypeRegistry registry_; scoped_ptr<SyncCore> core_; - SyncCoreProxy core_proxy_; + SyncCoreProxyImpl core_proxy_; }; // Try to connect a type to a SyncCore that has already shut down. -TEST_F(SyncCoreProxyTest, FailToConnect1) { +TEST_F(SyncCoreProxyImplTest, FailToConnect1) { NonBlockingTypeProcessor themes_processor(syncer::THEMES); DisableSync(); themes_processor.Enable(GetProxy()); @@ -56,7 +56,7 @@ TEST_F(SyncCoreProxyTest, FailToConnect1) { } // Try to connect a type to a SyncCore as it shuts down. -TEST_F(SyncCoreProxyTest, FailToConnect2) { +TEST_F(SyncCoreProxyImplTest, FailToConnect2) { NonBlockingTypeProcessor themes_processor(syncer::THEMES); themes_processor.Enable(GetProxy()); DisableSync(); @@ -67,7 +67,7 @@ TEST_F(SyncCoreProxyTest, FailToConnect2) { } // Tests the case where the type's processor shuts down first. -TEST_F(SyncCoreProxyTest, TypeDisconnectsFirst) { +TEST_F(SyncCoreProxyImplTest, TypeDisconnectsFirst) { scoped_ptr<NonBlockingTypeProcessor> themes_processor (new NonBlockingTypeProcessor(syncer::THEMES)); themes_processor->Enable(GetProxy()); @@ -80,7 +80,7 @@ TEST_F(SyncCoreProxyTest, TypeDisconnectsFirst) { } // Tests the case where the sync thread shuts down first. -TEST_F(SyncCoreProxyTest, SyncDisconnectsFirst) { +TEST_F(SyncCoreProxyImplTest, SyncDisconnectsFirst) { scoped_ptr<NonBlockingTypeProcessor> themes_processor (new NonBlockingTypeProcessor(syncer::THEMES)); themes_processor->Enable(GetProxy()); diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc index 94dfc5856d..7658f58184 100644 --- a/sync/internal_api/sync_manager_impl.cc +++ b/sync/internal_api/sync_manager_impl.cc @@ -29,11 +29,13 @@ #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/sync_core_proxy.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/sync_core.h" +#include "sync/internal_api/sync_core_proxy_impl.h" #include "sync/internal_api/syncapi_internal.h" #include "sync/internal_api/syncapi_server_connection_manager.h" #include "sync/notifier/invalidation_util.h" @@ -397,6 +399,14 @@ void SyncManagerImpl::Init( sync_core_.reset(new SyncCore(model_type_registry_.get())); + // Bind the SyncCore WeakPtr to this thread. This helps us crash earlier if + // the pointer is misused in debug mode. + base::WeakPtr<SyncCore> weak_core = sync_core_->AsWeakPtr(); + weak_core.get(); + + sync_core_proxy_.reset( + new SyncCoreProxyImpl(base::MessageLoopProxy::current(), weak_core)); + // Build a SyncSessionContext and store the worker in it. DVLOG(1) << "Sync is bringing up SyncSessionContext."; std::vector<SyncEngineEventListener*> listeners; @@ -941,14 +951,6 @@ void SyncManagerImpl::SetJsEventHandler( js_sync_encryption_handler_observer_.SetJsEventHandler(event_handler); } -// TODO(rlarocque): This function is no longer needed and should be removed. -// See http://crbug.com/357821. -void SyncManagerImpl::ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) { - NOTREACHED(); -} - scoped_ptr<base::ListValue> SyncManagerImpl::GetAllNodesForType( syncer::ModelType type) { DirectoryTypeDebugInfoEmitterMap* emitter_map = @@ -1025,9 +1027,9 @@ UserShare* SyncManagerImpl::GetUserShare() { return &share_; } -base::WeakPtr<syncer::SyncCore> SyncManagerImpl::GetSyncCore() { +syncer::SyncCoreProxy* SyncManagerImpl::GetSyncCoreProxy() { DCHECK(initialized_); - return sync_core_->AsWeakPtr(); + return sync_core_proxy_.get(); } const std::string SyncManagerImpl::cache_guid() { diff --git a/sync/internal_api/sync_manager_impl.h b/sync/internal_api/sync_manager_impl.h index 52d382ed1a..653e48a357 100644 --- a/sync/internal_api/sync_manager_impl.h +++ b/sync/internal_api/sync_manager_impl.h @@ -19,6 +19,7 @@ #include "sync/internal_api/js_sync_encryption_handler_observer.h" #include "sync/internal_api/js_sync_manager_observer.h" #include "sync/internal_api/protocol_event_buffer.h" +#include "sync/internal_api/public/sync_core_proxy.h" #include "sync/internal_api/public/sync_manager.h" #include "sync/internal_api/public/user_share.h" #include "sync/internal_api/sync_encryption_handler_impl.h" @@ -33,6 +34,7 @@ namespace syncer { class ModelTypeRegistry; class SyncAPIServerConnectionManager; +class SyncCore; class WriteNode; class WriteTransaction; @@ -110,7 +112,7 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : virtual void SaveChanges() OVERRIDE; virtual void ShutdownOnSyncThread() OVERRIDE; virtual UserShare* GetUserShare() OVERRIDE; - virtual base::WeakPtr<syncer::SyncCore> GetSyncCore() OVERRIDE; + virtual syncer::SyncCoreProxy* GetSyncCoreProxy() OVERRIDE; virtual const std::string cache_guid() OVERRIDE; virtual bool ReceivedExperiment(Experiments* experiments) OVERRIDE; virtual bool HasUnsyncedItems() OVERRIDE; @@ -156,9 +158,6 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : // JsBackend implementation. virtual void SetJsEventHandler( const WeakHandle<JsEventHandler>& event_handler) OVERRIDE; - virtual void ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) OVERRIDE; // DirectoryChangeDelegate implementation. // This listener is called upon completion of a syncable transaction, and @@ -301,8 +300,9 @@ class SYNC_EXPORT_PRIVATE SyncManagerImpl : // This state changes when entering or exiting a configuration cycle. scoped_ptr<ModelTypeRegistry> model_type_registry_; - // The main interface for non-blocking sync types. + // The main interface for non-blocking sync types and a thread-safe wrapper. scoped_ptr<SyncCore> sync_core_; + scoped_ptr<SyncCoreProxy> sync_core_proxy_; // A container of various bits of information used by the SyncScheduler to // create SyncSessions. Must outlive the SyncScheduler. diff --git a/sync/internal_api/test/fake_sync_manager.cc b/sync/internal_api/test/fake_sync_manager.cc index 9f1abb8c08..c7873a80cc 100644 --- a/sync/internal_api/test/fake_sync_manager.cc +++ b/sync/internal_api/test/fake_sync_manager.cc @@ -218,8 +218,8 @@ UserShare* FakeSyncManager::GetUserShare() { return test_user_share_.user_share(); } -base::WeakPtr<syncer::SyncCore> FakeSyncManager::GetSyncCore() { - return base::WeakPtr<syncer::SyncCore>(); +syncer::SyncCoreProxy* FakeSyncManager::GetSyncCoreProxy() { + return &null_sync_core_proxy_; } const std::string FakeSyncManager::cache_guid() { diff --git a/sync/internal_api/test/null_sync_core_proxy.cc b/sync/internal_api/test/null_sync_core_proxy.cc new file mode 100644 index 0000000000..866e68b33f --- /dev/null +++ b/sync/internal_api/test/null_sync_core_proxy.cc @@ -0,0 +1,23 @@ +// 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/internal_api/public/test/null_sync_core_proxy.h" + +namespace syncer { + +NullSyncCoreProxy::NullSyncCoreProxy() {} + +NullSyncCoreProxy::~NullSyncCoreProxy() {} + +void NullSyncCoreProxy::ConnectTypeToCore( + syncer::ModelType type, + base::WeakPtr<NonBlockingTypeProcessor> processor) { + NOTREACHED() << "NullSyncCoreProxy is not meant to be used"; +} + +scoped_ptr<SyncCoreProxy> NullSyncCoreProxy::Clone() { + return scoped_ptr<SyncCoreProxy>(new NullSyncCoreProxy()); +} + +} // namespace syncer diff --git a/sync/js/README.js b/sync/js/README.js index 0fbfa66bc0..3a99d1e7a3 100644 --- a/sync/js/README.js +++ b/sync/js/README.js @@ -1,48 +1,16 @@ -Overview of chrome://sync-internals ------------------------------------ - -This note explains how chrome://sync-internals (also known as -about:sync) interacts with the sync service/backend. - -Basically, chrome://sync-internals sends messages to the sync backend -and the sync backend sends the reply asynchronously. The sync backend -also asynchronously raises events which chrome://sync-internals listen -to. - -A message and its reply has a name and a list of arguments, which is -basically a wrapper around an immutable ListValue. - -An event has a name and a details object, which is represented by a -JsEventDetails (js_event_details.h) object, which is basically a -wrapper around an immutable DictionaryValue. - -Message/event flow ------------------- - -chrome://sync-internals is represented by SyncInternalsUI -(chrome/browser/ui/webui/sync_internals_ui.h). SyncInternalsUI -interacts with the sync service via a JsController (js_controller.h) -object, which has a ProcessJsMessage() method that just delegates to -an underlying JsBackend instance (js_backend.h). The SyncInternalsUI -object also registers itself (as a JsEventHandler -[js_event_handler.h]) to the JsController object, and any events -raised by the JsBackend are propagated to the JsController and then to -the registered JsEventHandlers. - -The ProcessJsMessage() takes a WeakHandle (weak_handle.h) to a -JsReplyHandler (js_reply_handler.h), which the backend uses to send -replies safely across threads. SyncInternalsUI implements -JsReplyHandler, so it simply passes itself as the reply handler when -it calls ProcessJsMessage() on the JsController. - -The following objects live on the UI thread: - -- SyncInternalsUI (implements JsEventHandler, JsReplyHandler) -- SyncJsController (implements JsController, JsEventHandler) - -The following objects live on the sync thread: - -- SyncManager::SyncInternal (implements JsBackend) - -Of course, none of these objects need to know where the other objects -live, since they interact via WeakHandles. +// 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. + +This framework was once used to implement an asynchronous request/reply +protocol between the chrome://sync-internals page and the sync backend thread. +Much of it has been removed in favor of an ad-hoc system that allows us to +offer better safety guarantees, and to dispatch requests to different threads. + +All that remains are some WeakHandles that allow us to send JsEvents from the +sync backend to about:sync. The SyncInternalsUI implements JsEventHandler in +order to receive these events. The SyncManager implements JsBackend in order +to send them. The SyncJsController acts as an intermediary between them. + +The old framework may still be useful to someone. Feel free to retrieve it +from SVN history if you feel you can make use of it. diff --git a/sync/js/js_arg_list.cc b/sync/js/js_arg_list.cc deleted file mode 100644 index e3317e5f57..0000000000 --- a/sync/js/js_arg_list.cc +++ /dev/null @@ -1,27 +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/js/js_arg_list.h" - -#include "base/json/json_writer.h" - -namespace syncer { - -JsArgList::JsArgList() {} - -JsArgList::JsArgList(base::ListValue* args) : args_(args) {} - -JsArgList::~JsArgList() {} - -const base::ListValue& JsArgList::Get() const { - return args_.Get(); -} - -std::string JsArgList::ToString() const { - std::string str; - base::JSONWriter::Write(&Get(), &str); - return str; -} - -} // namespace syncer diff --git a/sync/js/js_arg_list.h b/sync/js/js_arg_list.h deleted file mode 100644 index 34a0cf6966..0000000000 --- a/sync/js/js_arg_list.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 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. - -#ifndef SYNC_JS_JS_ARG_LIST_H_ -#define SYNC_JS_JS_ARG_LIST_H_ - -// See README.js for design comments. - -#include <string> - -#include "base/values.h" -#include "sync/base/sync_export.h" -#include "sync/internal_api/public/util/immutable.h" - -namespace syncer { - -// A thin wrapper around Immutable<ListValue>. Used for passing -// around argument lists to different threads. -class SYNC_EXPORT JsArgList { - public: - // Uses an empty argument list. - JsArgList(); - - // Takes over the data in |args|, leaving |args| empty. - explicit JsArgList(base::ListValue* args); - - ~JsArgList(); - - const base::ListValue& Get() const; - - std::string ToString() const; - - // Copy constructor and assignment operator welcome. - - private: - typedef Immutable<base::ListValue, HasSwapMemFnByPtr<base::ListValue> > - ImmutableListValue; - ImmutableListValue args_; -}; - -} // namespace syncer - -#endif // SYNC_JS_JS_ARG_LIST_H_ diff --git a/sync/js/js_arg_list_unittest.cc b/sync/js/js_arg_list_unittest.cc deleted file mode 100644 index 2a10286751..0000000000 --- a/sync/js/js_arg_list_unittest.cc +++ /dev/null @@ -1,40 +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/js/js_arg_list.h" - -#include "base/memory/scoped_ptr.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace syncer { -namespace { - -class JsArgListTest : public testing::Test {}; - -TEST_F(JsArgListTest, EmptyList) { - JsArgList arg_list; - EXPECT_TRUE(arg_list.Get().empty()); - EXPECT_EQ("[]", arg_list.ToString()); -} - -TEST_F(JsArgListTest, FromList) { - scoped_ptr<base::ListValue> list(new base::ListValue()); - list->Append(new base::FundamentalValue(false)); - list->Append(new base::FundamentalValue(5)); - base::DictionaryValue* dict = new base::DictionaryValue(); - list->Append(dict); - dict->SetString("foo", "bar"); - dict->Set("baz", new base::ListValue()); - - scoped_ptr<base::ListValue> list_copy(list->DeepCopy()); - - JsArgList arg_list(list.get()); - - // |arg_list| should take over |list|'s data. - EXPECT_TRUE(list->empty()); - EXPECT_TRUE(arg_list.Get().Equals(list_copy.get())); -} - -} // namespace -} // namespace syncer diff --git a/sync/js/js_backend.h b/sync/js/js_backend.h index e39600a8bc..a0ef317ba6 100644 --- a/sync/js/js_backend.h +++ b/sync/js/js_backend.h @@ -13,9 +13,7 @@ namespace syncer { -class JsArgList; class JsEventHandler; -class JsReplyHandler; template <typename T> class WeakHandle; // Interface representing the backend of chrome://sync-internals. A @@ -27,12 +25,6 @@ class SYNC_EXPORT_PRIVATE JsBackend { virtual void SetJsEventHandler( const WeakHandle<JsEventHandler>& event_handler) = 0; - // Processes the given message and replies via the given handler, if - // initialized. - virtual void ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) = 0; - protected: virtual ~JsBackend() {} }; diff --git a/sync/js/js_controller.h b/sync/js/js_controller.h index 08432bf004..482c8c1eba 100644 --- a/sync/js/js_controller.h +++ b/sync/js/js_controller.h @@ -13,9 +13,7 @@ namespace syncer { -class JsArgList; class JsEventHandler; -class JsReplyHandler; template <typename T> class WeakHandle; // An interface for objects that JsEventHandlers directly interact @@ -36,12 +34,6 @@ class SYNC_EXPORT JsController { // immediately stop receiving any JS events. virtual void RemoveJsEventHandler(JsEventHandler* event_handler) = 0; - // Processes a JS message. The reply (if any) will be sent to - // |reply_handler| if it is initialized. - virtual void ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) = 0; - protected: virtual ~JsController() {} }; diff --git a/sync/js/js_reply_handler.h b/sync/js/js_reply_handler.h deleted file mode 100644 index 3026b7b4da..0000000000 --- a/sync/js/js_reply_handler.h +++ /dev/null @@ -1,29 +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. - -#ifndef SYNC_JS_JS_REPLY_HANDLER_H_ -#define SYNC_JS_JS_REPLY_HANDLER_H_ - -// See README.js for design comments. - -#include <string> - -namespace syncer { - -class JsArgList; - -// An interface for objects that handle Javascript message replies -// (e.g., WebUIs). -class JsReplyHandler { - public: - virtual void HandleJsReply( - const std::string& name, const JsArgList& args) = 0; - - protected: - virtual ~JsReplyHandler() {} -}; - -} // namespace syncer - -#endif // SYNC_JS_JS_REPLY_HANDLER_H_ diff --git a/sync/js/js_test_util.cc b/sync/js/js_test_util.cc index 7d40289ef9..f596136a76 100644 --- a/sync/js/js_test_util.cc +++ b/sync/js/js_test_util.cc @@ -6,51 +6,16 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" namespace syncer { -void PrintTo(const JsArgList& args, ::std::ostream* os) { - *os << args.ToString(); -} - void PrintTo(const JsEventDetails& details, ::std::ostream* os) { *os << details.ToString(); } namespace { -// Matcher implementation for HasArgs(). -class HasArgsMatcher - : public ::testing::MatcherInterface<const JsArgList&> { - public: - explicit HasArgsMatcher(const JsArgList& expected_args) - : expected_args_(expected_args) {} - - virtual ~HasArgsMatcher() {} - - virtual bool MatchAndExplain( - const JsArgList& args, - ::testing::MatchResultListener* listener) const { - // No need to annotate listener since we already define PrintTo(). - return args.Get().Equals(&expected_args_.Get()); - } - - virtual void DescribeTo(::std::ostream* os) const { - *os << "has args " << expected_args_.ToString(); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "doesn't have args " << expected_args_.ToString(); - } - - private: - const JsArgList expected_args_; - - DISALLOW_COPY_AND_ASSIGN(HasArgsMatcher); -}; - // Matcher implementation for HasDetails(). class HasDetailsMatcher : public ::testing::MatcherInterface<const JsEventDetails&> { @@ -83,10 +48,6 @@ class HasDetailsMatcher } // namespace -::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args) { - return ::testing::MakeMatcher(new HasArgsMatcher(expected_args)); -} - ::testing::Matcher<const JsEventDetails&> HasDetails( const JsEventDetails& expected_details) { return ::testing::MakeMatcher(new HasDetailsMatcher(expected_details)); @@ -119,13 +80,5 @@ WeakHandle<JsEventHandler> MockJsEventHandler::AsWeakHandle() { MockJsEventHandler::~MockJsEventHandler() {} -MockJsReplyHandler::MockJsReplyHandler() {} - -MockJsReplyHandler::~MockJsReplyHandler() {} - -WeakHandle<JsReplyHandler> MockJsReplyHandler::AsWeakHandle() { - return MakeWeakHandle(AsWeakPtr()); -} - } // namespace syncer diff --git a/sync/js/js_test_util.h b/sync/js/js_test_util.h index 8f9824837f..b5ae4e8d78 100644 --- a/sync/js/js_test_util.h +++ b/sync/js/js_test_util.h @@ -13,7 +13,6 @@ #include "sync/js/js_backend.h" #include "sync/js/js_controller.h" #include "sync/js/js_event_handler.h" -#include "sync/js/js_reply_handler.h" #include "testing/gmock/include/gmock/gmock.h" namespace base { @@ -23,18 +22,11 @@ class ListValue; namespace syncer { -class JsArgList; class JsEventDetails; // Defined for googletest. Equivalent to "*os << args.ToString()". -void PrintTo(const JsArgList& args, ::std::ostream* os); void PrintTo(const JsEventDetails& details, ::std::ostream* os); -// A gmock matcher for JsArgList. Use like: -// -// EXPECT_CALL(mock, HandleJsReply("foo", HasArgs(expected_args))); -::testing::Matcher<const JsArgList&> HasArgs(const JsArgList& expected_args); - // A gmock matcher for JsEventDetails. Use like: // // EXPECT_CALL(mock, HandleJsEvent("foo", HasArgs(expected_details))); @@ -56,8 +48,6 @@ class MockJsBackend : public JsBackend, WeakHandle<JsBackend> AsWeakHandle(); MOCK_METHOD1(SetJsEventHandler, void(const WeakHandle<JsEventHandler>&)); - MOCK_METHOD3(ProcessJsMessage, void(const ::std::string&, const JsArgList&, - const WeakHandle<JsReplyHandler>&)); }; class MockJsController : public JsController, @@ -68,9 +58,6 @@ class MockJsController : public JsController, MOCK_METHOD1(AddJsEventHandler, void(JsEventHandler*)); MOCK_METHOD1(RemoveJsEventHandler, void(JsEventHandler*)); - MOCK_METHOD3(ProcessJsMessage, - void(const ::std::string&, const JsArgList&, - const WeakHandle<JsReplyHandler>&)); }; class MockJsEventHandler @@ -86,19 +73,6 @@ class MockJsEventHandler void(const ::std::string&, const JsEventDetails&)); }; -class MockJsReplyHandler - : public JsReplyHandler, - public base::SupportsWeakPtr<MockJsReplyHandler> { - public: - MockJsReplyHandler(); - virtual ~MockJsReplyHandler(); - - WeakHandle<JsReplyHandler> AsWeakHandle(); - - MOCK_METHOD2(HandleJsReply, - void(const ::std::string&, const JsArgList&)); -}; - } // namespace syncer #endif // SYNC_JS_JS_TEST_UTIL_H_ diff --git a/sync/js/sync_js_controller.cc b/sync/js/sync_js_controller.cc index 4d3148fdd0..42199d2997 100644 --- a/sync/js/sync_js_controller.cc +++ b/sync/js/sync_js_controller.cc @@ -10,13 +10,6 @@ namespace syncer { -SyncJsController::PendingJsMessage::PendingJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) - : name(name), args(args), reply_handler(reply_handler) {} - -SyncJsController::PendingJsMessage::~PendingJsMessage() {} - SyncJsController::SyncJsController() {} SyncJsController::~SyncJsController() { @@ -37,28 +30,6 @@ void SyncJsController::AttachJsBackend( const WeakHandle<JsBackend>& js_backend) { js_backend_ = js_backend; UpdateBackendEventHandler(); - - if (js_backend_.IsInitialized()) { - // Process any queued messages. - for (PendingJsMessageList::const_iterator it = - pending_js_messages_.begin(); - it != pending_js_messages_.end(); ++it) { - js_backend_.Call(FROM_HERE, &JsBackend::ProcessJsMessage, - it->name, it->args, it->reply_handler); - } - } -} - -void SyncJsController::ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) { - if (js_backend_.IsInitialized()) { - js_backend_.Call(FROM_HERE, &JsBackend::ProcessJsMessage, - name, args, reply_handler); - } else { - pending_js_messages_.push_back( - PendingJsMessage(name, args, reply_handler)); - } } void SyncJsController::HandleJsEvent(const std::string& name, diff --git a/sync/js/sync_js_controller.h b/sync/js/sync_js_controller.h index 0e259f860a..f0bb423b8c 100644 --- a/sync/js/sync_js_controller.h +++ b/sync/js/sync_js_controller.h @@ -14,7 +14,6 @@ #include "base/observer_list.h" #include "sync/base/sync_export.h" #include "sync/internal_api/public/util/weak_handle.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_controller.h" #include "sync/js/js_event_handler.h" @@ -39,39 +38,18 @@ class SYNC_EXPORT SyncJsController // JsController implementation. virtual void AddJsEventHandler(JsEventHandler* event_handler) OVERRIDE; virtual void RemoveJsEventHandler(JsEventHandler* event_handler) OVERRIDE; - // Queues up any messages that are sent when there is no attached - // initialized backend. - virtual void ProcessJsMessage( - const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler) OVERRIDE; // JsEventHandler implementation. virtual void HandleJsEvent(const std::string& name, const JsEventDetails& details) OVERRIDE; private: - // A struct used to hold the arguments to ProcessJsMessage() for - // future invocation. - struct PendingJsMessage { - std::string name; - JsArgList args; - WeakHandle<JsReplyHandler> reply_handler; - - PendingJsMessage(const std::string& name, const JsArgList& args, - const WeakHandle<JsReplyHandler>& reply_handler); - - ~PendingJsMessage(); - }; - - typedef std::vector<PendingJsMessage> PendingJsMessageList; - // Sets |js_backend_|'s event handler depending on how many // underlying event handlers we have. void UpdateBackendEventHandler(); WeakHandle<JsBackend> js_backend_; ObserverList<JsEventHandler> js_event_handlers_; - PendingJsMessageList pending_js_messages_; DISALLOW_COPY_AND_ASSIGN(SyncJsController); }; diff --git a/sync/js/sync_js_controller_unittest.cc b/sync/js/sync_js_controller_unittest.cc index eca617c2d4..f6f1abf85b 100644 --- a/sync/js/sync_js_controller_unittest.cc +++ b/sync/js/sync_js_controller_unittest.cc @@ -6,7 +6,6 @@ #include "base/message_loop/message_loop.h" #include "base/values.h" -#include "sync/js/js_arg_list.h" #include "sync/js/js_event_details.h" #include "sync/js/js_test_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -30,91 +29,6 @@ class SyncJsControllerTest : public testing::Test { base::MessageLoop message_loop_; }; -ACTION_P(ReplyToMessage, reply_name) { - arg2.Call(FROM_HERE, &JsReplyHandler::HandleJsReply, reply_name, JsArgList()); -} - -TEST_F(SyncJsControllerTest, Messages) { - InSequence dummy; - // |mock_backend| needs to outlive |sync_js_controller|. - StrictMock<MockJsBackend> mock_backend; - StrictMock<MockJsReplyHandler> mock_reply_handler; - SyncJsController sync_js_controller; - - base::ListValue arg_list1, arg_list2; - arg_list1.Append(new base::FundamentalValue(false)); - arg_list2.Append(new base::FundamentalValue(5)); - JsArgList args1(&arg_list1), args2(&arg_list2); - - EXPECT_CALL(mock_backend, SetJsEventHandler(_)); - EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) - .WillOnce(ReplyToMessage("test1_reply")); - EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) - .WillOnce(ReplyToMessage("test2_reply")); - - sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); - sync_js_controller.ProcessJsMessage("test1", - args2, - mock_reply_handler.AsWeakHandle()); - sync_js_controller.ProcessJsMessage("test2", - args1, - mock_reply_handler.AsWeakHandle()); - - // The replies should be waiting on our message loop. - EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); - PumpLoop(); - - // Let destructor of |sync_js_controller| call RemoveBackend(). -} - -TEST_F(SyncJsControllerTest, QueuedMessages) { - // |mock_backend| needs to outlive |sync_js_controller|. - StrictMock<MockJsBackend> mock_backend; - StrictMock<MockJsReplyHandler> mock_reply_handler; - SyncJsController sync_js_controller; - - base::ListValue arg_list1, arg_list2; - arg_list1.Append(new base::FundamentalValue(false)); - arg_list2.Append(new base::FundamentalValue(5)); - JsArgList args1(&arg_list1), args2(&arg_list2); - - // Should queue messages. - sync_js_controller.ProcessJsMessage( - "test1", - args2, - mock_reply_handler.AsWeakHandle()); - sync_js_controller.ProcessJsMessage( - "test2", - args1, - mock_reply_handler.AsWeakHandle()); - - // Should do nothing. - PumpLoop(); - Mock::VerifyAndClearExpectations(&mock_backend); - - - // Should call the queued messages. - EXPECT_CALL(mock_backend, SetJsEventHandler(_)); - EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) - .WillOnce(ReplyToMessage("test1_reply")); - EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) - .WillOnce(ReplyToMessage("test2_reply")); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); - - sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); - PumpLoop(); - - // Should do nothing. - sync_js_controller.AttachJsBackend(WeakHandle<JsBackend>()); - PumpLoop(); - - // Should also do nothing. - sync_js_controller.AttachJsBackend(WeakHandle<JsBackend>()); - PumpLoop(); -} - TEST_F(SyncJsControllerTest, Events) { InSequence dummy; SyncJsController sync_js_controller; diff --git a/sync/notifier/invalidation_util.h b/sync/notifier/invalidation_util.h index 392a15e53b..eac4bac5b6 100644 --- a/sync/notifier/invalidation_util.h +++ b/sync/notifier/invalidation_util.h @@ -40,7 +40,7 @@ struct SYNC_EXPORT ObjectIdLessThan { const invalidation::ObjectId& rhs) const; }; -struct InvalidationVersionLessThan { +struct SYNC_EXPORT InvalidationVersionLessThan { bool operator()(const syncer::Invalidation& a, const syncer::Invalidation& b) const; }; diff --git a/sync/protocol/autofill_specifics.proto b/sync/protocol/autofill_specifics.proto index 1402e47d85..64d8e1e8ed 100644 --- a/sync/protocol/autofill_specifics.proto +++ b/sync/protocol/autofill_specifics.proto @@ -40,6 +40,7 @@ message AutofillProfileSpecifics { optional string address_home_street_address = 17; optional string address_home_sorting_code = 18; optional string address_home_dependent_locality = 19; + optional string address_home_language_code = 20; // Phone. repeated string phone_home_whole_number = 13; diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc index 06ecdfee27..04c5f06d76 100644 --- a/sync/protocol/proto_value_conversions.cc +++ b/sync/protocol/proto_value_conversions.cc @@ -438,6 +438,7 @@ base::DictionaryValue* AutofillProfileSpecificsToValue( SET_STR(address_home_street_address); SET_STR(address_home_sorting_code); SET_STR(address_home_dependent_locality); + SET_STR(address_home_language_code); SET_STR_REP(phone_home_whole_number); return value; diff --git a/sync/sync_api.gypi b/sync/sync_api.gypi index 02ff2c4367..8e5b911f23 100644 --- a/sync/sync_api.gypi +++ b/sync/sync_api.gypi @@ -22,6 +22,8 @@ 'api/attachments/attachment_service.h', 'api/attachments/attachment_service_proxy.cc', 'api/attachments/attachment_service_proxy.h', + 'api/attachments/attachment_service_proxy_for_test.cc', + 'api/attachments/attachment_service_proxy_for_test.h', 'api/attachments/attachment_store.cc', 'api/attachments/attachment_store.h', 'api/attachments/fake_attachment_service.cc', diff --git a/sync/sync_core.gypi b/sync/sync_core.gypi index 4ba949c81e..e7019a013f 100644 --- a/sync/sync_core.gypi +++ b/sync/sync_core.gypi @@ -93,14 +93,11 @@ 'engine/update_applicator.h', 'engine/update_handler.cc', 'engine/update_handler.h', - 'js/js_arg_list.cc', - 'js/js_arg_list.h', 'js/js_backend.h', 'js/js_controller.h', 'js/js_event_details.cc', 'js/js_event_details.h', 'js/js_event_handler.h', - 'js/js_reply_handler.h', 'js/sync_js_controller.cc', 'js/sync_js_controller.h', 'protocol/proto_enum_conversions.cc', diff --git a/sync/sync_internal_api.gypi b/sync/sync_internal_api.gypi index b0a476ba0b..3a572dfd38 100644 --- a/sync/sync_internal_api.gypi +++ b/sync/sync_internal_api.gypi @@ -125,6 +125,8 @@ 'internal_api/sync_core.cc', 'internal_api/sync_core.h', 'internal_api/sync_core_proxy.cc', + 'internal_api/sync_core_proxy_impl.cc', + 'internal_api/sync_core_proxy_impl.h', 'internal_api/sync_encryption_handler_impl.cc', 'internal_api/sync_encryption_handler_impl.h', 'internal_api/sync_manager_factory.cc', diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index f5c5301f3f..6841beceb2 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi @@ -191,11 +191,13 @@ 'internal_api/public/base/invalidation_test_util.cc', 'internal_api/public/base/invalidation_test_util.h', 'internal_api/public/test/fake_sync_manager.h', + 'internal_api/public/test/null_sync_core_proxy.h', 'internal_api/public/test/sync_manager_factory_for_profile_sync_test.h', 'internal_api/public/test/test_entry_factory.h', 'internal_api/public/test/test_internal_components_factory.h', 'internal_api/public/test/test_user_share.h', 'internal_api/test/fake_sync_manager.cc', + 'internal_api/test/null_sync_core_proxy.cc', 'internal_api/test/sync_manager_factory_for_profile_sync_test.cc', 'internal_api/test/sync_manager_for_profile_sync_test.cc', 'internal_api/test/sync_manager_for_profile_sync_test.h', @@ -291,7 +293,6 @@ 'engine/sync_scheduler_unittest.cc', 'engine/syncer_proto_util_unittest.cc', 'engine/syncer_unittest.cc', - 'js/js_arg_list_unittest.cc', 'js/js_event_details_unittest.cc', 'js/sync_js_controller_unittest.cc', 'protocol/proto_enum_conversions_unittest.cc', @@ -419,7 +420,7 @@ 'internal_api/protocol_event_buffer_unittest.cc', 'internal_api/public/change_record_unittest.cc', 'internal_api/public/sessions/sync_session_snapshot_unittest.cc', - 'internal_api/sync_core_proxy_unittest.cc', + 'internal_api/sync_core_proxy_impl_unittest.cc', 'internal_api/sync_encryption_handler_impl_unittest.cc', 'internal_api/sync_manager_impl_unittest.cc', 'internal_api/syncapi_server_connection_manager_unittest.cc', diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc index 11bc9562bd..75c1bec561 100644 --- a/sync/syncable/directory.cc +++ b/sync/syncable/directory.cc @@ -39,19 +39,22 @@ Directory::PersistedKernelInfo::PersistedKernelInfo() ModelTypeSet protocol_types = ProtocolTypes(); for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); iter.Inc()) { - reset_download_progress(iter.Get()); + ResetDownloadProgress(iter.Get()); transaction_version[iter.Get()] = 0; } } Directory::PersistedKernelInfo::~PersistedKernelInfo() {} -void Directory::PersistedKernelInfo::reset_download_progress( +void Directory::PersistedKernelInfo::ResetDownloadProgress( ModelType model_type) { + // Clear everything except the data type id field. + download_progress[model_type].Clear(); download_progress[model_type].set_data_type_id( GetSpecificsFieldNumberFromModelType(model_type)); - // An empty-string token indicates no prior knowledge. - download_progress[model_type].set_token(std::string()); + + // Explicitly set an empty token field to denote no progress. + download_progress[model_type].set_token(""); } Directory::SaveChangesSnapshot::SaveChangesSnapshot() @@ -321,10 +324,6 @@ int Directory::GetPositionIndex( return std::distance(siblings->begin(), it); } -EntryKernel* Directory::GetRootEntry() { - return GetEntryById(Id()); -} - bool Directory::InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry) { ScopedKernelLock lock(this); return InsertEntry(trans, entry, &lock); @@ -716,10 +715,14 @@ bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, it.Good(); it.Inc()) { kernel_->persisted_info.transaction_version[it.Get()] = 0; - // Don't discard progress markers for unapplied types. - if (!types_to_unapply.Has(it.Get())) - kernel_->persisted_info.reset_download_progress(it.Get()); + // Don't discard progress markers or context for unapplied types. + if (!types_to_unapply.Has(it.Get())) { + kernel_->persisted_info.ResetDownloadProgress(it.Get()); + kernel_->persisted_info.datatype_context[it.Get()].Clear(); + } } + + kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; } } return true; diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h index 6b91a5ab99..fdac9b4afe 100644 --- a/sync/syncable/directory.h +++ b/sync/syncable/directory.h @@ -100,7 +100,7 @@ class SYNC_EXPORT Directory { // Set the |download_progress| entry for the given model to a // "first sync" start point. When such a value is sent to the server, // a full download of all objects of the model will be initiated. - void reset_download_progress(ModelType model_type); + void ResetDownloadProgress(ModelType model_type); // Last sync timestamp fetched from the server. sync_pb::DataTypeProgressMarker download_progress[MODEL_TYPE_COUNT]; @@ -390,7 +390,6 @@ class SYNC_EXPORT Directory { virtual EntryKernel* GetEntryById(const Id& id); EntryKernel* GetEntryByServerTag(const std::string& tag); virtual EntryKernel* GetEntryByClientTag(const std::string& tag); - EntryKernel* GetRootEntry(); bool ReindexId(BaseWriteTransaction* trans, EntryKernel* const entry, const Id& new_id); bool ReindexParentId(BaseWriteTransaction* trans, EntryKernel* const entry, diff --git a/sync/syncable/syncable_unittest.cc b/sync/syncable/syncable_unittest.cc index 8f261c7d94..01176c2c4d 100644 --- a/sync/syncable/syncable_unittest.cc +++ b/sync/syncable/syncable_unittest.cc @@ -489,6 +489,14 @@ class SyncableDirectoryTest : public testing::Test { for (ModelTypeSet::Iterator it = types_to_purge.First(); it.Good(); it.Inc()) { EXPECT_FALSE(dir_->InitialSyncEndedForType(it.Get())); + sync_pb::DataTypeProgressMarker progress; + dir_->GetDownloadProgress(it.Get(), &progress); + EXPECT_EQ("", progress.token()); + + ReadTransaction trans(FROM_HERE, dir_.get()); + sync_pb::DataTypeContext context; + dir_->GetDataTypeContext(&trans, it.Get(), &context); + EXPECT_TRUE(context.SerializeAsString().empty()); } EXPECT_FALSE(types_to_purge.Has(BOOKMARKS)); EXPECT_TRUE(dir_->InitialSyncEndedForType(BOOKMARKS)); @@ -1686,6 +1694,20 @@ class OnDiskSyncableDirectoryTest : public SyncableDirectoryTest { base::FilePath file_path_; }; +sync_pb::DataTypeProgressMarker BuildProgress(ModelType type) { + sync_pb::DataTypeProgressMarker progress; + progress.set_token("token"); + progress.set_data_type_id(GetSpecificsFieldNumberFromModelType(type)); + return progress; +} + +sync_pb::DataTypeContext BuildContext(ModelType type) { + sync_pb::DataTypeContext context; + context.set_context("context"); + context.set_data_type_id(GetSpecificsFieldNumberFromModelType(type)); + return context; +} + TEST_F(OnDiskSyncableDirectoryTest, TestPurgeEntriesWithTypeIn) { sync_pb::EntitySpecifics bookmark_specs; sync_pb::EntitySpecifics autofill_specs; @@ -1696,11 +1718,22 @@ TEST_F(OnDiskSyncableDirectoryTest, TestPurgeEntriesWithTypeIn) { ModelTypeSet types_to_purge(PREFERENCES, AUTOFILL); + dir_->SetDownloadProgress(BOOKMARKS, + BuildProgress(BOOKMARKS)); + dir_->SetDownloadProgress(PREFERENCES, + BuildProgress(PREFERENCES)); + dir_->SetDownloadProgress(AUTOFILL, + BuildProgress(AUTOFILL)); + TestIdFactory id_factory; // Create some items for each type. { WriteTransaction trans(FROM_HERE, UNITTEST, dir_.get()); + dir_->SetDataTypeContext(&trans, BOOKMARKS, BuildContext(BOOKMARKS)); + dir_->SetDataTypeContext(&trans, PREFERENCES, BuildContext(PREFERENCES)); + dir_->SetDataTypeContext(&trans, AUTOFILL, BuildContext(AUTOFILL)); + // Make it look like these types have completed initial sync. CreateTypeRoot(&trans, dir_.get(), BOOKMARKS); CreateTypeRoot(&trans, dir_.get(), PREFERENCES); diff --git a/sync/test/engine/mock_update_handler.cc b/sync/test/engine/mock_update_handler.cc index da2db885f7..b4e1bd2d9e 100644 --- a/sync/test/engine/mock_update_handler.cc +++ b/sync/test/engine/mock_update_handler.cc @@ -29,12 +29,13 @@ void MockUpdateHandler::GetDataTypeContext( context->Clear(); } -void MockUpdateHandler::ProcessGetUpdatesResponse( +SyncerError MockUpdateHandler::ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, sessions::StatusController* status) { progress_marker_.CopyFrom(progress_marker); + return syncer::SYNCER_OK; } void MockUpdateHandler::ApplyUpdates(sessions::StatusController* status) { diff --git a/sync/test/engine/mock_update_handler.h b/sync/test/engine/mock_update_handler.h index 0cbeca3847..64654adf30 100644 --- a/sync/test/engine/mock_update_handler.h +++ b/sync/test/engine/mock_update_handler.h @@ -22,7 +22,7 @@ class MockUpdateHandler : public UpdateHandler { sync_pb::DataTypeProgressMarker* progress_marker) const OVERRIDE; virtual void GetDataTypeContext(sync_pb::DataTypeContext* context) const OVERRIDE; - virtual void ProcessGetUpdatesResponse( + virtual SyncerError ProcessGetUpdatesResponse( const sync_pb::DataTypeProgressMarker& progress_marker, const sync_pb::DataTypeContext& mutated_context, const SyncEntityList& applicable_updates, |