1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef COMPONENTS_SYNC_DRIVER_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ 6#define COMPONENTS_SYNC_DRIVER_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ 7 8#include "base/memory/scoped_ptr.h" 9#include "base/memory/weak_ptr.h" 10#include "base/sequenced_task_runner.h" 11#include "sync/internal_api/public/base/model_type.h" 12#include "sync/internal_api/public/sync_context_proxy.h" 13 14namespace syncer { 15class ModelTypeSyncProxy; 16} 17 18namespace sync_driver { 19 20// Lives on the UI thread and manages the interactions between many sync 21// components. 22// 23// There are three main parts to this controller: 24// - The SyncContextProxy, represening the sync thread. 25// - The ModelTypeSyncProxy, representing the model type thread. 26// - The user-set state for this type (prefs), which lives on the UI thread. 27// 28// The ModelTypeSyncProxy can exist in three different states. Those 29// states are: 30// - Enabled: Changes are being synced. 31// - Disconnected: Changes would be synced, but there is no connection between 32// the sync thread and the model thread. 33// - Disabled: Syncing is intentionally disabled. The type proxy may clear any 34// of its local state associated with sync when this happens, since 35// this is expected to last a while. 36// 37// This controller is responsible for transitioning the type proxy into and out 38// of these states. It does this by posting tasks to the model type thread. 39// 40// The type proxy is enabled when the user has indicated a desire to sync this 41// type, and the ModelTypeSyncProxy and SyncContextProxy are available. 42// 43// The type proxy is disconnected during initialization, or when either the 44// NonBlockingDataTypeController or SyncContextProxy have not yet registered. 45// It can also be disconnected later on if the sync backend becomes 46// unavailable. 47// 48// The type proxy is disabled if the user has disabled sync for this type. The 49// signal indicating this state will be sent to the type proxy when the pref is 50// first changed, or when the type proxy first connects to the controller. 51// 52// This class is structured using some state machine patterns. It's a bit 53// awkward at times, but this seems to be the clearest way to express the 54// behaviors this class must implement. 55class NonBlockingDataTypeController { 56 public: 57 NonBlockingDataTypeController(syncer::ModelType type, bool is_preferred); 58 ~NonBlockingDataTypeController(); 59 60 // Connects the ModelTypeSyncProxy to this controller. 61 // 62 // There is no "undo" for this operation. The NonBlockingDataTypeController 63 // will only ever deal with a single type proxy. 64 void InitializeType( 65 const scoped_refptr<base::SequencedTaskRunner>& task_runner, 66 const base::WeakPtr<syncer::ModelTypeSyncProxyImpl>& type_sync_proxy); 67 68 // Initialize the connection to the SyncContextProxy. 69 // 70 // This process may be reversed with ClearSyncContextProxy(). 71 void InitializeSyncContext( 72 scoped_ptr<syncer::SyncContextProxy> sync_context_proxy); 73 74 // Disconnect from the current SyncContextProxy. 75 void ClearSyncContext(); 76 77 // Sets the current preferred state. 78 // 79 // Represents a choice to sync or not sync this type. This is expected to 80 // last a long time, so local state may be deleted if this setting is toggled 81 // to false. 82 void SetIsPreferred(bool is_preferred); 83 84 private: 85 enum TypeState { ENABLED, DISABLED, DISCONNECTED }; 86 87 // Figures out which signals need to be sent then send then sends them. 88 void UpdateState(); 89 90 // Sends an enable signal to the ModelTypeSyncProxyImpl. 91 void SendEnableSignal(); 92 93 // Sends a disable signal to the ModelTypeSyncProxyImpl. 94 void SendDisableSignal(); 95 96 // Sends a disconnect signal to the ModelTypeSyncProxyImpl. 97 void SendDisconnectSignal(); 98 99 // Returns true if this type should be synced. 100 bool IsPreferred() const; 101 102 // Returns true if this object has access to the ModelTypeSyncProxyImpl. 103 bool IsSyncProxyConnected() const; 104 105 // Returns true if this object has access to the SyncContextProxy. 106 bool IsSyncBackendConnected() const; 107 108 // Returns the state that the type sync proxy should be in. 109 TypeState GetDesiredState() const; 110 111 // The ModelType we're controlling. Kept mainly for debugging. 112 const syncer::ModelType type_; 113 114 // Returns the state that the type sync proxy is actually in, from this 115 // class' point of view. 116 // 117 // This state is inferred based on the most recently sent signals, and is 118 // intended to represent the state the sync proxy will be in by the time any 119 // tasks we post to it now will be run. Due to threading / queueing effects, 120 // this may or may not be the actual state at this point in time. 121 TypeState current_state_; 122 123 // Whether or not the user wants to sync this type. 124 bool is_preferred_; 125 126 // The ModelTypeSyncProxyImpl and its associated thread. May be NULL. 127 scoped_refptr<base::SequencedTaskRunner> task_runner_; 128 base::WeakPtr<syncer::ModelTypeSyncProxyImpl> type_sync_proxy_; 129 130 // The SyncContextProxy that connects to the current sync backend. May be 131 // NULL. 132 scoped_ptr<syncer::SyncContextProxy> sync_context_proxy_; 133 134 DISALLOW_COPY_AND_ASSIGN(NonBlockingDataTypeController); 135}; 136 137} // namespace sync_driver 138 139#endif // COMPONENTS_SYNC_DRIVER_NON_BLOCKING_DATA_TYPE_CONTROLLER_H_ 140