1 // Copyright 2013 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_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_ 6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_ 7 8 #include <deque> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <vector> 13 14 #include "base/callback.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/observer_list.h" 18 #include "base/threading/non_thread_safe.h" 19 #include "chrome/browser/drive/drive_notification_manager_factory.h" 20 #include "chrome/browser/drive/drive_notification_observer.h" 21 #include "chrome/browser/extensions/extension_system_factory.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 24 #include "chrome/browser/sync_file_system/conflict_resolution_resolver.h" 25 #include "chrome/browser/sync_file_system/drive_backend_v1/api_util_interface.h" 26 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h" 27 #include "chrome/browser/sync_file_system/drive_backend_v1/local_sync_operation_resolver.h" 28 #include "chrome/browser/sync_file_system/drive_backend_v1/origin_operation_queue.h" 29 #include "chrome/browser/sync_file_system/drive_backend_v1/remote_change_handler.h" 30 #include "chrome/browser/sync_file_system/file_change.h" 31 #include "chrome/browser/sync_file_system/local_change_processor.h" 32 #include "chrome/browser/sync_file_system/remote_file_sync_service.h" 33 #include "chrome/browser/sync_file_system/sync_action.h" 34 #include "chrome/browser/sync_file_system/sync_callbacks.h" 35 #include "chrome/browser/sync_file_system/sync_direction.h" 36 #include "chrome/browser/sync_file_system/sync_file_system.pb.h" 37 #include "chrome/browser/sync_file_system/sync_status_code.h" 38 #include "chrome/browser/sync_file_system/sync_task_manager.h" 39 40 class ExtensionService; 41 42 namespace google_apis { 43 class ResourceList; 44 } 45 46 namespace tracked_objects { 47 class Location; 48 } 49 50 namespace sync_file_system { 51 52 namespace drive_backend { 53 class LocalSyncDelegate; 54 class RemoteSyncDelegate; 55 } 56 57 class SyncTaskManager; 58 59 // Maintains remote file changes. 60 // Owned by SyncFileSystemService (which is a per-profile object). 61 class DriveFileSyncService : public RemoteFileSyncService, 62 public LocalChangeProcessor, 63 public drive_backend::APIUtilObserver, 64 public SyncTaskManager::Client, 65 public base::NonThreadSafe, 66 public base::SupportsWeakPtr<DriveFileSyncService>, 67 public drive::DriveNotificationObserver { 68 public: 69 typedef base::Callback<void(const SyncStatusCallback& callback)> Task; 70 71 static ConflictResolutionPolicy kDefaultPolicy; 72 73 virtual ~DriveFileSyncService(); 74 75 // Creates DriveFileSyncService. 76 static scoped_ptr<DriveFileSyncService> Create(Profile* profile); 77 static void AppendDependsOnFactories( 78 std::set<BrowserContextKeyedServiceFactory*>* factories); 79 80 // Creates DriveFileSyncService instance for testing. 81 // |metadata_store| must be initialized beforehand. 82 static scoped_ptr<DriveFileSyncService> CreateForTesting( 83 Profile* profile, 84 const base::FilePath& base_dir, 85 scoped_ptr<drive_backend::APIUtilInterface> api_util, 86 scoped_ptr<DriveMetadataStore> metadata_store); 87 88 // RemoteFileSyncService overrides. 89 virtual void AddServiceObserver(Observer* observer) OVERRIDE; 90 virtual void AddFileStatusObserver(FileStatusObserver* observer) OVERRIDE; 91 virtual void RegisterOrigin(const GURL& origin, 92 const SyncStatusCallback& callback) OVERRIDE; 93 virtual void EnableOrigin(const GURL& origin, 94 const SyncStatusCallback& callback) OVERRIDE; 95 virtual void DisableOrigin(const GURL& origin, 96 const SyncStatusCallback& callback) OVERRIDE; 97 virtual void UninstallOrigin(const GURL& origin, 98 UninstallFlag flag, 99 const SyncStatusCallback& callback) OVERRIDE; 100 virtual void ProcessRemoteChange(const SyncFileCallback& callback) OVERRIDE; 101 virtual void SetRemoteChangeProcessor( 102 RemoteChangeProcessor* processor) OVERRIDE; 103 virtual LocalChangeProcessor* GetLocalChangeProcessor() OVERRIDE; 104 virtual bool IsConflicting(const fileapi::FileSystemURL& url) OVERRIDE; 105 virtual RemoteServiceState GetCurrentState() const OVERRIDE; 106 virtual void GetOriginStatusMap(OriginStatusMap* status_map) OVERRIDE; 107 virtual scoped_ptr<base::ListValue> DumpFiles(const GURL& origin) OVERRIDE; 108 virtual scoped_ptr<base::ListValue> DumpDatabase() OVERRIDE; 109 virtual void SetSyncEnabled(bool enabled) OVERRIDE; 110 virtual SyncStatusCode SetConflictResolutionPolicy( 111 ConflictResolutionPolicy policy) OVERRIDE; 112 virtual ConflictResolutionPolicy GetConflictResolutionPolicy() const OVERRIDE; 113 virtual void GetRemoteVersions( 114 const fileapi::FileSystemURL& url, 115 const RemoteVersionsCallback& callback) OVERRIDE; 116 virtual void DownloadRemoteVersion( 117 const fileapi::FileSystemURL& url, 118 const std::string& version_id, 119 const DownloadVersionCallback& callback) OVERRIDE; 120 121 // LocalChangeProcessor overrides. 122 virtual void ApplyLocalChange( 123 const FileChange& change, 124 const base::FilePath& local_file_path, 125 const SyncFileMetadata& local_file_metadata, 126 const fileapi::FileSystemURL& url, 127 const SyncStatusCallback& callback) OVERRIDE; 128 129 // DriveFileSyncClientObserver overrides. 130 virtual void OnAuthenticated() OVERRIDE; 131 virtual void OnNetworkConnected() OVERRIDE; 132 133 // drive::DriveNotificationObserver implementation. 134 virtual void OnNotificationReceived() OVERRIDE; 135 virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE; 136 137 // SyncTaskManager::Client overrides. 138 virtual void MaybeScheduleNextTask() OVERRIDE; 139 virtual void NotifyLastOperationStatus( 140 SyncStatusCode sync_status, 141 bool used_network) OVERRIDE; 142 143 static std::string PathToTitle(const base::FilePath& path); 144 static base::FilePath TitleToPath(const std::string& title); 145 static DriveMetadata::ResourceType SyncFileTypeToDriveMetadataResourceType( 146 SyncFileType file_type); 147 static SyncFileType DriveMetadataResourceTypeToSyncFileType( 148 DriveMetadata::ResourceType resource_type); 149 150 private: 151 friend class SyncTaskManager; 152 friend class drive_backend::LocalSyncDelegate; 153 friend class drive_backend::RemoteSyncDelegate; 154 155 friend class DriveFileSyncServiceFakeTest; 156 friend class DriveFileSyncServiceSyncTest; 157 friend class DriveFileSyncServiceTest; 158 struct ApplyLocalChangeParam; 159 struct ProcessRemoteChangeParam; 160 161 typedef base::Callback< 162 void(SyncStatusCode status, 163 const std::string& resource_id)> ResourceIdCallback; 164 165 explicit DriveFileSyncService(Profile* profile); 166 167 void Initialize(scoped_ptr<SyncTaskManager> task_manager, 168 const SyncStatusCallback& callback); 169 void InitializeForTesting( 170 scoped_ptr<SyncTaskManager> task_manager, 171 const base::FilePath& base_dir, 172 scoped_ptr<drive_backend::APIUtilInterface> sync_client, 173 scoped_ptr<DriveMetadataStore> metadata_store, 174 const SyncStatusCallback& callback); 175 176 void DidInitializeMetadataStore(const SyncStatusCallback& callback, 177 SyncStatusCode status, 178 bool created); 179 180 void UpdateServiceStateFromLastOperationStatus( 181 SyncStatusCode sync_status, 182 google_apis::GDataErrorCode gdata_error); 183 184 // Updates the service state. Also this may notify observers if the 185 // service state has been changed from the original value. 186 void UpdateServiceState(RemoteServiceState state, 187 const std::string& description); 188 189 void DoRegisterOrigin( 190 const GURL& origin, 191 const SyncStatusCallback& callback); 192 void DoEnableOrigin( 193 const GURL& origin, 194 const SyncStatusCallback& callback); 195 void DoDisableOrigin( 196 const GURL& origin, 197 const SyncStatusCallback& callback); 198 void DoUninstallOrigin( 199 const GURL& origin, 200 UninstallFlag flag, 201 const SyncStatusCallback& callback); 202 void DoProcessRemoteChange( 203 const SyncFileCallback& sync_callback, 204 const SyncStatusCallback& completion_callback); 205 void DoApplyLocalChange( 206 const FileChange& change, 207 const base::FilePath& local_file_path, 208 const SyncFileMetadata& local_file_metadata, 209 const fileapi::FileSystemURL& url, 210 const SyncStatusCallback& callback); 211 212 void DoGetRemoteVersions( 213 const fileapi::FileSystemURL& url, 214 const RemoteVersionsCallback& callback, 215 const SyncStatusCallback& completion_callback); 216 void DidGetEntryForRemoteVersions( 217 const RemoteVersionsCallback& callback, 218 google_apis::GDataErrorCode error, 219 scoped_ptr<google_apis::ResourceEntry> entry); 220 221 void DoDownloadRemoteVersion( 222 const fileapi::FileSystemURL& url, 223 const std::string& version_id, 224 const DownloadVersionCallback& callback, 225 const SyncStatusCallback& completion_callback); 226 void DidDownloadVersion( 227 const DownloadVersionCallback& download_callback, 228 google_apis::GDataErrorCode error, 229 const std::string& file_md5, 230 int64 file_size, 231 const base::Time& last_updated, 232 webkit_blob::ScopedFile downloaded); 233 234 void UpdateRegisteredOrigins(); 235 236 void StartBatchSync(const SyncStatusCallback& callback); 237 void DidGetDriveDirectoryForOrigin(const GURL& origin, 238 const SyncStatusCallback& callback, 239 SyncStatusCode status, 240 const std::string& resource_id); 241 void DidUninstallOrigin(const GURL& origin, 242 const SyncStatusCallback& callback, 243 google_apis::GDataErrorCode error); 244 void DidGetLargestChangeStampForBatchSync( 245 const SyncStatusCallback& callback, 246 const GURL& origin, 247 const std::string& resource_id, 248 google_apis::GDataErrorCode error, 249 int64 largest_changestamp); 250 void DidGetDirectoryContentForBatchSync( 251 const SyncStatusCallback& callback, 252 const GURL& origin, 253 const std::string& resource_id, 254 int64 largest_changestamp, 255 google_apis::GDataErrorCode error, 256 scoped_ptr<google_apis::ResourceList> feed); 257 258 void DidProcessRemoteChange(const SyncFileCallback& sync_callback, 259 const SyncStatusCallback& completion_callback, 260 SyncStatusCode status); 261 void DidApplyLocalChange(const SyncStatusCallback& callback, 262 SyncStatusCode status); 263 264 // Returns true if |pending_changes_| was updated. 265 bool AppendRemoteChange( 266 const GURL& origin, 267 const google_apis::ResourceEntry& entry, 268 int64 changestamp); 269 bool AppendFetchChange( 270 const GURL& origin, 271 const base::FilePath& path, 272 const std::string& resource_id, 273 SyncFileType file_type); 274 bool AppendRemoteChangeInternal( 275 const GURL& origin, 276 const base::FilePath& path, 277 bool is_deleted, 278 const std::string& resource_id, 279 int64 changestamp, 280 const std::string& remote_file_md5, 281 const base::Time& updated_time, 282 SyncFileType file_type); 283 void RemoveRemoteChange(const fileapi::FileSystemURL& url); 284 285 // TODO(kinuko,tzik): Move this out of DriveFileSyncService. 286 void MarkConflict( 287 const fileapi::FileSystemURL& url, 288 DriveMetadata* drive_metadata, 289 const SyncStatusCallback& callback); 290 void NotifyConflict( 291 const fileapi::FileSystemURL& url, 292 const SyncStatusCallback& callback, 293 SyncStatusCode status); 294 295 // A wrapper implementation to GDataErrorCodeToSyncStatusCode which returns 296 // authentication error if the user is not signed in. 297 SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper( 298 google_apis::GDataErrorCode error); 299 300 base::FilePath temporary_file_dir_; 301 302 // May start batch sync or incremental sync. 303 // This posts either one of following tasks: 304 // - StartBatchSyncForOrigin() if it has any pending batch sync origins, or 305 // - FetchChangesForIncrementalSync() otherwise. 306 // 307 // These two methods are called only from this method. 308 void MaybeStartFetchChanges(); 309 310 void FetchChangesForIncrementalSync(const SyncStatusCallback& callback); 311 void DidFetchChangesForIncrementalSync( 312 const SyncStatusCallback& callback, 313 bool has_new_changes, 314 google_apis::GDataErrorCode error, 315 scoped_ptr<google_apis::ResourceList> changes); 316 bool GetOriginForEntry(const google_apis::ResourceEntry& entry, GURL* origin); 317 void NotifyObserversFileStatusChanged(const fileapi::FileSystemURL& url, 318 SyncFileStatus sync_status, 319 SyncAction action_taken, 320 SyncDirection direction); 321 322 void EnsureSyncRootDirectory(const ResourceIdCallback& callback); 323 void DidEnsureSyncRoot(const ResourceIdCallback& callback, 324 google_apis::GDataErrorCode error, 325 const std::string& sync_root_resource_id); 326 void EnsureOriginRootDirectory(const GURL& origin, 327 const ResourceIdCallback& callback); 328 void DidEnsureSyncRootForOriginRoot(const GURL& origin, 329 const ResourceIdCallback& callback, 330 SyncStatusCode status, 331 const std::string& sync_root_resource_id); 332 void DidEnsureOriginRoot(const GURL& origin, 333 const ResourceIdCallback& callback, 334 google_apis::GDataErrorCode error, 335 const std::string& resource_id); 336 337 // This function returns Resouce ID for the sync root directory if available. 338 // Returns an empty string 1) when the resource ID has not been initialized 339 // yet, and 2) after the service has detected the remote sync root folder was 340 // removed. 341 std::string sync_root_resource_id(); 342 343 scoped_ptr<DriveMetadataStore> metadata_store_; 344 scoped_ptr<drive_backend::APIUtilInterface> api_util_; 345 346 Profile* profile_; 347 348 scoped_ptr<SyncTaskManager> task_manager_; 349 350 scoped_ptr<drive_backend::LocalSyncDelegate> running_local_sync_task_; 351 scoped_ptr<drive_backend::RemoteSyncDelegate> running_remote_sync_task_; 352 353 // The current remote service state. This does NOT reflect the 354 // sync_enabled_ flag, while GetCurrentState() DOES reflect the flag 355 // value (i.e. it returns REMOTE_SERVICE_DISABLED when sync_enabled_ 356 // is false even if state_ is REMOTE_SERVICE_OK). 357 RemoteServiceState state_; 358 359 // Indicates if sync is enabled or not. This flag can be turned on or 360 // off by SetSyncEnabled() method. To start synchronization 361 // this needs to be true and state_ needs to be REMOTE_SERVICE_OK. 362 bool sync_enabled_; 363 364 int64 largest_fetched_changestamp_; 365 366 std::map<GURL, std::string> pending_batch_sync_origins_; 367 368 // Is set to true when there's a fair possibility that we have some 369 // remote changes that haven't been fetched yet. 370 // 371 // This flag is set when: 372 // - This gets invalidation notification, 373 // - The service is authenticated or becomes online, and 374 // - The polling timer is fired. 375 // 376 // This flag is cleared when: 377 // - A batch or incremental sync has been started, and 378 // - When all pending batch sync tasks have been finished. 379 bool may_have_unfetched_changes_; 380 381 ObserverList<Observer> service_observers_; 382 ObserverList<FileStatusObserver> file_status_observers_; 383 384 RemoteChangeHandler remote_change_handler_; 385 RemoteChangeProcessor* remote_change_processor_; 386 387 google_apis::GDataErrorCode last_gdata_error_; 388 389 ConflictResolutionResolver conflict_resolution_resolver_; 390 391 OriginOperationQueue pending_origin_operations_; 392 393 DISALLOW_COPY_AND_ASSIGN(DriveFileSyncService); 394 }; 395 396 } // namespace sync_file_system 397 398 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_ 399