blob: ce36f985af892bad93cd9fe25e8c1ee6f87347ce [file] [log] [blame]
[email protected]132c85652009-08-05 01:18:271// Copyright (c) 2006-2008 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
[email protected]132c85652009-08-05 01:18:275#ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_
6#define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_
7
8#include <string>
9#include <map>
[email protected]132c85652009-08-05 01:18:2710
11#include "base/basictypes.h"
[email protected]132c85652009-08-05 01:18:2712#include "base/observer_list.h"
13#include "base/scoped_ptr.h"
[email protected]4aea04a2010-02-10 20:13:4314#include "base/time.h"
[email protected]712257e2009-11-11 22:57:4615#include "chrome/browser/google_service_auth_error.h"
[email protected]4aea04a2010-02-10 20:13:4316#include "chrome/browser/profile.h"
[email protected]72a31b42010-02-17 22:26:3317#include "chrome/browser/sync/glue/data_type_controller.h"
[email protected]132c85652009-08-05 01:18:2718#include "chrome/browser/sync/glue/sync_backend_host.h"
[email protected]93d960ce2010-02-11 04:27:0019#include "chrome/browser/sync/notification_method.h"
[email protected]d80033e2009-10-16 10:32:0420#include "chrome/browser/sync/sync_setup_wizard.h"
[email protected]4aea04a2010-02-10 20:13:4321#include "chrome/browser/sync/syncable/model_type.h"
[email protected]132c85652009-08-05 01:18:2722#include "googleurl/src/gurl.h"
[email protected]8cb5d5b2010-02-09 11:36:1623#include "testing/gtest/include/gtest/gtest_prod.h"
[email protected]132c85652009-08-05 01:18:2724
[email protected]132c85652009-08-05 01:18:2725namespace browser_sync {
[email protected]db1df0f2009-08-18 22:36:0526
[email protected]4aea04a2010-02-10 20:13:4327class ChangeProcessor;
[email protected]4aea04a2010-02-10 20:13:4328
[email protected]db1df0f2009-08-18 22:36:0529class UnrecoverableErrorHandler {
30 public:
31 // Call this when normal operation detects that the bookmark model and the
32 // syncer model are inconsistent, or similar. The ProfileSyncService will
33 // try to avoid doing any work to avoid crashing or corrupting things
34 // further, and will report an error status if queried.
35 virtual void OnUnrecoverableError() = 0;
36 protected:
37 virtual ~UnrecoverableErrorHandler() { }
38};
39
[email protected]132c85652009-08-05 01:18:2740}
41
42// Various UI components such as the New Tab page can be driven by observing
43// the ProfileSyncService through this interface.
44class ProfileSyncServiceObserver {
45 public:
46 // When one of the following events occurs, OnStateChanged() is called.
47 // Observers should query the service to determine what happened.
48 // - We initialized successfully.
49 // - There was an authentication error and the user needs to reauthenticate.
50 // - The sync servers are unavailable at this time.
51 // - Credentials are now in flight for authentication.
52 virtual void OnStateChanged() = 0;
53 protected:
54 virtual ~ProfileSyncServiceObserver() { }
55};
56
57// ProfileSyncService is the layer between browser subsystems like bookmarks,
58// and the sync backend.
[email protected]4aea04a2010-02-10 20:13:4359class ProfileSyncService : public browser_sync::SyncFrontend,
[email protected]db1df0f2009-08-18 22:36:0560 public browser_sync::UnrecoverableErrorHandler {
[email protected]132c85652009-08-05 01:18:2761 public:
[email protected]132c85652009-08-05 01:18:2762 typedef ProfileSyncServiceObserver Observer;
63 typedef browser_sync::SyncBackendHost::Status Status;
64
[email protected]1f97a112009-08-11 02:17:0665 enum SyncEventCodes {
66 MIN_SYNC_EVENT_CODE = 0,
67
68 // Events starting the sync service.
69 START_FROM_NTP = 1, // Sync was started from the ad in NTP
70 START_FROM_WRENCH = 2, // Sync was started from the Wrench menu.
71 START_FROM_OPTIONS = 3, // Sync was started from Wrench->Options.
[email protected]b220d13f2009-10-09 04:12:4672 START_FROM_BOOKMARK_MANAGER = 4, // Sync was started from Bookmark manager.
[email protected]1f97a112009-08-11 02:17:0673
74 // Events regarding cancelation of the signon process of sync.
[email protected]8ac2dc112009-10-01 23:19:1375 CANCEL_FROM_SIGNON_WITHOUT_AUTH = 10, // Cancelled before submitting
[email protected]1f97a112009-08-11 02:17:0676 // username and password.
77 CANCEL_DURING_SIGNON = 11, // Cancelled after auth.
78 CANCEL_DURING_SIGNON_AFTER_MERGE = 12, // Cancelled during merge.
79
80 // Events resulting in the stoppage of sync service.
81 STOP_FROM_OPTIONS = 20, // Sync was stopped from Wrench->Options.
82
83 // Miscellaneous events caused by sync service.
84 MERGE_AND_SYNC_NEEDED = 30,
85
86 MAX_SYNC_EVENT_CODE
87 };
88
[email protected]72a31b42010-02-17 22:26:3389 ProfileSyncService(Profile* profile, bool bootstrap_sync_authentication);
[email protected]132c85652009-08-05 01:18:2790 virtual ~ProfileSyncService();
91
92 // Initializes the object. This should be called every time an object of this
93 // class is constructed.
94 void Initialize();
95
[email protected]4aea04a2010-02-10 20:13:4396 // Registers a data type controller with the sync service. This
97 // makes the data type controller available for use, it does not
98 // enable or activate the synchronization of the data type (see
99 // ActivateDataType). Takes ownership of the pointer.
100 void RegisterDataTypeController(
101 browser_sync::DataTypeController* data_type_controller);
102
[email protected]72a31b42010-02-17 22:26:33103 const browser_sync::DataTypeController::TypeMap& data_type_controllers()
104 const {
[email protected]4aea04a2010-02-10 20:13:43105 return data_type_controllers_;
106 }
107
[email protected]132c85652009-08-05 01:18:27108 // Enables/disables sync for user.
109 virtual void EnableForUser();
110 virtual void DisableForUser();
111
112 // Whether sync is enabled by user or not.
[email protected]48352c12009-08-15 01:19:11113 bool HasSyncSetupCompleted() const;
114 void SetSyncSetupCompleted();
[email protected]132c85652009-08-05 01:18:27115
[email protected]132c85652009-08-05 01:18:27116 // SyncFrontend implementation.
117 virtual void OnBackendInitialized();
118 virtual void OnSyncCycleCompleted();
119 virtual void OnAuthError();
[email protected]132c85652009-08-05 01:18:27120
121 // Called when a user enters credentials through UI.
122 virtual void OnUserSubmittedAuth(const std::string& username,
[email protected]1fc9b3f2009-11-12 21:22:09123 const std::string& password,
124 const std::string& captcha);
[email protected]132c85652009-08-05 01:18:27125
126 // Called when a user decides whether to merge and sync or abort.
127 virtual void OnUserAcceptedMergeAndSync();
128
129 // Called when a user cancels any setup dialog (login, merge and sync, etc).
130 virtual void OnUserCancelledDialog();
131
132 // Get various information for displaying in the user interface.
133 browser_sync::SyncBackendHost::StatusSummary QuerySyncStatusSummary();
134 browser_sync::SyncBackendHost::Status QueryDetailedSyncStatus();
135
[email protected]712257e2009-11-11 22:57:46136 const GoogleServiceAuthError& GetAuthError() const {
[email protected]132c85652009-08-05 01:18:27137 return last_auth_error_;
138 }
139
140 // Displays a dialog for the user to enter GAIA credentials and attempt
141 // re-authentication, and returns true if it actually opened the dialog.
142 // Returns false if a dialog is already showing, an auth attempt is in
143 // progress, the sync system is already authenticated, or some error
144 // occurred preventing the action. We make it the duty of ProfileSyncService
145 // to open the dialog to easily ensure only one is ever showing.
146 bool SetupInProgress() const {
[email protected]48352c12009-08-15 01:19:11147 return !HasSyncSetupCompleted() && WizardIsVisible();
[email protected]132c85652009-08-05 01:18:27148 }
[email protected]44b78f90a2009-10-15 17:32:20149 bool WizardIsVisible() const {
150 return wizard_.IsVisible();
151 }
[email protected]132c85652009-08-05 01:18:27152 void ShowLoginDialog();
153
154 // Pretty-printed strings for a given StatusSummary.
155 static std::wstring BuildSyncStatusSummaryText(
156 const browser_sync::SyncBackendHost::StatusSummary& summary);
157
158 // Returns true if the SyncBackendHost has told us it's ready to accept
159 // changes.
160 // TODO(timsteele): What happens if the bookmark model is loaded, a change
161 // takes place, and the backend isn't initialized yet?
162 bool sync_initialized() const { return backend_initialized_; }
[email protected]fb42c982009-09-16 22:33:33163 bool unrecoverable_error_detected() const {
164 return unrecoverable_error_detected_;
165 }
[email protected]132c85652009-08-05 01:18:27166
167 bool UIShouldDepictAuthInProgress() const {
168 return is_auth_in_progress_;
169 }
170
171 // A timestamp marking the last time the service observed a transition from
172 // the SYNCING state to the READY state. Note that this does not reflect the
173 // last time we polled the server to see if there were any changes; the
174 // timestamp is only snapped when syncing takes place and we download or
175 // upload some bookmark entity.
176 const base::Time& last_synced_time() const { return last_synced_time_; }
177
178 // Returns a user-friendly string form of last synced time (in minutes).
179 std::wstring GetLastSyncedTimeString() const;
180
181 // Returns the authenticated username of the sync user, or empty if none
182 // exists. It will only exist if the authentication service provider (e.g
183 // GAIA) has confirmed the username is authentic.
184 virtual string16 GetAuthenticatedUsername() const;
185
186 const std::string& last_attempted_user_email() const {
187 return last_attempted_user_email_;
188 }
189
190 // The profile we are syncing for.
191 Profile* profile() { return profile_; }
192
193 // Adds/removes an observer. ProfileSyncService does not take ownership of
194 // the observer.
195 void AddObserver(Observer* observer);
196 void RemoveObserver(Observer* observer);
197
[email protected]1f97a112009-08-11 02:17:06198 // Record stats on various events.
199 static void SyncEvent(SyncEventCodes code);
200
[email protected]eec3bcfa2009-11-12 17:23:43201 // Returns whether sync is enabled. Sync can be enabled/disabled both
202 // at compile time (e.g., on a per-OS basis) or at run time (e.g.,
203 // command-line switches).
204 static bool IsSyncEnabled();
205
[email protected]db1df0f2009-08-18 22:36:05206 // UnrecoverableErrorHandler implementation.
207 virtual void OnUnrecoverableError();
208
209 browser_sync::SyncBackendHost* backend() { return backend_.get(); }
210
[email protected]4aea04a2010-02-10 20:13:43211 virtual void ActivateDataType(
212 browser_sync::DataTypeController* data_type_controller,
213 browser_sync::ChangeProcessor* change_processor);
214 virtual void DeactivateDataType(
215 browser_sync::DataTypeController* data_type_controller,
216 browser_sync::ChangeProcessor* change_processor);
217
[email protected]132c85652009-08-05 01:18:27218 protected:
219 // Call this after any of the subsystems being synced (the bookmark
220 // model and the sync backend) finishes its initialization. When everything
221 // is ready, this function will bootstrap the subsystems so that they are
222 // initially in sync, and start forwarding changes between the two models.
223 void StartProcessingChangesIfReady();
224
[email protected]132c85652009-08-05 01:18:27225 // Returns whether processing changes is allowed. Check this before doing
226 // any model-modifying operations.
227 bool ShouldPushChanges();
228
229 // Starts up the backend sync components.
230 void StartUp();
231 // Shuts down the backend sync components.
232 // |sync_disabled| indicates if syncing is being disabled or not.
233 void Shutdown(bool sync_disabled);
234
[email protected]48352c12009-08-15 01:19:11235 // Methods to register and remove preferences.
236 void RegisterPreferences();
237 void ClearPreferences();
238
[email protected]4aea04a2010-02-10 20:13:43239 void BookmarkStartCallback(
240 browser_sync::DataTypeController::StartResult result);
[email protected]72a31b42010-02-17 22:26:33241 void PreferenceStartCallback(
242 browser_sync::DataTypeController::StartResult result);
[email protected]4aea04a2010-02-10 20:13:43243
[email protected]9b3f2ae2010-01-29 01:56:00244 // Tests need to override this. If |delete_sync_data_folder| is true, then
245 // this method will delete all previous "Sync Data" folders. (useful if the
246 // folder is partial/corrupt)
247 virtual void InitializeBackend(bool delete_sync_data_folder);
[email protected]132c85652009-08-05 01:18:27248
[email protected]132c85652009-08-05 01:18:27249 // We keep track of the last auth error observed so we can cover up the first
250 // "expected" auth failure from observers.
251 // TODO(timsteele): Same as expecting_first_run_auth_needed_event_. Remove
252 // this!
[email protected]712257e2009-11-11 22:57:46253 GoogleServiceAuthError last_auth_error_;
[email protected]132c85652009-08-05 01:18:27254
255 // Cache of the last name the client attempted to authenticate.
256 std::string last_attempted_user_email_;
257
258 private:
[email protected]132c85652009-08-05 01:18:27259 friend class ProfileSyncServiceTest;
[email protected]65b3aa12010-02-22 22:49:00260 friend class ProfileSyncServicePreferenceTest;
[email protected]132c85652009-08-05 01:18:27261 friend class ProfileSyncServiceTestHarness;
[email protected]132c85652009-08-05 01:18:27262 FRIEND_TEST(ProfileSyncServiceTest, UnrecoverableErrorSuspendsService);
263
[email protected]132c85652009-08-05 01:18:27264 // Initializes the various settings from the command line.
265 void InitSettings();
266
[email protected]132c85652009-08-05 01:18:27267 // Sets the last synced time to the current time.
268 void UpdateLastSyncedTime();
269
[email protected]35e4c0d2009-12-01 00:39:53270 // When running inside Chrome OS, extract the LSID cookie from the cookie
271 // store to bootstrap the authentication process.
[email protected]72a31b42010-02-17 22:26:33272 virtual std::string GetLsidForAuthBootstraping();
273
274 // Stops a data type.
275 void StopDataType(syncable::ModelType model_type);
[email protected]35e4c0d2009-12-01 00:39:53276
[email protected]cb4c06e2009-08-22 00:24:39277 // Time at which we begin an attempt a GAIA authorization.
278 base::TimeTicks auth_start_time_;
279
280 // Time at which error UI is presented for the new tab page.
[email protected]1f97a112009-08-11 02:17:06281 base::TimeTicks auth_error_time_;
282
[email protected]132c85652009-08-05 01:18:27283 // The profile whose data we are synchronizing.
284 Profile* profile_;
285
[email protected]72a31b42010-02-17 22:26:33286 // True if the profile sync service should attempt to use an LSID
287 // cookie for authentication. This is typically set to true in
288 // ChromiumOS since we want to use the system level authentication
289 // for sync.
290 bool bootstrap_sync_authentication_;
291
[email protected]132c85652009-08-05 01:18:27292 // TODO(ncarter): Put this in a profile, once there is UI for it.
293 // This specifies where to find the sync server.
294 GURL sync_service_url_;
295
[email protected]132c85652009-08-05 01:18:27296 // The last time we detected a successful transition from SYNCING state.
297 // Our backend notifies us whenever we should take a new snapshot.
298 base::Time last_synced_time_;
299
300 // Our asynchronous backend to communicate with sync components living on
301 // other threads.
302 scoped_ptr<browser_sync::SyncBackendHost> backend_;
303
[email protected]4aea04a2010-02-10 20:13:43304 // List of available data type controllers.
[email protected]72a31b42010-02-17 22:26:33305 browser_sync::DataTypeController::TypeMap data_type_controllers_;
[email protected]db1df0f2009-08-18 22:36:05306
[email protected]132c85652009-08-05 01:18:27307 // Whether the SyncBackendHost has been initialized.
308 bool backend_initialized_;
309
310 // Set to true when the user first enables sync, and we are waiting for
311 // syncapi to give us the green light on providing credentials for the first
312 // time. It is set back to false as soon as we get this message, and is
313 // false all other times so we don't have to persist this value as it will
314 // get initialized to false.
315 // TODO(timsteele): Remove this by way of starting the wizard when enabling
316 // sync *before* initializing the backend. syncapi will need to change, but
317 // it means we don't have to wait for the first AuthError; if we ever get
318 // one, it is actually an error and this bool isn't needed.
319 bool expecting_first_run_auth_needed_event_;
320
321 // Various pieces of UI query this value to determine if they should show
322 // an "Authenticating.." type of message. We are the only central place
323 // all auth attempts funnel through, so it makes sense to provide this.
324 // As its name suggests, this should NOT be used for anything other than UI.
325 bool is_auth_in_progress_;
326
[email protected]44b78f90a2009-10-15 17:32:20327 SyncSetupWizard wizard_;
328
[email protected]132c85652009-08-05 01:18:27329 // True if an unrecoverable error (e.g. violation of an assumed invariant)
330 // occurred during syncer operation. This value should be checked before
331 // doing any work that might corrupt things further.
332 bool unrecoverable_error_detected_;
333
[email protected]72a31b42010-02-17 22:26:33334 // True if at least one of the data types started up was started for
335 // the first time. TODO(sync): Remove this when we have full
336 // support for starting multiple data types.
337 bool startup_had_first_time_;
338
[email protected]93d960ce2010-02-11 04:27:00339 // Which peer-to-peer notification method to use.
340 browser_sync::NotificationMethod notification_method_;
341
[email protected]132c85652009-08-05 01:18:27342 ObserverList<Observer> observers_;
343
344 DISALLOW_COPY_AND_ASSIGN(ProfileSyncService);
345};
346
347#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_