diff options
author | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-26 09:57:48 +0000 |
---|---|---|
committer | rlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-26 09:57:48 +0000 |
commit | a74bfd94b772bd2fd2fb6a4c86ab7fa28bae5e09 (patch) | |
tree | cd65affbec838521ffaaa82797e59e9d0d5b3bfe | |
parent | 599bdcf987a713e054225e9d9908374cd95c05c7 (diff) | |
download | chromium_src-a74bfd94b772bd2fd2fb6a4c86ab7fa28bae5e09.zip chromium_src-a74bfd94b772bd2fd2fb6a4c86ab7fa28bae5e09.tar.gz chromium_src-a74bfd94b772bd2fd2fb6a4c86ab7fa28bae5e09.tar.bz2 |
Introduce NonBlockingDataTypeController
The NonBlockingDataTypeController tracks the sync state of
a non-blocking data type and sends signals to its components from the UI
thread. It is responsible for enabling and disabling sync for a data
type according to user preference and the availbility of the sync
backend.
This CL also includes some changes to the NonBlockingDataTypeProcessor,
which is currently just a stub of what will eventually become
non-blocking sync's model thread component, so that it can be used in
testing NonBlockingDataTypeController.
BUG=351005
Review URL: https://codereview.chromium.org/249843002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266344 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | components/components_tests.gyp | 1 | ||||
-rw-r--r-- | components/sync_driver.gypi | 2 | ||||
-rw-r--r-- | components/sync_driver/non_blocking_data_type_controller.cc | 137 | ||||
-rw-r--r-- | components/sync_driver/non_blocking_data_type_controller.h | 136 | ||||
-rw-r--r-- | components/sync_driver/non_blocking_data_type_controller_unittest.cc | 227 | ||||
-rw-r--r-- | sync/internal_api/non_blocking_type_processor.cc | 30 | ||||
-rw-r--r-- | sync/internal_api/public/non_blocking_type_processor.h | 29 | ||||
-rw-r--r-- | sync/internal_api/sync_core_proxy_impl_unittest.cc | 8 |
8 files changed, 554 insertions, 16 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index b533cd4..a1f587a 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -135,6 +135,7 @@ 'storage_monitor/storage_monitor_win_unittest.cc', 'sync_driver/generic_change_processor_unittest.cc', 'sync_driver/model_association_manager_unittest.cc', + 'sync_driver/non_blocking_data_type_controller_unittest.cc', 'sync_driver/sync_prefs_unittest.cc', 'sync_driver/system_encryptor_unittest.cc', 'test/run_all_unittests.cc', diff --git a/components/sync_driver.gypi b/components/sync_driver.gypi index 364274dd..0a13f9f 100644 --- a/components/sync_driver.gypi +++ b/components/sync_driver.gypi @@ -35,6 +35,8 @@ 'sync_driver/model_association_manager.cc', 'sync_driver/model_association_manager.h', 'sync_driver/model_associator.h', + 'sync_driver/non_blocking_data_type_controller.cc', + 'sync_driver/non_blocking_data_type_controller.h', 'sync_driver/pref_names.cc', 'sync_driver/pref_names.h', 'sync_driver/proxy_data_type_controller.cc', diff --git a/components/sync_driver/non_blocking_data_type_controller.cc b/components/sync_driver/non_blocking_data_type_controller.cc new file mode 100644 index 0000000..e2e0366 --- /dev/null +++ b/components/sync_driver/non_blocking_data_type_controller.cc @@ -0,0 +1,137 @@ +// 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 "components/sync_driver/non_blocking_data_type_controller.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/location.h" +#include "sync/internal_api/public/non_blocking_type_processor.h" + +namespace browser_sync { + +NonBlockingDataTypeController::NonBlockingDataTypeController( + syncer::ModelType type, bool is_preferred) + : type_(type), + current_state_(DISCONNECTED), + is_preferred_(is_preferred) {} + +NonBlockingDataTypeController::~NonBlockingDataTypeController() {} + +void NonBlockingDataTypeController::InitializeProcessor( + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::WeakPtr<syncer::NonBlockingTypeProcessor> processor) { + DCHECK(!IsTypeProcessorConnected()); + task_runner_ = task_runner; + processor_ = processor; + DCHECK(IsTypeProcessorConnected()); + + UpdateState(); +} + +void NonBlockingDataTypeController::InitializeSyncCoreProxy( + scoped_ptr<syncer::SyncCoreProxy> proxy) { + DCHECK(!IsSyncBackendConnected()); + proxy_ = proxy.Pass(); + + UpdateState(); +} + +void NonBlockingDataTypeController::ClearSyncCoreProxy() { + // Never had a sync core proxy to begin with. No change. + if (!proxy_) + return; + proxy_.reset(); + + UpdateState(); +} + +void NonBlockingDataTypeController::SetIsPreferred(bool is_preferred) { + is_preferred_ = is_preferred; + + UpdateState(); +} + +void NonBlockingDataTypeController::UpdateState() { + // Return immediately if no updates are necessary. + if (GetDesiredState() == current_state_) { + return; + } + + // Return immediately if the processor is not ready yet. + if (!IsTypeProcessorConnected()) { + return; + } + + // Send the appropriate state transition request to the processor. + switch (GetDesiredState()) { + case ENABLED: + SendEnableSignal(); + return; + case DISABLED: + SendDisableSignal(); + return; + case DISCONNECTED: + SendDisconnectSignal(); + return; + } + NOTREACHED(); + return; +} + +void NonBlockingDataTypeController::SendEnableSignal() { + DCHECK_EQ(ENABLED, GetDesiredState()); + DVLOG(1) << "Enabling non-blocking sync type " << ModelTypeToString(type_); + + task_runner_->PostTask( + FROM_HERE, + base::Bind(&syncer::NonBlockingTypeProcessor::Enable, + processor_, + base::Owned(proxy_->Clone().release()))); + current_state_ = ENABLED; +} + +void NonBlockingDataTypeController::SendDisableSignal() { + DCHECK_EQ(DISABLED, GetDesiredState()); + DVLOG(1) << "Disabling non-blocking sync type " << ModelTypeToString(type_); + task_runner_->PostTask( + FROM_HERE, + base::Bind(&syncer::NonBlockingTypeProcessor::Disable, processor_)); + current_state_ = DISABLED; +} + +void NonBlockingDataTypeController::SendDisconnectSignal() { + DCHECK_EQ(DISCONNECTED, GetDesiredState()); + DVLOG(1) << "Disconnecting non-blocking sync type " + << ModelTypeToString(type_); + task_runner_->PostTask( + FROM_HERE, + base::Bind(&syncer::NonBlockingTypeProcessor::Disconnect, processor_)); + current_state_ = DISCONNECTED; +} + +bool NonBlockingDataTypeController::IsPreferred() const { + return is_preferred_; +} + +bool NonBlockingDataTypeController::IsTypeProcessorConnected() const { + return task_runner_ != NULL; +} + +bool NonBlockingDataTypeController::IsSyncBackendConnected() const { + return proxy_; +} + +NonBlockingDataTypeController::TypeProcessorState +NonBlockingDataTypeController::GetDesiredState() const { + if (!IsPreferred()) { + return DISABLED; + } else if (!IsSyncBackendConnected() || !IsTypeProcessorConnected()) { + return DISCONNECTED; + } else { + return ENABLED; + } +} + +} // namespace browser_sync diff --git a/components/sync_driver/non_blocking_data_type_controller.h b/components/sync_driver/non_blocking_data_type_controller.h new file mode 100644 index 0000000..4a1c66c --- /dev/null +++ b/components/sync_driver/non_blocking_data_type_controller.h @@ -0,0 +1,136 @@ +// 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 CHROME_BROWSER_SYNC_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ +#define CHROME_BROWSER_SYNC_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/internal_api/public/sync_core_proxy.h" + +namespace syncer { +class NonBlockingTypeProcessor; +} + +namespace browser_sync { + +// Lives on the UI thread and manages the interactions between many sync +// components. +// +// There are three main parts to this controller: +// - The SyncCoreProxy, represening the sync thread. +// - The NonBlockingTypeProcessor, representing the model type thread. +// - The user-set state for this type (prefs), which lives on the UI thread. +// +// The NonBlockingSyncTypeProcessor can exist in three different states. Those +// states are: +// - Enabled: Changes are being synced. +// - Disconnected: Changes would be synced, but there is no connection between +// the sync thread and the model thread. +// - Disabled: Syncing is intentionally disabled. The processor may clear any +// of its local state associated with sync when this happens, since +// this is expected to last a while. +// +// This controller is responsible for transitioning the processor into and out +// of these states. It does this by posting tasks to the model type thread. +// +// The processor is enabled when the user has indicated a desire to sync this +// type, and the NonBlockingTypeProcessor and SyncCoreProxy are available. +// +// The processor is disconnected during initialization, or when either the +// NonBlockingDataTypeController or SyncCoreProxy have not yet registered. It +// can also be disconnected later on if the sync backend becomes unavailable. +// +// The processor is disabled if the user has disabled sync for this type. The +// signal indicating this state will be sent to the processor when the pref is +// first changed, or when the processor first connects to the controller. +// +// This class is structured using some state machine patterns. It's a bit +// awkward at times, but this seems to be the clearest way to express the +// behaviors this class must implement. +class NonBlockingDataTypeController { + public: + NonBlockingDataTypeController(syncer::ModelType type, bool is_preferred); + ~NonBlockingDataTypeController(); + + // Connects the NonBlockingTypeProcessor to this controller. + // + // There is no "undo" for this operation. The NonBlockingDataTypeController + // will only ever deal with a single processor. + void InitializeProcessor( + scoped_refptr<base::SequencedTaskRunner> task_runner, + base::WeakPtr<syncer::NonBlockingTypeProcessor> processor); + + // Initialize the connection to the SyncCoreProxy. + // + // This process may be reversed with ClearSyncCoreProxy(). + void InitializeSyncCoreProxy(scoped_ptr<syncer::SyncCoreProxy> proxy); + + // Disconnect from the current SyncCoreProxy. + void ClearSyncCoreProxy(); + + // Sets the current preferred state. + // + // Represents a choice to sync or not sync this type. This is expected to + // last a long time, so local state may be deleted if this setting is toggled + // to false. + void SetIsPreferred(bool is_preferred); + + private: + enum TypeProcessorState { ENABLED, DISABLED, DISCONNECTED }; + + // Figures out which signals need to be sent then send then sends them. + void UpdateState(); + + // Sends an enable signal to the NonBlockingTypeProcessor. + void SendEnableSignal(); + + // Sends a disable signal to the NonBlockingTypeProcessor. + void SendDisableSignal(); + + // Sends a disconnect signal to the NonBlockingTypeProcessor. + void SendDisconnectSignal(); + + // Returns true if this type should be synced. + bool IsPreferred() const; + + // Returns true if this object has access to the NonBlockingTypeProcessor. + bool IsTypeProcessorConnected() const; + + // Returns true if this object has access to the SyncCoreProxy. + bool IsSyncBackendConnected() const; + + // Returns the state that the processor *should* be in. + TypeProcessorState GetDesiredState() const; + + // The ModelType we're controlling. Kept mainly for debugging. + const syncer::ModelType type_; + + // Returns the state that the processor is actually in, from this class' + // point of view. + // + // This state is inferred based on the most recently sent signals, and is + // intended to represent the state the processor will be in by the time any + // tasks we post to it now will be run. Due to threading / queueing effects, + // this may or may not be the actual state at this point in time. + TypeProcessorState current_state_; + + // Whether or not the user wants to sync this type. + bool is_preferred_; + + // The NonBlockingTypeProcessor and its associated thread. May be NULL. + scoped_refptr<base::SequencedTaskRunner> task_runner_; + base::WeakPtr<syncer::NonBlockingTypeProcessor> processor_; + + // The SyncCoreProxy that connects to the current sync backend. May be NULL. + scoped_ptr<syncer::SyncCoreProxy> proxy_; + + DISALLOW_COPY_AND_ASSIGN(NonBlockingDataTypeController); +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ diff --git a/components/sync_driver/non_blocking_data_type_controller_unittest.cc b/components/sync_driver/non_blocking_data_type_controller_unittest.cc new file mode 100644 index 0000000..b695c0b --- /dev/null +++ b/components/sync_driver/non_blocking_data_type_controller_unittest.cc @@ -0,0 +1,227 @@ +// 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 "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "base/test/test_simple_task_runner.h" +#include "components/sync_driver/non_blocking_data_type_controller.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 "testing/gtest/include/gtest/gtest.h" + +namespace { + +class MockSyncCoreProxy : public syncer::SyncCoreProxy { + public: + MockSyncCoreProxy() {} + virtual ~MockSyncCoreProxy() {} + + virtual void ConnectTypeToCore( + syncer::ModelType type, + base::WeakPtr<syncer::NonBlockingTypeProcessor> type_processor) OVERRIDE { + type_processor->OnConnect( + base::WeakPtr<syncer::NonBlockingTypeProcessorCore>(), + scoped_refptr<base::SequencedTaskRunner>()); + } + + virtual scoped_ptr<SyncCoreProxy> Clone() OVERRIDE { + return scoped_ptr<SyncCoreProxy>(new MockSyncCoreProxy()); + } +}; + +class NonBlockingDataTypeControllerTest : public testing::Test { + public: + NonBlockingDataTypeControllerTest() + : processor_(syncer::DICTIONARY), + model_thread_(new base::TestSimpleTaskRunner()), + controller_(syncer::DICTIONARY, true) {} + + virtual ~NonBlockingDataTypeControllerTest() {} + + // Connects the processor to the NonBlockingDataTypeController. + void InitProcessor() { + controller_.InitializeProcessor( + model_thread_, processor_.AsWeakPtr()); + RunQueuedTasks(); + } + + // Connects the sync backend to the NonBlockingDataTypeController. + void InitSync() { + controller_.InitializeSyncCoreProxy(mock_core_proxy_.Clone()); + RunQueuedTasks(); + } + + // Disconnects the sync backend from the NonBlockingDataTypeController. + void UninitializeSync() { + controller_.ClearSyncCoreProxy(); + RunQueuedTasks(); + } + + // Toggles the user's preference for syncing this type. + void SetIsPreferred(bool preferred) { + controller_.SetIsPreferred(preferred); + RunQueuedTasks(); + } + + // The processor pretends to run tasks on a different thread. + // This function runs any posted tasks. + void RunQueuedTasks() { + model_thread_->RunUntilIdle(); + } + + protected: + MockSyncCoreProxy mock_core_proxy_; + + syncer::NonBlockingTypeProcessor processor_; + scoped_refptr<base::TestSimpleTaskRunner> model_thread_; + + browser_sync::NonBlockingDataTypeController controller_; +}; + +// Initialization when the user has disabled syncing for this type. +TEST_F(NonBlockingDataTypeControllerTest, UserDisabled) { + SetIsPreferred(false); + InitProcessor(); + InitSync(); + + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + UninitializeSync(); + + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); +} + +// Init the sync backend then the type processor. +TEST_F(NonBlockingDataTypeControllerTest, Enabled_SyncFirst) { + SetIsPreferred(true); + InitSync(); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + InitProcessor(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + UninitializeSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); +} + +// Init the type processor then the sync backend. +TEST_F(NonBlockingDataTypeControllerTest, Enabled_ProcessorFirst) { + SetIsPreferred(true); + InitProcessor(); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + InitSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + UninitializeSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); +} + +// Initialize sync then disable it with a pref change. +TEST_F(NonBlockingDataTypeControllerTest, PreferThenNot) { + SetIsPreferred(true); + InitProcessor(); + InitSync(); + + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + SetIsPreferred(false); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); +} + +// Connect type processor and sync backend, then toggle prefs repeatedly. +TEST_F(NonBlockingDataTypeControllerTest, RepeatedTogglePreference) { + SetIsPreferred(false); + InitProcessor(); + InitSync(); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + SetIsPreferred(true); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + SetIsPreferred(false); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + SetIsPreferred(true); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + SetIsPreferred(false); + EXPECT_FALSE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); +} + +// Test sync backend getting restarted while processor is connected. +TEST_F(NonBlockingDataTypeControllerTest, RestartSyncBackend) { + SetIsPreferred(true); + InitProcessor(); + InitSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); + + // Shutting down sync backend should disconnect but not disable the type. + UninitializeSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_FALSE(processor_.IsConnected()); + + // Brining the backend back should reconnect the type. + InitSync(); + EXPECT_TRUE(processor_.IsPreferred()); + EXPECT_TRUE(processor_.IsConnected()); +} + +// Test sync backend being restarted before processor connects. +TEST_F(NonBlockingDataTypeControllerTest, RestartSyncBackendEarly) { + SetIsPreferred(true); + + // Toggle sync off and on before the type processor is available. + InitSync(); + EXPECT_FALSE(processor_.IsConnected()); + UninitializeSync(); + EXPECT_FALSE(processor_.IsConnected()); + InitSync(); + EXPECT_FALSE(processor_.IsConnected()); + + // Introduce the processor. + InitProcessor(); + EXPECT_TRUE(processor_.IsConnected()); +} + +// Test pref toggling before the sync backend has connected. +TEST_F(NonBlockingDataTypeControllerTest, TogglePreferenceWithoutBackend) { + SetIsPreferred(true); + InitProcessor(); + + // This should emit a disable signal. + SetIsPreferred(false); + EXPECT_FALSE(processor_.IsConnected()); + EXPECT_FALSE(processor_.IsPreferred()); + + // This won't enable us, since we don't have a sync backend. + SetIsPreferred(true); + EXPECT_FALSE(processor_.IsConnected()); + EXPECT_FALSE(processor_.IsPreferred()); + + // Only now do we start sending enable signals. + InitSync(); + EXPECT_TRUE(processor_.IsConnected()); + EXPECT_TRUE(processor_.IsPreferred()); +} + +} // namespace diff --git a/sync/internal_api/non_blocking_type_processor.cc b/sync/internal_api/non_blocking_type_processor.cc index 8fd0d27..d426443 100644 --- a/sync/internal_api/non_blocking_type_processor.cc +++ b/sync/internal_api/non_blocking_type_processor.cc @@ -11,14 +11,22 @@ namespace syncer { NonBlockingTypeProcessor::NonBlockingTypeProcessor(ModelType type) - : type_(type), enabled_(false), weak_ptr_factory_(this) {} + : type_(type), + is_preferred_(false), + is_connected_(false), + weak_ptr_factory_(this) {} NonBlockingTypeProcessor::~NonBlockingTypeProcessor() { } -bool NonBlockingTypeProcessor::IsEnabled() const { +bool NonBlockingTypeProcessor::IsPreferred() const { DCHECK(CalledOnValidThread()); - return enabled_; + return is_preferred_; +} + +bool NonBlockingTypeProcessor::IsConnected() const { + DCHECK(CalledOnValidThread()); + return is_connected_; } ModelType NonBlockingTypeProcessor::GetModelType() const { @@ -28,15 +36,19 @@ ModelType NonBlockingTypeProcessor::GetModelType() const { void NonBlockingTypeProcessor::Enable(SyncCoreProxy* core_proxy) { DCHECK(CalledOnValidThread()); - core_proxy->ConnectTypeToCore( - GetModelType(), - AsWeakPtr()); + is_preferred_ = true; + core_proxy->ConnectTypeToCore(GetModelType(), AsWeakPtr()); } void NonBlockingTypeProcessor::Disable() { DCHECK(CalledOnValidThread()); - enabled_ = false; - weak_ptr_factory_.InvalidateWeakPtrs(); + is_preferred_ = false; + Disconnect(); +} + +void NonBlockingTypeProcessor::Disconnect() { + DCHECK(CalledOnValidThread()); + is_connected_ = false; core_ = base::WeakPtr<NonBlockingTypeProcessorCore>(); sync_thread_ = scoped_refptr<base::SequencedTaskRunner>(); } @@ -50,7 +62,7 @@ void NonBlockingTypeProcessor::OnConnect( base::WeakPtr<NonBlockingTypeProcessorCore> core, scoped_refptr<base::SequencedTaskRunner> sync_thread) { DCHECK(CalledOnValidThread()); - enabled_ = true; + is_connected_ = true; core_ = core; sync_thread_ = sync_thread; } diff --git a/sync/internal_api/public/non_blocking_type_processor.h b/sync/internal_api/public/non_blocking_type_processor.h index 0198c27..3745088 100644 --- a/sync/internal_api/public/non_blocking_type_processor.h +++ b/sync/internal_api/public/non_blocking_type_processor.h @@ -24,8 +24,20 @@ class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessor : base::NonThreadSafe { NonBlockingTypeProcessor(ModelType type); virtual ~NonBlockingTypeProcessor(); + // Returns true if this object believes that sync is preferred for this type. + // + // By "preferred", we mean that a policy decision has been made that this + // type should be synced. Most of the time this is controlled by a user + // clicking a checkbox on the settings page. + // + // The canonical preferred state is based on SyncPrefs on the UI thread. At + // best, this value is stale and may lag behind the one set on the UI thread. + // Before this type has registered with the UI thread, it's mostly just an + // informed guess. + bool IsPreferred() const; + // Returns true if the handshake with sync thread is complete. - bool IsEnabled() const; + bool IsConnected() const; // Returns the model type handled by this processor. ModelType GetModelType() const; @@ -33,10 +45,14 @@ class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessor : base::NonThreadSafe { // Starts the handshake with the sync thread. void Enable(SyncCoreProxy* core_proxy); - // Severs all ties to the sync thread. + // Severs all ties to the sync thread and may delete local sync state. // Another call to Enable() can be used to re-establish this connection. void Disable(); + // Severs all ties to the sync thread. + // Another call to Enable() can be used to re-establish this connection. + void Disconnect(); + // Callback used to process the handshake response. void OnConnect(base::WeakPtr<NonBlockingTypeProcessorCore> core, scoped_refptr<base::SequencedTaskRunner> sync_thread); @@ -46,7 +62,14 @@ class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessor : base::NonThreadSafe { private: ModelType type_; sync_pb::DataTypeProgressMarker progress_marker_; - bool enabled_; + + // Whether or not sync is preferred for this type. This is a cached copy of + // the canonical copy information on the UI thread. + bool is_preferred_; + + // Whether or not this object has completed its initial handshake with the + // SyncCoreProxy. + bool is_connected_; base::WeakPtr<NonBlockingTypeProcessorCore> core_; scoped_refptr<base::SequencedTaskRunner> sync_thread_; diff --git a/sync/internal_api/sync_core_proxy_impl_unittest.cc b/sync/internal_api/sync_core_proxy_impl_unittest.cc index a3e228c..2e306ee 100644 --- a/sync/internal_api/sync_core_proxy_impl_unittest.cc +++ b/sync/internal_api/sync_core_proxy_impl_unittest.cc @@ -52,7 +52,7 @@ TEST_F(SyncCoreProxyImplTest, FailToConnect1) { base::RunLoop run_loop_; run_loop_.RunUntilIdle(); - EXPECT_FALSE(themes_processor.IsEnabled()); + EXPECT_FALSE(themes_processor.IsConnected()); } // Try to connect a type to a SyncCore as it shuts down. @@ -63,7 +63,7 @@ TEST_F(SyncCoreProxyImplTest, FailToConnect2) { base::RunLoop run_loop_; run_loop_.RunUntilIdle(); - EXPECT_FALSE(themes_processor.IsEnabled()); + EXPECT_FALSE(themes_processor.IsConnected()); } // Tests the case where the type's processor shuts down first. @@ -75,7 +75,7 @@ TEST_F(SyncCoreProxyImplTest, TypeDisconnectsFirst) { base::RunLoop run_loop_; run_loop_.RunUntilIdle(); - EXPECT_TRUE(themes_processor->IsEnabled()); + EXPECT_TRUE(themes_processor->IsConnected()); themes_processor.reset(); } @@ -88,7 +88,7 @@ TEST_F(SyncCoreProxyImplTest, SyncDisconnectsFirst) { base::RunLoop run_loop_; run_loop_.RunUntilIdle(); - EXPECT_TRUE(themes_processor->IsEnabled()); + EXPECT_TRUE(themes_processor->IsConnected()); DisableSync(); } |