| OLD | NEW |
| (Empty) |
| 1 // 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 | |
| 5 #ifdef CHROME_PERSONALIZATION | |
| 6 | |
| 7 #ifndef CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_ | |
| 8 #define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_ | |
| 9 | |
| 10 #include <string> | |
| 11 #include <map> | |
| 12 #include <vector> | |
| 13 | |
| 14 #include "base/basictypes.h" | |
| 15 #include "base/file_path.h" | |
| 16 #include "base/observer_list.h" | |
| 17 #include "base/scoped_ptr.h" | |
| 18 #include "chrome/browser/bookmarks/bookmark_model.h" | |
| 19 #include "chrome/browser/profile.h" | |
| 20 #include "chrome/browser/sync/glue/model_associator.h" | |
| 21 #include "chrome/browser/sync/glue/sync_backend_host.h" | |
| 22 #include "chrome/browser/views/sync/sync_setup_wizard.h" | |
| 23 #include "googleurl/src/gurl.h" | |
| 24 | |
| 25 class CommandLine; | |
| 26 class MessageLoop; | |
| 27 class Profile; | |
| 28 | |
| 29 namespace browser_sync { | |
| 30 class ModelAssociator; | |
| 31 } | |
| 32 | |
| 33 // Various UI components such as the New Tab page can be driven by observing | |
| 34 // the ProfileSyncService through this interface. | |
| 35 class ProfileSyncServiceObserver { | |
| 36 public: | |
| 37 // When one of the following events occurs, OnStateChanged() is called. | |
| 38 // Observers should query the service to determine what happened. | |
| 39 // - We initialized successfully. | |
| 40 // - There was an authentication error and the user needs to reauthenticate. | |
| 41 // - The sync servers are unavailable at this time. | |
| 42 // - Credentials are now in flight for authentication. | |
| 43 virtual void OnStateChanged() = 0; | |
| 44 protected: | |
| 45 virtual ~ProfileSyncServiceObserver() { } | |
| 46 }; | |
| 47 | |
| 48 // ProfileSyncService is the layer between browser subsystems like bookmarks, | |
| 49 // and the sync backend. | |
| 50 class ProfileSyncService : public BookmarkModelObserver, | |
| 51 public browser_sync::SyncFrontend { | |
| 52 public: | |
| 53 typedef ProfileSyncServiceObserver Observer; | |
| 54 typedef browser_sync::SyncBackendHost::Status Status; | |
| 55 | |
| 56 ProfileSyncService(Profile* profile); | |
| 57 virtual ~ProfileSyncService(); | |
| 58 | |
| 59 // Initializes the object. This should be called every time an object of this | |
| 60 // class is constructed. | |
| 61 void Initialize(); | |
| 62 | |
| 63 // Enables/disables sync for user. | |
| 64 virtual void EnableForUser(); | |
| 65 virtual void DisableForUser(); | |
| 66 | |
| 67 // Whether sync is enabled by user or not. | |
| 68 bool IsSyncEnabledByUser() const; | |
| 69 | |
| 70 // BookmarkModelObserver implementation. | |
| 71 virtual void Loaded(BookmarkModel* model); | |
| 72 virtual void BookmarkModelBeingDeleted(BookmarkModel* model) {} | |
| 73 virtual void BookmarkNodeMoved(BookmarkModel* model, | |
| 74 const BookmarkNode* old_parent, | |
| 75 int old_index, | |
| 76 const BookmarkNode* new_parent, | |
| 77 int new_index); | |
| 78 virtual void BookmarkNodeAdded(BookmarkModel* model, | |
| 79 const BookmarkNode* parent, | |
| 80 int index); | |
| 81 virtual void BookmarkNodeRemoved(BookmarkModel* model, | |
| 82 const BookmarkNode* parent, | |
| 83 int index, | |
| 84 const BookmarkNode* node); | |
| 85 virtual void BookmarkNodeChanged(BookmarkModel* model, | |
| 86 const BookmarkNode* node); | |
| 87 virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, | |
| 88 const BookmarkNode* node); | |
| 89 virtual void BookmarkNodeChildrenReordered(BookmarkModel* model, | |
| 90 const BookmarkNode* node); | |
| 91 | |
| 92 // SyncFrontend implementation. | |
| 93 virtual void OnBackendInitialized(); | |
| 94 virtual void OnSyncCycleCompleted(); | |
| 95 virtual void OnAuthError(); | |
| 96 virtual void ApplyModelChanges( | |
| 97 const sync_api::BaseTransaction* trans, | |
| 98 const sync_api::SyncManager::ChangeRecord* changes, | |
| 99 int change_count); | |
| 100 | |
| 101 // Called when a user enters credentials through UI. | |
| 102 virtual void OnUserSubmittedAuth(const std::string& username, | |
| 103 const std::string& password); | |
| 104 | |
| 105 // Called when a user decides whether to merge and sync or abort. | |
| 106 virtual void OnUserAcceptedMergeAndSync(); | |
| 107 | |
| 108 // Called when a user cancels any setup dialog (login, merge and sync, etc). | |
| 109 virtual void OnUserCancelledDialog(); | |
| 110 | |
| 111 // Get various information for displaying in the user interface. | |
| 112 browser_sync::SyncBackendHost::StatusSummary QuerySyncStatusSummary(); | |
| 113 browser_sync::SyncBackendHost::Status QueryDetailedSyncStatus(); | |
| 114 | |
| 115 AuthErrorState GetAuthErrorState() const { | |
| 116 return last_auth_error_; | |
| 117 } | |
| 118 | |
| 119 // Displays a dialog for the user to enter GAIA credentials and attempt | |
| 120 // re-authentication, and returns true if it actually opened the dialog. | |
| 121 // Returns false if a dialog is already showing, an auth attempt is in | |
| 122 // progress, the sync system is already authenticated, or some error | |
| 123 // occurred preventing the action. We make it the duty of ProfileSyncService | |
| 124 // to open the dialog to easily ensure only one is ever showing. | |
| 125 bool SetupInProgress() const { | |
| 126 return !IsSyncEnabledByUser() && WizardIsVisible(); | |
| 127 } | |
| 128 bool WizardIsVisible() const { return wizard_.IsVisible(); } | |
| 129 void ShowLoginDialog(); | |
| 130 | |
| 131 // Pretty-printed strings for a given StatusSummary. | |
| 132 static std::wstring BuildSyncStatusSummaryText( | |
| 133 const browser_sync::SyncBackendHost::StatusSummary& summary); | |
| 134 | |
| 135 // Returns true if the SyncBackendHost has told us it's ready to accept | |
| 136 // changes. | |
| 137 // TODO(timsteele): What happens if the bookmark model is loaded, a change | |
| 138 // takes place, and the backend isn't initialized yet? | |
| 139 bool sync_initialized() const { return backend_initialized_; } | |
| 140 | |
| 141 bool UIShouldDepictAuthInProgress() const { | |
| 142 return is_auth_in_progress_; | |
| 143 } | |
| 144 | |
| 145 // A timestamp marking the last time the service observed a transition from | |
| 146 // the SYNCING state to the READY state. Note that this does not reflect the | |
| 147 // last time we polled the server to see if there were any changes; the | |
| 148 // timestamp is only snapped when syncing takes place and we download or | |
| 149 // upload some bookmark entity. | |
| 150 const base::Time& last_synced_time() const { return last_synced_time_; } | |
| 151 | |
| 152 // Returns a user-friendly string form of last synced time (in minutes). | |
| 153 std::wstring GetLastSyncedTimeString() const; | |
| 154 | |
| 155 // Returns the authenticated username of the sync user, or empty if none | |
| 156 // exists. It will only exist if the authentication service provider (e.g | |
| 157 // GAIA) has confirmed the username is authentic. | |
| 158 virtual string16 GetAuthenticatedUsername() const; | |
| 159 | |
| 160 const std::string& last_attempted_user_email() const { | |
| 161 return last_attempted_user_email_; | |
| 162 } | |
| 163 | |
| 164 // The profile we are syncing for. | |
| 165 Profile* profile() { return profile_; } | |
| 166 | |
| 167 // Adds/removes an observer. ProfileSyncService does not take ownership of | |
| 168 // the observer. | |
| 169 void AddObserver(Observer* observer); | |
| 170 void RemoveObserver(Observer* observer); | |
| 171 | |
| 172 protected: | |
| 173 // Call this after any of the subsystems being synced (the bookmark | |
| 174 // model and the sync backend) finishes its initialization. When everything | |
| 175 // is ready, this function will bootstrap the subsystems so that they are | |
| 176 // initially in sync, and start forwarding changes between the two models. | |
| 177 void StartProcessingChangesIfReady(); | |
| 178 | |
| 179 // Various member accessors needed by unit tests. | |
| 180 browser_sync::SyncBackendHost* backend() { return backend_.get(); } | |
| 181 | |
| 182 // Call this when normal operation detects that the bookmark model and the | |
| 183 // syncer model are inconsistent, or similar. The ProfileSyncService will | |
| 184 // try to avoid doing any work to avoid crashing or corrupting things | |
| 185 // further, and will report an error status if queried. | |
| 186 void SetUnrecoverableError(); | |
| 187 | |
| 188 // Returns whether processing changes is allowed. Check this before doing | |
| 189 // any model-modifying operations. | |
| 190 bool ShouldPushChanges(); | |
| 191 | |
| 192 // Starts up the backend sync components. | |
| 193 void StartUp(); | |
| 194 // Shuts down the backend sync components. | |
| 195 // |sync_disabled| indicates if syncing is being disabled or not. | |
| 196 void Shutdown(bool sync_disabled); | |
| 197 | |
| 198 // Tests need to override this. | |
| 199 virtual void InitializeBackend(); | |
| 200 | |
| 201 // Tests need this. | |
| 202 void set_model_associator(browser_sync::ModelAssociator* manager) { | |
| 203 model_associator_ = manager; | |
| 204 } | |
| 205 | |
| 206 // We keep track of the last auth error observed so we can cover up the first | |
| 207 // "expected" auth failure from observers. | |
| 208 // TODO(timsteele): Same as expecting_first_run_auth_needed_event_. Remove | |
| 209 // this! | |
| 210 AuthErrorState last_auth_error_; | |
| 211 | |
| 212 // Cache of the last name the client attempted to authenticate. | |
| 213 std::string last_attempted_user_email_; | |
| 214 | |
| 215 private: | |
| 216 friend class browser_sync::ModelAssociator; | |
| 217 friend class ProfileSyncServiceTest; | |
| 218 friend class ProfileSyncServiceTestHarness; | |
| 219 friend class TestModelAssociator; | |
| 220 FRIEND_TEST(ProfileSyncServiceTest, UnrecoverableErrorSuspendsService); | |
| 221 | |
| 222 enum MoveOrCreate { | |
| 223 MOVE, | |
| 224 CREATE, | |
| 225 }; | |
| 226 | |
| 227 // Initializes the various settings from the command line. | |
| 228 void InitSettings(); | |
| 229 | |
| 230 // Methods to register, load and remove preferences. | |
| 231 void RegisterPreferences(); | |
| 232 void LoadPreferences(); | |
| 233 void ClearPreferences(); | |
| 234 | |
| 235 // Treat the |index|th child of |parent| as a newly added node, and create a | |
| 236 // corresponding node in the sync domain using |trans|. All properties | |
| 237 // will be transferred to the new node. A node corresponding to |parent| | |
| 238 // must already exist and be associated for this call to succeed. Returns | |
| 239 // the ID of the just-created node, or if creation fails, kInvalidID. | |
| 240 int64 CreateSyncNode(const BookmarkNode* parent, | |
| 241 int index, | |
| 242 sync_api::WriteTransaction* trans); | |
| 243 | |
| 244 // Create a bookmark node corresponding to |src| if one is not already | |
| 245 // associated with |src|. Returns the node that was created or updated. | |
| 246 const BookmarkNode* CreateOrUpdateBookmarkNode( | |
| 247 sync_api::BaseNode* src, | |
| 248 BookmarkModel* model); | |
| 249 | |
| 250 // Creates a bookmark node under the given parent node from the given sync | |
| 251 // node. Returns the newly created node. | |
| 252 const BookmarkNode* CreateBookmarkNode( | |
| 253 sync_api::BaseNode* sync_node, | |
| 254 const BookmarkNode* parent, | |
| 255 int index) const; | |
| 256 | |
| 257 // Sets the favicon of the given bookmark node from the given sync node. | |
| 258 // Returns whether the favicon was set in the bookmark node. | |
| 259 bool SetBookmarkFavicon(sync_api::BaseNode* sync_node, | |
| 260 const BookmarkNode* bookmark_node) const; | |
| 261 | |
| 262 // Sets the favicon of the given sync node from the given bookmark node. | |
| 263 void SetSyncNodeFavicon(const BookmarkNode* bookmark_node, | |
| 264 sync_api::WriteNode* sync_node) const; | |
| 265 | |
| 266 // Helper function to determine the appropriate insertion index of sync node | |
| 267 // |node| under the Bookmark model node |parent|, to make the positions | |
| 268 // match up between the two models. This presumes that the predecessor of the | |
| 269 // item (in the bookmark model) has already been moved into its appropriate | |
| 270 // position. | |
| 271 int CalculateBookmarkModelInsertionIndex( | |
| 272 const BookmarkNode* parent, | |
| 273 const sync_api::BaseNode* node) const; | |
| 274 | |
| 275 // Helper function used to fix the position of a sync node so that it matches | |
| 276 // the position of a corresponding bookmark model node. |parent| and | |
| 277 // |index| identify the bookmark model position. |dst| is the node whose | |
| 278 // position is to be fixed. If |operation| is CREATE, treat |dst| as an | |
| 279 // uncreated node and set its position via InitByCreation(); otherwise, | |
| 280 // |dst| is treated as an existing node, and its position will be set via | |
| 281 // SetPosition(). |trans| is the transaction to which |dst| belongs. Returns | |
| 282 // false on failure. | |
| 283 bool PlaceSyncNode(MoveOrCreate operation, | |
| 284 const BookmarkNode* parent, | |
| 285 int index, | |
| 286 sync_api::WriteTransaction* trans, | |
| 287 sync_api::WriteNode* dst); | |
| 288 | |
| 289 // Copy properties (but not position) from |src| to |dst|. | |
| 290 void UpdateSyncNodeProperties(const BookmarkNode* src, | |
| 291 sync_api::WriteNode* dst); | |
| 292 | |
| 293 // Helper function to encode a bookmark's favicon into a PNG byte vector. | |
| 294 void EncodeFavicon(const BookmarkNode* src, | |
| 295 std::vector<unsigned char>* dst) const; | |
| 296 | |
| 297 // Remove the sync node corresponding to |node|. It shouldn't have | |
| 298 // any children. | |
| 299 void RemoveOneSyncNode(sync_api::WriteTransaction* trans, | |
| 300 const BookmarkNode* node); | |
| 301 | |
| 302 // Remove all the sync nodes associated with |node| and its children. | |
| 303 void RemoveSyncNodeHierarchy(const BookmarkNode* node); | |
| 304 | |
| 305 // Whether the sync merge warning should be shown. | |
| 306 bool MergeAndSyncAcceptanceNeeded() const; | |
| 307 | |
| 308 // Sets the last synced time to the current time. | |
| 309 void UpdateLastSyncedTime(); | |
| 310 | |
| 311 // The profile whose data we are synchronizing. | |
| 312 Profile* profile_; | |
| 313 | |
| 314 // TODO(ncarter): Put this in a profile, once there is UI for it. | |
| 315 // This specifies where to find the sync server. | |
| 316 GURL sync_service_url_; | |
| 317 | |
| 318 // Model assocation manager instance. | |
| 319 scoped_refptr<browser_sync::ModelAssociator> model_associator_; | |
| 320 | |
| 321 // The last time we detected a successful transition from SYNCING state. | |
| 322 // Our backend notifies us whenever we should take a new snapshot. | |
| 323 base::Time last_synced_time_; | |
| 324 | |
| 325 // Our asynchronous backend to communicate with sync components living on | |
| 326 // other threads. | |
| 327 scoped_ptr<browser_sync::SyncBackendHost> backend_; | |
| 328 | |
| 329 // Whether the SyncBackendHost has been initialized. | |
| 330 bool backend_initialized_; | |
| 331 | |
| 332 // Set to true when the user first enables sync, and we are waiting for | |
| 333 // syncapi to give us the green light on providing credentials for the first | |
| 334 // time. It is set back to false as soon as we get this message, and is | |
| 335 // false all other times so we don't have to persist this value as it will | |
| 336 // get initialized to false. | |
| 337 // TODO(timsteele): Remove this by way of starting the wizard when enabling | |
| 338 // sync *before* initializing the backend. syncapi will need to change, but | |
| 339 // it means we don't have to wait for the first AuthError; if we ever get | |
| 340 // one, it is actually an error and this bool isn't needed. | |
| 341 bool expecting_first_run_auth_needed_event_; | |
| 342 | |
| 343 // Various pieces of UI query this value to determine if they should show | |
| 344 // an "Authenticating.." type of message. We are the only central place | |
| 345 // all auth attempts funnel through, so it makes sense to provide this. | |
| 346 // As its name suggests, this should NOT be used for anything other than UI. | |
| 347 bool is_auth_in_progress_; | |
| 348 | |
| 349 // True only after all bootstrapping has succeeded: the bookmark model is | |
| 350 // loaded, the sync backend is initialized, and the two domains are | |
| 351 // consistent with one another. | |
| 352 bool ready_to_process_changes_; | |
| 353 | |
| 354 // True if an unrecoverable error (e.g. violation of an assumed invariant) | |
| 355 // occurred during syncer operation. This value should be checked before | |
| 356 // doing any work that might corrupt things further. | |
| 357 bool unrecoverable_error_detected_; | |
| 358 | |
| 359 SyncSetupWizard wizard_; | |
| 360 | |
| 361 ObserverList<Observer> observers_; | |
| 362 | |
| 363 DISALLOW_COPY_AND_ASSIGN(ProfileSyncService); | |
| 364 }; | |
| 365 | |
| 366 #endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_H_ | |
| 367 | |
| 368 #endif // CHROME_PERSONALIZATION | |
| OLD | NEW |