| // 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 COMPONENTS_SYNC_DRIVER_SHARED_CHANGE_PROCESSOR_H_ |
| #define COMPONENTS_SYNC_DRIVER_SHARED_CHANGE_PROCESSOR_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "base/location.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/synchronization/lock.h" |
| #include "components/sync/api/data_type_error_handler.h" |
| #include "components/sync/api/sync_change_processor.h" |
| #include "components/sync/api/sync_data.h" |
| #include "components/sync/api/sync_error.h" |
| #include "components/sync/api/sync_error_factory.h" |
| #include "components/sync/api/sync_merge_result.h" |
| #include "components/sync/driver/data_type_controller.h" |
| #include "components/sync/engine/model_safe_worker.h" |
| |
| namespace syncer { |
| class SyncableService; |
| struct UserShare; |
| } // namespace syncer |
| |
| namespace sync_driver { |
| |
| class ChangeProcessor; |
| class GenericChangeProcessor; |
| class GenericChangeProcessorFactory; |
| class SyncClient; |
| |
| // A ref-counted wrapper around a GenericChangeProcessor for use with datatypes |
| // that don't live on the UI thread. |
| // |
| // We need to make it refcounted as the ownership transfer from the |
| // DataTypeController is dependent on threading, and hence racy. The |
| // SharedChangeProcessor should be created on the UI thread, but should only be |
| // connected and used on the same thread as the datatype it interacts with. |
| // |
| // The only thread-safe method is Disconnect, which will disconnect from the |
| // generic change processor, letting us shut down the syncer/datatype without |
| // waiting for non-UI threads. |
| // |
| // Note: since we control the work being done while holding the lock, we ensure |
| // no I/O or other intensive work is done while blocking the UI thread (all |
| // the work is in-memory sync interactions). |
| // |
| // We use virtual methods so that we can use mock's in testing. |
| class SharedChangeProcessor |
| : public base::RefCountedThreadSafe<SharedChangeProcessor> { |
| public: |
| typedef base::Callback<void( |
| DataTypeController::ConfigureResult start_result, |
| const syncer::SyncMergeResult& local_merge_result, |
| const syncer::SyncMergeResult& syncer_merge_result)> |
| StartDoneCallback; |
| |
| // Create an uninitialized SharedChangeProcessor. |
| explicit SharedChangeProcessor(syncer::ModelType type); |
| |
| void StartAssociation( |
| StartDoneCallback start_done, |
| SyncClient* const sync_client, |
| syncer::UserShare* user_share, |
| std::unique_ptr<syncer::DataTypeErrorHandler> error_handler); |
| |
| // Connect to the Syncer and prepare to handle changes for |type|. Will |
| // create and store a new GenericChangeProcessor and return a weak pointer to |
| // the syncer::SyncableService associated with |type|. |
| // Note: If this SharedChangeProcessor has been disconnected, or the |
| // syncer::SyncableService was not alive, will return a null weak pointer. |
| virtual base::WeakPtr<syncer::SyncableService> Connect( |
| SyncClient* sync_client, |
| GenericChangeProcessorFactory* processor_factory, |
| syncer::UserShare* user_share, |
| std::unique_ptr<syncer::DataTypeErrorHandler> error_handler, |
| const base::WeakPtr<syncer::SyncMergeResult>& merge_result); |
| |
| // Disconnects from the generic change processor. May be called from any |
| // thread. After this, all attempts to interact with the change processor by |
| // |local_service_| are dropped and return errors. The syncer will be safe to |
| // shut down from the point of view of this datatype. |
| // Note: Once disconnected, you cannot reconnect without creating a new |
| // SharedChangeProcessor. |
| // Returns: true if we were previously succesfully connected, false if we were |
| // already disconnected. |
| virtual bool Disconnect(); |
| |
| // GenericChangeProcessor stubs (with disconnect support). |
| // Should only be called on the same thread the datatype resides. |
| virtual int GetSyncCount(); |
| virtual syncer::SyncError ProcessSyncChanges( |
| const tracked_objects::Location& from_here, |
| const syncer::SyncChangeList& change_list); |
| virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const; |
| virtual syncer::SyncError GetAllSyncDataReturnError( |
| syncer::ModelType type, |
| syncer::SyncDataList* data) const; |
| virtual syncer::SyncError UpdateDataTypeContext( |
| syncer::ModelType type, |
| syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status, |
| const std::string& context); |
| virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes); |
| virtual bool CryptoReadyIfNecessary(); |
| |
| // If a datatype context associated with the current type exists, fills |
| // |context| and returns true. Otheriwse, if there has not been a context |
| // set, returns false. |
| virtual bool GetDataTypeContext(std::string* context) const; |
| |
| virtual syncer::SyncError CreateAndUploadError( |
| const tracked_objects::Location& location, |
| const std::string& message); |
| |
| // Calls local_service_->StopSyncing() and releases our reference to it. |
| void StopLocalService(); |
| |
| ChangeProcessor* generic_change_processor(); |
| |
| protected: |
| friend class base::RefCountedThreadSafe<SharedChangeProcessor>; |
| virtual ~SharedChangeProcessor(); |
| |
| private: |
| // Record association time. |
| virtual void RecordAssociationTime(base::TimeDelta time); |
| |
| // Monitor lock for this object. All methods that interact with the change |
| // processor must aquire this lock and check whether we're disconnected or |
| // not. Once disconnected, all attempted changes to or loads from the change |
| // processor return errors. This enables us to shut down the syncer without |
| // having to wait for possibly non-UI thread datatypes to complete work. |
| mutable base::Lock monitor_lock_; |
| bool disconnected_; |
| |
| // The sync datatype we process changes for. |
| const syncer::ModelType type_; |
| |
| // The frontend / UI MessageLoop this object is constructed on. May also be |
| // destructed and/or disconnected on this loop, see ~SharedChangeProcessor. |
| const scoped_refptr<const base::SingleThreadTaskRunner> frontend_task_runner_; |
| |
| // The loop that all methods except the constructor, destructor, and |
| // Disconnect() should be called on. Set in Connect(). |
| scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_; |
| |
| // Used only on |backend_loop_|. |
| GenericChangeProcessor* generic_change_processor_; |
| |
| std::unique_ptr<syncer::DataTypeErrorHandler> error_handler_; |
| |
| // The local service for this type. Only set if the DTC for the type uses |
| // SharedChangeProcessor::StartAssociation(). |
| base::WeakPtr<syncer::SyncableService> local_service_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SharedChangeProcessor); |
| }; |
| |
| } // namespace sync_driver |
| |
| #endif // COMPONENTS_SYNC_DRIVER_SHARED_CHANGE_PROCESSOR_H_ |