summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-26 09:57:48 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-26 09:57:48 +0000
commita74bfd94b772bd2fd2fb6a4c86ab7fa28bae5e09 (patch)
treecd65affbec838521ffaaa82797e59e9d0d5b3bfe
parent599bdcf987a713e054225e9d9908374cd95c05c7 (diff)
downloadchromium_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.gyp1
-rw-r--r--components/sync_driver.gypi2
-rw-r--r--components/sync_driver/non_blocking_data_type_controller.cc137
-rw-r--r--components/sync_driver/non_blocking_data_type_controller.h136
-rw-r--r--components/sync_driver/non_blocking_data_type_controller_unittest.cc227
-rw-r--r--sync/internal_api/non_blocking_type_processor.cc30
-rw-r--r--sync/internal_api/public/non_blocking_type_processor.h29
-rw-r--r--sync/internal_api/sync_core_proxy_impl_unittest.cc8
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();
}