Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2012 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 CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
      6 #define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
      7 
      8 #include <map>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/synchronization/lock.h"
     15 #include "base/threading/thread.h"
     16 #include "sync/internal_api/public/base/model_type.h"
     17 #include "sync/internal_api/public/engine/model_safe_worker.h"
     18 #include "sync/internal_api/public/sync_manager.h"
     19 
     20 class Profile;
     21 
     22 namespace base {
     23 class MessageLoop;
     24 }
     25 
     26 namespace syncer {
     27 struct UserShare;
     28 }  // namespace syncer
     29 
     30 namespace sync_driver {
     31 class ChangeProcessor;
     32 }
     33 
     34 namespace browser_sync {
     35 
     36 class UIModelWorker;
     37 
     38 // A class that keep track of the workers, change processors, and
     39 // routing info for the enabled sync types, and also routes change
     40 // events to the right processors.
     41 class SyncBackendRegistrar : public syncer::SyncManager::ChangeDelegate,
     42                              public syncer::WorkerLoopDestructionObserver {
     43  public:
     44   // |name| is used for debugging.  Does not take ownership of |profile| or
     45   // |sync_loop|.  Must be created on the UI thread.
     46   SyncBackendRegistrar(const std::string& name,
     47                        Profile* profile,
     48                        scoped_ptr<base::Thread> sync_thread);
     49 
     50   // SyncBackendRegistrar must be destroyed as follows:
     51   //
     52   //   1) On the UI thread, call RequestWorkerStopOnUIThread().
     53   //   2) UI posts task to shut down syncer on sync thread.
     54   //   3) If sync is disabled, call ReleaseSyncThread() on the UI thread.
     55   //   3) UI posts SyncBackendRegistrar::ShutDown() on sync thread to
     56   //      unregister workers from observing destruction of their working loops.
     57   //   4) Workers notify registrar when unregistration finishes or working
     58   //      loops are destroyed. Registrar destroys itself on last worker
     59   //      notification. Sync thread will be stopped if ownership was not
     60   //      released.
     61   virtual ~SyncBackendRegistrar();
     62 
     63   // Informs the SyncBackendRegistrar of the currently enabled set of types.
     64   // These types will be placed in the passive group.  This function should be
     65   // called exactly once during startup.
     66   void SetInitialTypes(syncer::ModelTypeSet initial_types);
     67 
     68   // Returns whether or not we are currently syncing encryption keys.
     69   // Must be called on the UI thread.
     70   bool IsNigoriEnabled() const;
     71 
     72   // Removes all types in |types_to_remove| from the routing info and
     73   // adds all the types in |types_to_add| to the routing info that are
     74   // not already there (initially put in the passive group).
     75   // |types_to_remove| and |types_to_add| must be disjoint.  Returns
     76   // the set of newly-added types.  Must be called on the UI thread.
     77   syncer::ModelTypeSet ConfigureDataTypes(
     78       syncer::ModelTypeSet types_to_add,
     79       syncer::ModelTypeSet types_to_remove);
     80 
     81   // Returns the set of enabled types as of the last configuration. Note that
     82   // this might be different from the current types in the routing info due
     83   // to DeactiveDataType being called separately from ConfigureDataTypes.
     84   syncer::ModelTypeSet GetLastConfiguredTypes() const;
     85 
     86   // Must be called from the UI thread. (See destructor comment.)
     87   void RequestWorkerStopOnUIThread();
     88 
     89   // Activates the given data type (which should belong to the given
     90   // group) and starts the given change processor.  Must be called
     91   // from |group|'s native thread.
     92   void ActivateDataType(syncer::ModelType type,
     93                         syncer::ModelSafeGroup group,
     94                         sync_driver::ChangeProcessor* change_processor,
     95                         syncer::UserShare* user_share);
     96 
     97   // Deactivates the given type if necessary.  Must be called from the
     98   // UI thread and not |type|'s native thread.  Yes, this is
     99   // surprising: see http://crbug.com/92804.
    100   void DeactivateDataType(syncer::ModelType type);
    101 
    102   // Returns true only between calls to ActivateDataType(type, ...)
    103   // and DeactivateDataType(type).  Used only by tests.
    104   bool IsTypeActivatedForTest(syncer::ModelType type) const;
    105 
    106   // SyncManager::ChangeDelegate implementation.  May be called from
    107   // any thread.
    108   virtual void OnChangesApplied(
    109       syncer::ModelType model_type,
    110       int64 model_version,
    111       const syncer::BaseTransaction* trans,
    112       const syncer::ImmutableChangeRecordList& changes) OVERRIDE;
    113   virtual void OnChangesComplete(syncer::ModelType model_type) OVERRIDE;
    114 
    115   void GetWorkers(std::vector<scoped_refptr<syncer::ModelSafeWorker> >* out);
    116   void GetModelSafeRoutingInfo(syncer::ModelSafeRoutingInfo* out);
    117 
    118   // syncer::WorkerLoopDestructionObserver implementation.
    119   virtual void OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) OVERRIDE;
    120 
    121   // Release ownership of |sync_thread_|. Called when sync is disabled.
    122   scoped_ptr<base::Thread> ReleaseSyncThread();
    123 
    124   // Unregister workers from loop destruction observation.
    125   void Shutdown();
    126 
    127   base::Thread* sync_thread();
    128 
    129  private:
    130   typedef std::map<syncer::ModelSafeGroup,
    131       scoped_refptr<syncer::ModelSafeWorker> > WorkerMap;
    132   typedef std::map<syncer::ModelType, sync_driver::ChangeProcessor*>
    133       ProcessorMap;
    134 
    135   // Callback after workers unregister from observing destruction of their
    136   // working loops.
    137   void OnWorkerUnregistrationDone(syncer::ModelSafeGroup group);
    138 
    139   void RemoveWorker(syncer::ModelSafeGroup group);
    140 
    141   // Returns the change processor for the given model, or NULL if none
    142   // exists.  Must be called from |group|'s native thread.
    143   sync_driver::ChangeProcessor* GetProcessor(syncer::ModelType type) const;
    144 
    145   // Must be called with |lock_| held.  Simply returns the change
    146   // processor for the given type, if it exists.  May be called from
    147   // any thread.
    148   sync_driver::ChangeProcessor* GetProcessorUnsafe(
    149       syncer::ModelType type) const;
    150 
    151   // Return true if |model_type| lives on the current thread.  Must be
    152   // called with |lock_| held.  May be called on any thread.
    153   bool IsCurrentThreadSafeForModel(
    154       syncer::ModelType model_type) const;
    155 
    156   // Name used for debugging.
    157   const std::string name_;
    158 
    159   Profile* const profile_;
    160 
    161   // Protects all variables below.
    162   mutable base::Lock lock_;
    163 
    164   // We maintain ownership of all workers.  In some cases, we need to
    165   // ensure shutdown occurs in an expected sequence by Stop()ing
    166   // certain workers.  They are guaranteed to be valid because we only
    167   // destroy elements of |workers_| after the syncapi has been
    168   // destroyed.  Unless a worker is no longer needed because all types
    169   // that get routed to it have been disabled (from syncing). In that
    170   // case, we'll destroy on demand *after* routing any dependent types
    171   // to syncer::GROUP_PASSIVE, so that the syncapi doesn't call into garbage.
    172   // If a key is present, it means at least one ModelType that routes
    173   // to that model safe group is being synced.
    174   WorkerMap workers_;
    175   syncer::ModelSafeRoutingInfo routing_info_;
    176 
    177   // The change processors that handle the different data types.
    178   ProcessorMap processors_;
    179 
    180   // The types that were enabled as of the last configuration. Updated on each
    181   // call to ConfigureDataTypes as well as SetInitialTypes.
    182   syncer::ModelTypeSet last_configured_types_;
    183 
    184   // Parks stopped workers because they may still be referenced by syncer.
    185   std::vector<scoped_refptr<syncer::ModelSafeWorker> > stopped_workers_;
    186 
    187   // Declare |sync_thread_| at the end so that it will be destroyed before
    188   // objects above because tasks on sync thread depend on those objects,
    189   // e.g. Shutdown() depends on |lock_|, SyncManager::Init() depends on
    190   // workers, etc.
    191   scoped_ptr<base::Thread> sync_thread_;
    192 
    193   DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar);
    194 };
    195 
    196 }  // namespace browser_sync
    197 
    198 #endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
    199