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_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
6#define CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/callback_forward.h"
12#include "base/compiler_specific.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/synchronization/lock.h"
15#include "base/synchronization/waitable_event.h"
16#include "chrome/browser/sync/profile_sync_components_factory.h"
17#include "components/sync_driver/data_type_controller.h"
18#include "components/sync_driver/data_type_error_handler.h"
19
20class Profile;
21class ProfileSyncService;
22class ProfileSyncComponentsFactory;
23
24namespace base {
25class TimeDelta;
26}
27
28namespace syncer {
29class SyncError;
30}
31
32namespace sync_driver {
33class AssociatorInterface;
34class ChangeProcessor;
35}
36
37namespace browser_sync {
38
39// Implementation for datatypes that do not reside on the frontend thread
40// (UI thread). This is the same thread we perform initialization
41// on, so we don't have to worry about thread safety. The main start/stop
42// functionality is implemented by default. Derived classes must implement:
43//    type()
44//    model_safe_group()
45//    PostTaskOnBackendThread()
46//    CreateSyncComponents()
47class NonFrontendDataTypeController : public sync_driver::DataTypeController {
48 public:
49  // For creating non-frontend processor/associator and associating on backend.
50  class BackendComponentsContainer;
51
52  NonFrontendDataTypeController(
53      scoped_refptr<base::MessageLoopProxy> ui_thread,
54      const base::Closure& error_callback,
55      ProfileSyncComponentsFactory* profile_sync_factory,
56      Profile* profile,
57      ProfileSyncService* sync_service);
58
59  // DataTypeController interface.
60  virtual void LoadModels(
61      const ModelLoadCallback& model_load_callback) OVERRIDE;
62  virtual void StartAssociating(const StartCallback& start_callback) OVERRIDE;
63  virtual void Stop() OVERRIDE;
64  virtual syncer::ModelType type() const = 0;
65  virtual syncer::ModelSafeGroup model_safe_group() const = 0;
66  virtual std::string name() const OVERRIDE;
67  virtual State state() const OVERRIDE;
68
69  // DataTypeErrorHandler interface.
70  // Note: this is performed on the datatype's thread.
71  virtual void OnSingleDataTypeUnrecoverableError(
72      const syncer::SyncError& error) OVERRIDE;
73
74  // Callback to receive background association results.
75  struct AssociationResult {
76    explicit AssociationResult(syncer::ModelType type);
77    ~AssociationResult();
78    bool needs_crypto;
79    bool unrecoverable_error;
80    bool sync_has_nodes;
81    syncer::SyncError error;
82    syncer::SyncMergeResult local_merge_result;
83    syncer::SyncMergeResult syncer_merge_result;
84    base::TimeDelta association_time;
85    sync_driver::ChangeProcessor* change_processor;
86    sync_driver::AssociatorInterface* model_associator;
87  };
88  void AssociationCallback(AssociationResult result);
89
90 protected:
91  // For testing only.
92  NonFrontendDataTypeController();
93
94  virtual ~NonFrontendDataTypeController();
95
96  // DataTypeController interface.
97  virtual void OnModelLoaded() OVERRIDE;
98
99  // Start any dependent services that need to be running before we can
100  // associate models. The default implementation is a no-op.
101  // Return value:
102  //   True - if models are ready and association can proceed.
103  //   False - if models are not ready. StartAssociationAsync should be called
104  //           when the models are ready.
105  // Note: this is performed on the frontend (UI) thread.
106  virtual bool StartModels();
107
108  // Posts the given task to the backend thread, i.e. the thread the
109  // datatype lives on.  Return value: True if task posted successfully,
110  // false otherwise.
111  // NOTE: The StopAssociationAsync() implementation relies on the fact that
112  // implementations of this API do not hold any references to the DTC while
113  // the task is executing. See http://crbug.com/127706.
114  virtual bool PostTaskOnBackendThread(
115      const tracked_objects::Location& from_here,
116      const base::Closure& task) = 0;
117
118  // Returns true if the current thread is the backend thread, i.e. the same
119  // thread used by |PostTaskOnBackendThread|. The default implementation just
120  // checks that the current thread is not the UI thread, but subclasses should
121  // override it appropriately.
122  virtual bool IsOnBackendThread();
123
124  // Datatype specific creation of sync components.
125  // Note: this is performed on the datatype's thread.
126  virtual ProfileSyncComponentsFactory::SyncComponents
127      CreateSyncComponents() = 0;
128
129  // Called on UI thread during shutdown to effectively disable processing
130  // any changes.
131  virtual void DisconnectProcessor(sync_driver::ChangeProcessor* processor) = 0;
132
133  // Start up complete, update the state and invoke the callback.
134  // Note: this is performed on the datatype's thread.
135  virtual void StartDone(
136      DataTypeController::ConfigureResult start_result,
137      const syncer::SyncMergeResult& local_merge_result,
138      const syncer::SyncMergeResult& syncer_merge_result);
139
140  // UI thread implementation of StartDone.
141  virtual void StartDoneImpl(
142      DataTypeController::ConfigureResult start_result,
143      DataTypeController::State new_state,
144      const syncer::SyncMergeResult& local_merge_result,
145      const syncer::SyncMergeResult& syncer_merge_result);
146
147  // The actual implementation of Disabling the datatype. This happens
148  // on the UI thread.
149  virtual void DisableImpl(const syncer::SyncError& error);
150
151  // Record association time. Called on Datatype's thread.
152  virtual void RecordAssociationTime(base::TimeDelta time);
153  // Record causes of start failure. Called on UI thread.
154  virtual void RecordStartFailure(ConfigureResult result);
155
156  // Handles the reporting of unrecoverable error. It records stuff in
157  // UMA and reports to breakpad.
158  // Virtual for testing purpose.
159  virtual void RecordUnrecoverableError(
160      const tracked_objects::Location& from_here,
161      const std::string& message);
162
163  // Accessors and mutators used by derived classes.
164  ProfileSyncComponentsFactory* profile_sync_factory() const;
165  Profile* profile() const;
166  ProfileSyncService* profile_sync_service() const;
167  void set_start_callback(const StartCallback& callback);
168  void set_state(State state);
169
170  virtual sync_driver::AssociatorInterface* associator() const;
171  virtual sync_driver::ChangeProcessor* GetChangeProcessor() const OVERRIDE;
172
173  State state_;
174  StartCallback start_callback_;
175  ModelLoadCallback model_load_callback_;
176
177 private:
178  friend class BackendComponentsContainer;
179  ProfileSyncComponentsFactory* const profile_sync_factory_;
180  Profile* const profile_;
181  ProfileSyncService* const profile_sync_service_;
182
183  // Created on UI thread and passed to backend to create processor/associator
184  // and associate model. Released on backend.
185  scoped_ptr<BackendComponentsContainer> components_container_;
186
187  sync_driver::AssociatorInterface* model_associator_;
188  sync_driver::ChangeProcessor* change_processor_;
189
190  base::WeakPtrFactory<NonFrontendDataTypeController> weak_ptr_factory_;
191
192  DISALLOW_COPY_AND_ASSIGN(NonFrontendDataTypeController);
193};
194
195}  // namespace browser_sync
196
197#endif  // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
198