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
20class Profile;
21
22namespace base {
23class MessageLoop;
24}
25
26namespace syncer {
27struct UserShare;
28}  // namespace syncer
29
30namespace sync_driver {
31class ChangeProcessor;
32}
33
34namespace browser_sync {
35
36class 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.
41class 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