summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/glue/sync_backend_registrar.h
blob: 44883312635b1fbd3cd77d538b5eb7d7ddd52261 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// 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_
#pragma once

#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 "sync/internal_api/public/engine/model_safe_worker.h"
#include "sync/internal_api/public/syncable/model_type.h"
#include "sync/internal_api/sync_manager.h"

class MessageLoop;
class Profile;

namespace sync_api {
struct UserShare;
}  // namespace sync_api

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 sync_api::SyncManager::ChangeDelegate {
 public:
  // |initial_types| contains the initial set of types to sync
  // (initially put in the passive group).  |name| is used for
  // debugging.  Does not take ownership of |profile| or |sync_loop|.
  // Must be created on the UI thread.
  SyncBackendRegistrar(syncable::ModelTypeSet initial_types,
                       const std::string& name,
                       Profile* profile,
                       MessageLoop* sync_loop);

  // SyncBackendRegistrar must be destroyed as follows:
  //
  //   1) On the sync thread, call OnSyncerShutdownComplete() after
  //      the syncer is shutdown.
  //   2) Meanwhile, on the UI thread, call StopOnUIThread(), which
  //      blocks until OnSyncerShutdownComplete() is called.
  //   3) Destroy the SyncBackendRegistrar.
  //
  // This is to handle the complicated shutdown requirements of the
  // UIModelWorker (since the UI thread is both the main thread and a
  // thread which the syncer pushes changes to).
  virtual ~SyncBackendRegistrar();

  // 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.
  syncable::ModelTypeSet ConfigureDataTypes(
      syncable::ModelTypeSet types_to_add,
      syncable::ModelTypeSet types_to_remove);

  // Must be called from the UI thread. (See destructor comment.)
  void StopOnUIThread();

  // Must be called from the sync thread. (See destructor comment.)
  void OnSyncerShutdownComplete();

  // 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(syncable::ModelType type,
                        ModelSafeGroup group,
                        ChangeProcessor* change_processor,
                        sync_api::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(syncable::ModelType type);

  // Returns true only between calls to ActivateDataType(type, ...)
  // and DeactivateDataType(type).  Used only by tests.
  bool IsTypeActivatedForTest(syncable::ModelType type) const;

  // SyncManager::ChangeDelegate implementation.  May be called from
  // any thread.
  virtual void OnChangesApplied(
      syncable::ModelType model_type,
      const sync_api::BaseTransaction* trans,
      const sync_api::ImmutableChangeRecordList& changes) OVERRIDE;
  virtual void OnChangesComplete(syncable::ModelType model_type) OVERRIDE;

  void GetWorkers(std::vector<ModelSafeWorker*>* out);
  void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out);

 private:
  typedef std::map<ModelSafeGroup,
                   scoped_refptr<ModelSafeWorker> > WorkerMap;

  // Returns the change processor for the given model, or NULL if none
  // exists.  Must be called from |group|'s native thread.
  ChangeProcessor* GetProcessor(syncable::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(syncable::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(
      syncable::ModelType model_type) const;

  // Name used for debugging.
  const std::string name_;

  Profile* const profile_;

  MessageLoop* const sync_loop_;

  const scoped_refptr<UIModelWorker> ui_worker_;

  bool stopped_on_ui_thread_;

  // 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 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_;
  ModelSafeRoutingInfo routing_info_;

  // The change processors that handle the different data types.
  std::map<syncable::ModelType, ChangeProcessor*> processors_;

  DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar);
};

}  // namespace browser_sync

#endif  // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_