• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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 COMPONENTS_SYNC_DRIVER_DATA_TYPE_CONTROLLER_H__
6 #define COMPONENTS_SYNC_DRIVER_DATA_TYPE_CONTROLLER_H__
7 
8 #include <map>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/ref_counted_delete_on_message_loop.h"
15 #include "base/sequenced_task_runner_helpers.h"
16 #include "components/sync_driver/data_type_error_handler.h"
17 #include "sync/api/sync_merge_result.h"
18 #include "sync/internal_api/public/base/model_type.h"
19 #include "sync/internal_api/public/engine/model_safe_worker.h"
20 #include "sync/internal_api/public/util/unrecoverable_error_handler.h"
21 
22 namespace syncer {
23 class SyncError;
24 struct UserShare;
25 }
26 
27 namespace browser_sync {
28 
29 class ChangeProcessor;
30 
31 // Data type controllers need to be refcounted threadsafe, as they may
32 // need to run model associator or change processor on other threads.
33 class DataTypeController
34     : public base::RefCountedDeleteOnMessageLoop<DataTypeController>,
35       public DataTypeErrorHandler {
36  public:
37   enum State {
38     NOT_RUNNING,    // The controller has never been started or has
39                     // previously been stopped.  Must be in this state to start.
40     MODEL_STARTING, // The controller is waiting on dependent services
41                     // that need to be available before model
42                     // association.
43     MODEL_LOADED,   // The model has finished loading and can start
44                     // associating now.
45     ASSOCIATING,    // Model association is in progress.
46     RUNNING,        // The controller is running and the data type is
47                     // in sync with the cloud.
48     STOPPING,       // The controller is in the process of stopping
49                     // and is waiting for dependent services to stop.
50     DISABLED        // The controller was started but encountered an error
51                     // so it is disabled waiting for it to be stopped.
52   };
53 
54   enum StartResult {
55     OK,                   // The data type has started normally.
56     OK_FIRST_RUN,         // Same as OK, but sent on first successful
57                           // start for this type for this user as
58                           // determined by cloud state.
59     ASSOCIATION_FAILED,   // An error occurred during model association.
60     ABORTED,              // Start was aborted by calling Stop().
61     UNRECOVERABLE_ERROR,  // An unrecoverable error occured.
62     NEEDS_CRYPTO,         // The data type cannot be started yet because it
63                           // depends on the cryptographer.
64     MAX_START_RESULT
65   };
66 
67   typedef base::Callback<void(StartResult,
68                               const syncer::SyncMergeResult&,
69                               const syncer::SyncMergeResult&)> StartCallback;
70 
71   typedef base::Callback<void(syncer::ModelType,
72                               syncer::SyncError)> ModelLoadCallback;
73 
74   typedef base::Callback<void(const tracked_objects::Location& location,
75                               const std::string&)> DisableTypeCallback;
76 
77   typedef std::map<syncer::ModelType,
78                    scoped_refptr<DataTypeController> > TypeMap;
79   typedef std::map<syncer::ModelType, DataTypeController::State> StateMap;
80 
81   // Returns true if the start result should trigger an unrecoverable error.
82   // Public so unit tests can use this function as well.
83   static bool IsUnrecoverableResult(StartResult result);
84 
85   // Returns true if the datatype started successfully.
86   static bool IsSuccessfulResult(StartResult result);
87 
88   // Begins asynchronous operation of loading the model to get it ready for
89   // model association. Once the models are loaded the callback will be invoked
90   // with the result. If the models are already loaded it is safe to call the
91   // callback right away. Else the callback needs to be stored and called when
92   // the models are ready.
93   virtual void LoadModels(const ModelLoadCallback& model_load_callback) = 0;
94 
95   // Will start a potentially asynchronous operation to perform the
96   // model association. Once the model association is done the callback will
97   // be invoked.
98   virtual void StartAssociating(const StartCallback& start_callback) = 0;
99 
100   // Synchronously stops the data type. If StartAssociating has already been
101   // called but is not done yet it will be aborted. Similarly if LoadModels
102   // has not completed it will also be aborted.
103   // NOTE: Stop() should be called after sync backend machinery has stopped
104   // routing changes to this data type. Stop() should ensure the data type
105   // logic shuts down gracefully by flushing remaining changes and calling
106   // StopSyncing on the SyncableService. This assumes no changes will ever
107   // propagate from sync again from point where Stop() is called.
108   virtual void Stop() = 0;
109 
110   // Unique model type for this data type controller.
111   virtual syncer::ModelType type() const = 0;
112 
113   // Name of this data type.  For logging purposes only.
114   virtual std::string name() const = 0;
115 
116   // The model safe group of this data type.  This should reflect the
117   // thread that should be used to modify the data type's native
118   // model.
119   virtual syncer::ModelSafeGroup model_safe_group() const = 0;
120 
121   // Access to the ChangeProcessor for the type being controlled by |this|.
122   // Returns NULL if the ChangeProcessor isn't created or connected.
123   virtual ChangeProcessor* GetChangeProcessor() const = 0;
124 
125   // Current state of the data type controller.
126   virtual State state() const = 0;
127 
128   // Partial implementation of DataTypeErrorHandler.
129   // This is thread safe.
130   virtual syncer::SyncError CreateAndUploadError(
131       const tracked_objects::Location& location,
132       const std::string& message,
133       syncer::ModelType type) OVERRIDE;
134 
135   // Called when the sync backend has initialized. |share| is the
136   // UserShare handle to associate model data with.
137   void OnUserShareReady(syncer::UserShare* share);
138 
139   // Whether the DataTypeController is ready to start. This is useful if the
140   // datatype itself must make the decision about whether it should be enabled
141   // at all (and therefore whether the initial download of the sync data for
142   // the type should be performed).
143   // Returns true by default.
144   virtual bool ReadyForStart() const;
145 
146  protected:
147   friend class base::RefCountedDeleteOnMessageLoop<DataTypeController>;
148   friend class base::DeleteHelper<DataTypeController>;
149 
150   DataTypeController(scoped_refptr<base::MessageLoopProxy> ui_thread,
151                      const base::Closure& error_callback,
152                      const DisableTypeCallback& disable_callback);
153 
154   // If the DTC is waiting for models to load, once the models are
155   // loaded the datatype service will call this function on DTC to let
156   // us know that it is safe to start associating.
157   virtual void OnModelLoaded() = 0;
158 
159   virtual ~DataTypeController();
160 
161   syncer::UserShare* user_share() const;
162   DisableTypeCallback disable_callback();
163 
164   // The callback that will be invoked when an unrecoverable error occurs.
165   // TODO(sync): protected for use by legacy controllers.
166   base::Closure error_callback_;
167 
168  private:
169   // TODO(tim): Bug 383480. Do we need two callbacks?
170   DisableTypeCallback disable_callback_;
171 
172   syncer::UserShare* user_share_;
173 };
174 
175 }  // namespace browser_sync
176 
177 #endif  // COMPONENTS_SYNC_DRIVER_DATA_TYPE_CONTROLLER_H__
178