| // 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 CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_ |
| #define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_ |
| |
| #include <map> |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/compiler_specific.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/thread.h" |
| #include "sync/internal_api/public/base/model_type.h" |
| #include "sync/internal_api/public/engine/model_safe_worker.h" |
| #include "sync/internal_api/public/sync_manager.h" |
| |
| class Profile; |
| |
| namespace base { |
| class MessageLoop; |
| } |
| |
| namespace syncer { |
| struct UserShare; |
| } // namespace syncer |
| |
| namespace browser_sync { |
| |
| class ChangeProcessor; |
| class UIModelWorker; |
| |
| // A class that keep track of the workers, change processors, and |
| // routing info for the enabled sync types, and also routes change |
| // events to the right processors. |
| class SyncBackendRegistrar : public syncer::SyncManager::ChangeDelegate, |
| public syncer::WorkerLoopDestructionObserver { |
| public: |
| // |name| is used for debugging. Does not take ownership of |profile| or |
| // |sync_loop|. Must be created on the UI thread. |
| SyncBackendRegistrar(const std::string& name, |
| Profile* profile, |
| scoped_ptr<base::Thread> sync_thread); |
| |
| // SyncBackendRegistrar must be destroyed as follows: |
| // |
| // 1) On the UI thread, call RequestWorkerStopOnUIThread(). |
| // 2) UI posts task to shut down syncer on sync thread. |
| // 3) If sync is disabled, call ReleaseSyncThread() on the UI thread. |
| // 3) UI posts SyncBackendRegistrar::ShutDown() on sync thread to |
| // unregister workers from observing destruction of their working loops. |
| // 4) Workers notify registrar when unregistration finishes or working |
| // loops are destroyed. Registrar destroys itself on last worker |
| // notification. Sync thread will be stopped if ownership was not |
| // released. |
| virtual ~SyncBackendRegistrar(); |
| |
| // Informs the SyncBackendRegistrar of the currently enabled set of types. |
| // These types will be placed in the passive group. This function should be |
| // called exactly once during startup. |
| void SetInitialTypes(syncer::ModelTypeSet initial_types); |
| |
| // Returns whether or not we are currently syncing encryption keys. |
| // Must be called on the UI thread. |
| bool IsNigoriEnabled() const; |
| |
| // Removes all types in |types_to_remove| from the routing info and |
| // adds all the types in |types_to_add| to the routing info that are |
| // not already there (initially put in the passive group). |
| // |types_to_remove| and |types_to_add| must be disjoint. Returns |
| // the set of newly-added types. Must be called on the UI thread. |
| syncer::ModelTypeSet ConfigureDataTypes( |
| syncer::ModelTypeSet types_to_add, |
| syncer::ModelTypeSet types_to_remove); |
| |
| // Returns the set of enabled types as of the last configuration. Note that |
| // this might be different from the current types in the routing info due |
| // to DeactiveDataType being called separately from ConfigureDataTypes. |
| syncer::ModelTypeSet GetLastConfiguredTypes() const; |
| |
| // Must be called from the UI thread. (See destructor comment.) |
| void RequestWorkerStopOnUIThread(); |
| |
| // Activates the given data type (which should belong to the given |
| // group) and starts the given change processor. Must be called |
| // from |group|'s native thread. |
| void ActivateDataType(syncer::ModelType type, |
| syncer::ModelSafeGroup group, |
| ChangeProcessor* change_processor, |
| syncer::UserShare* user_share); |
| |
| // Deactivates the given type if necessary. Must be called from the |
| // UI thread and not |type|'s native thread. Yes, this is |
| // surprising: see http://crbug.com/92804. |
| void DeactivateDataType(syncer::ModelType type); |
| |
| // Returns true only between calls to ActivateDataType(type, ...) |
| // and DeactivateDataType(type). Used only by tests. |
| bool IsTypeActivatedForTest(syncer::ModelType type) const; |
| |
| // SyncManager::ChangeDelegate implementation. May be called from |
| // any thread. |
| virtual void OnChangesApplied( |
| syncer::ModelType model_type, |
| int64 model_version, |
| const syncer::BaseTransaction* trans, |
| const syncer::ImmutableChangeRecordList& changes) OVERRIDE; |
| virtual void OnChangesComplete(syncer::ModelType model_type) OVERRIDE; |
| |
| void GetWorkers(std::vector<syncer::ModelSafeWorker*>* out); |
| void GetModelSafeRoutingInfo(syncer::ModelSafeRoutingInfo* out); |
| |
| // syncer::WorkerLoopDestructionObserver implementation. |
| virtual void OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) OVERRIDE; |
| |
| // Release ownership of |sync_thread_|. Called when sync is disabled. |
| scoped_ptr<base::Thread> ReleaseSyncThread(); |
| |
| // Unregister workers from loop destruction observation. |
| void Shutdown(); |
| |
| base::Thread* sync_thread(); |
| |
| private: |
| typedef std::map<syncer::ModelSafeGroup, |
| scoped_refptr<syncer::ModelSafeWorker> > WorkerMap; |
| typedef std::map<syncer::ModelType, ChangeProcessor*> |
| ProcessorMap; |
| |
| // Callback after workers unregister from observing destruction of their |
| // working loops. |
| void OnWorkerUnregistrationDone(syncer::ModelSafeGroup group); |
| |
| void RemoveWorker(syncer::ModelSafeGroup group); |
| |
| // Returns the change processor for the given model, or NULL if none |
| // exists. Must be called from |group|'s native thread. |
| ChangeProcessor* GetProcessor(syncer::ModelType type) const; |
| |
| // Must be called with |lock_| held. Simply returns the change |
| // processor for the given type, if it exists. May be called from |
| // any thread. |
| ChangeProcessor* GetProcessorUnsafe(syncer::ModelType type) const; |
| |
| // Return true if |model_type| lives on the current thread. Must be |
| // called with |lock_| held. May be called on any thread. |
| bool IsCurrentThreadSafeForModel( |
| syncer::ModelType model_type) const; |
| |
| // Name used for debugging. |
| const std::string name_; |
| |
| Profile* const profile_; |
| |
| // Protects all variables below. |
| mutable base::Lock lock_; |
| |
| // We maintain ownership of all workers. In some cases, we need to |
| // ensure shutdown occurs in an expected sequence by Stop()ing |
| // certain workers. They are guaranteed to be valid because we only |
| // destroy elements of |workers_| after the syncapi has been |
| // destroyed. Unless a worker is no longer needed because all types |
| // that get routed to it have been disabled (from syncing). In that |
| // case, we'll destroy on demand *after* routing any dependent types |
| // to syncer::GROUP_PASSIVE, so that the syncapi doesn't call into garbage. |
| // If a key is present, it means at least one ModelType that routes |
| // to that model safe group is being synced. |
| WorkerMap workers_; |
| syncer::ModelSafeRoutingInfo routing_info_; |
| |
| // The change processors that handle the different data types. |
| ProcessorMap processors_; |
| |
| // The types that were enabled as of the last configuration. Updated on each |
| // call to ConfigureDataTypes as well as SetInitialTypes. |
| syncer::ModelTypeSet last_configured_types_; |
| |
| // Parks stopped workers because they may still be referenced by syncer. |
| std::vector<scoped_refptr<syncer::ModelSafeWorker> > stopped_workers_; |
| |
| // Declare |sync_thread_| at the end so that it will be destroyed before |
| // objects above because tasks on sync thread depend on those objects, |
| // e.g. Shutdown() depends on |lock_|, SyncManager::Init() depends on |
| // workers, etc. |
| scoped_ptr<base::Thread> sync_thread_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar); |
| }; |
| |
| } // namespace browser_sync |
| |
| #endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_ |