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_DATA_TYPE_CONTROLLER_H__
6#define CHROME_BROWSER_SYNC_GLUE_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/sequenced_task_runner_helpers.h"
14#include "chrome/browser/sync/glue/data_type_error_handler.h"
15#include "content/public/browser/browser_thread.h"
16#include "sync/api/sync_merge_result.h"
17#include "sync/internal_api/public/base/model_type.h"
18#include "sync/internal_api/public/engine/model_safe_worker.h"
19#include "sync/internal_api/public/util/unrecoverable_error_handler.h"
20
21namespace syncer {
22class SyncError;
23}
24
25namespace browser_sync {
26
27// Data type controllers need to be refcounted threadsafe, as they may
28// need to run model associator or change processor on other threads.
29class DataTypeController
30    : public base::RefCountedThreadSafe<
31          DataTypeController, content::BrowserThread::DeleteOnUIThread>,
32      public DataTypeErrorHandler {
33 public:
34  enum State {
35    NOT_RUNNING,    // The controller has never been started or has
36                    // previously been stopped.  Must be in this state to start.
37    MODEL_STARTING, // The controller is waiting on dependent services
38                    // that need to be available before model
39                    // association.
40    MODEL_LOADED,   // The model has finished loading and can start
41                    // associating now.
42    ASSOCIATING,    // Model association is in progress.
43    RUNNING,        // The controller is running and the data type is
44                    // in sync with the cloud.
45    STOPPING,       // The controller is in the process of stopping
46                    // and is waiting for dependent services to stop.
47    DISABLED        // The controller was started but encountered an error
48                    // so it is disabled waiting for it to be stopped.
49  };
50
51  enum StartResult {
52    OK,                   // The data type has started normally.
53    OK_FIRST_RUN,         // Same as OK, but sent on first successful
54                          // start for this type for this user as
55                          // determined by cloud state.
56    BUSY,                 // Start() was called while already in progress.
57    NOT_ENABLED,          // This data type is not enabled for the current user.
58    ASSOCIATION_FAILED,   // An error occurred during model association.
59    ABORTED,              // Start was aborted by calling Stop().
60    UNRECOVERABLE_ERROR,  // An unrecoverable error occured.
61    NEEDS_CRYPTO,         // The data type cannot be started yet because it
62                          // depends on the cryptographer.
63    MAX_START_RESULT
64  };
65
66  typedef base::Callback<void(StartResult,
67                              const syncer::SyncMergeResult&,
68                              const syncer::SyncMergeResult&)> StartCallback;
69
70  typedef base::Callback<void(syncer::ModelType,
71                              syncer::SyncError)> ModelLoadCallback;
72
73  typedef std::map<syncer::ModelType,
74                   scoped_refptr<DataTypeController> > TypeMap;
75  typedef std::map<syncer::ModelType, DataTypeController::State> StateMap;
76
77  // Returns true if the start result should trigger an unrecoverable error.
78  // Public so unit tests can use this function as well.
79  static bool IsUnrecoverableResult(StartResult result);
80
81  // Returns true if the datatype started successfully.
82  static bool IsSuccessfulResult(StartResult result);
83
84  // Begins asynchronous operation of loading the model to get it ready for
85  // model association. Once the models are loaded the callback will be invoked
86  // with the result. If the models are already loaded it is safe to call the
87  // callback right away. Else the callback needs to be stored and called when
88  // the models are ready.
89  virtual void LoadModels(const ModelLoadCallback& model_load_callback) = 0;
90
91  // Will start a potentially asynchronous operation to perform the
92  // model association. Once the model association is done the callback will
93  // be invoked.
94  virtual void StartAssociating(const StartCallback& start_callback) = 0;
95
96  // Synchronously stops the data type. If StartAssociating has already been
97  // called but is not done yet it will be aborted. Similarly if LoadModels
98  // has not completed it will also be aborted.
99  virtual void Stop() = 0;
100
101  // Unique model type for this data type controller.
102  virtual syncer::ModelType type() const = 0;
103
104  // Name of this data type.  For logging purposes only.
105  virtual std::string name() const = 0;
106
107  // The model safe group of this data type.  This should reflect the
108  // thread that should be used to modify the data type's native
109  // model.
110  virtual syncer::ModelSafeGroup model_safe_group() const = 0;
111
112  // Current state of the data type controller.
113  virtual State state() const = 0;
114
115  // Partial implementation of DataTypeErrorHandler.
116  // This is thread safe.
117  virtual syncer::SyncError CreateAndUploadError(
118      const tracked_objects::Location& location,
119      const std::string& message,
120      syncer::ModelType type) OVERRIDE;
121
122 protected:
123  friend struct content::BrowserThread::DeleteOnThread<
124      content::BrowserThread::UI>;
125  friend class base::DeleteHelper<DataTypeController>;
126
127  // If the DTC is waiting for models to load, once the models are
128  // loaded the datatype service will call this function on DTC to let
129  // us know that it is safe to start associating.
130  virtual void OnModelLoaded() = 0;
131
132  virtual ~DataTypeController() {}
133
134  // Handles the reporting of unrecoverable error. It records stuff in
135  // UMA and reports to breakpad.
136  // Virtual for testing purpose.
137  virtual void RecordUnrecoverableError(
138      const tracked_objects::Location& from_here,
139      const std::string& message);
140};
141
142}  // namespace browser_sync
143
144#endif  // CHROME_BROWSER_SYNC_GLUE_DATA_TYPE_CONTROLLER_H__
145