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.
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_
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_observer.h"
20 #include "chrome/browser/sync_file_system/conflict_resolution_resolver.h"
21 #include "chrome/browser/sync_file_system/drive_backend_v1/api_util_interface.h"
22 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_metadata_store.h"
23 #include "chrome/browser/sync_file_system/drive_backend_v1/local_sync_operation_resolver.h"
24 #include "chrome/browser/sync_file_system/drive_backend_v1/origin_operation_queue.h"
25 #include "chrome/browser/sync_file_system/drive_backend_v1/remote_change_handler.h"
26 #include "chrome/browser/sync_file_system/file_change.h"
27 #include "chrome/browser/sync_file_system/local_change_processor.h"
28 #include "chrome/browser/sync_file_system/remote_file_sync_service.h"
29 #include "chrome/browser/sync_file_system/sync_action.h"
30 #include "chrome/browser/sync_file_system/sync_callbacks.h"
31 #include "chrome/browser/sync_file_system/sync_direction.h"
32 #include "chrome/browser/sync_file_system/sync_file_system.pb.h"
33 #include "chrome/browser/sync_file_system/sync_status_code.h"
34 #include "chrome/browser/sync_file_system/sync_task_manager.h"
36 class ExtensionService;
38 namespace google_apis {
42 namespace tracked_objects {
46 namespace sync_file_system {
48 namespace drive_backend {
49 class LocalSyncDelegate;
50 class RemoteSyncDelegate;
53 class SyncTaskManager;
55 // Maintains remote file changes.
56 // Owned by SyncFileSystemService (which is a per-profile object).
57 class DriveFileSyncService : public RemoteFileSyncService,
58 public LocalChangeProcessor,
59 public drive_backend::APIUtilObserver,
60 public SyncTaskManager::Client,
61 public base::NonThreadSafe,
62 public base::SupportsWeakPtr<DriveFileSyncService>,
63 public drive::DriveNotificationObserver {
65 typedef base::Callback<void(const SyncStatusCallback& callback)> Task;
67 static ConflictResolutionPolicy kDefaultPolicy;
69 virtual ~DriveFileSyncService();
71 // Creates DriveFileSyncService.
72 static scoped_ptr<DriveFileSyncService> Create(Profile* profile);
74 // Creates DriveFileSyncService instance for testing.
75 // |metadata_store| must be initialized beforehand.
76 static scoped_ptr<DriveFileSyncService> CreateForTesting(
78 const base::FilePath& base_dir,
79 scoped_ptr<drive_backend::APIUtilInterface> api_util,
80 scoped_ptr<DriveMetadataStore> metadata_store);
82 // Destroys |sync_service| and passes the ownership of |sync_client| to caller
84 static scoped_ptr<drive_backend::APIUtilInterface>
85 DestroyAndPassAPIUtilForTesting(
86 scoped_ptr<DriveFileSyncService> sync_service);
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,
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 void SetSyncEnabled(bool enabled) OVERRIDE;
109 virtual SyncStatusCode SetConflictResolutionPolicy(
110 ConflictResolutionPolicy policy) OVERRIDE;
111 virtual ConflictResolutionPolicy GetConflictResolutionPolicy() const OVERRIDE;
112 virtual void GetRemoteVersions(
113 const fileapi::FileSystemURL& url,
114 const RemoteVersionsCallback& callback) OVERRIDE;
115 virtual void DownloadRemoteVersion(
116 const fileapi::FileSystemURL& url,
117 const std::string& version_id,
118 const DownloadVersionCallback& callback) OVERRIDE;
120 // LocalChangeProcessor overrides.
121 virtual void ApplyLocalChange(
122 const FileChange& change,
123 const base::FilePath& local_file_path,
124 const SyncFileMetadata& local_file_metadata,
125 const fileapi::FileSystemURL& url,
126 const SyncStatusCallback& callback) OVERRIDE;
128 // DriveFileSyncClientObserver overrides.
129 virtual void OnAuthenticated() OVERRIDE;
130 virtual void OnNetworkConnected() OVERRIDE;
132 // drive::DriveNotificationObserver implementation.
133 virtual void OnNotificationReceived() OVERRIDE;
134 virtual void OnPushNotificationEnabled(bool enabled) OVERRIDE;
136 // SyncTaskManager::Client overrides.
137 virtual void MaybeScheduleNextTask() OVERRIDE;
138 virtual void NotifyLastOperationStatus(SyncStatusCode sync_status) OVERRIDE;
140 static std::string PathToTitle(const base::FilePath& path);
141 static base::FilePath TitleToPath(const std::string& title);
142 static DriveMetadata::ResourceType SyncFileTypeToDriveMetadataResourceType(
143 SyncFileType file_type);
144 static SyncFileType DriveMetadataResourceTypeToSyncFileType(
145 DriveMetadata::ResourceType resource_type);
148 friend class SyncTaskManager;
149 friend class drive_backend::LocalSyncDelegate;
150 friend class drive_backend::RemoteSyncDelegate;
152 friend class DriveFileSyncServiceFakeTest;
153 friend class DriveFileSyncServiceSyncTest;
154 friend class DriveFileSyncServiceTest;
155 struct ApplyLocalChangeParam;
156 struct ProcessRemoteChangeParam;
158 typedef base::Callback<
159 void(SyncStatusCode status,
160 const std::string& resource_id)> ResourceIdCallback;
162 explicit DriveFileSyncService(Profile* profile);
164 void Initialize(scoped_ptr<SyncTaskManager> task_manager,
165 const SyncStatusCallback& callback);
166 void InitializeForTesting(
167 scoped_ptr<SyncTaskManager> task_manager,
168 const base::FilePath& base_dir,
169 scoped_ptr<drive_backend::APIUtilInterface> sync_client,
170 scoped_ptr<DriveMetadataStore> metadata_store,
171 const SyncStatusCallback& callback);
173 void DidInitializeMetadataStore(const SyncStatusCallback& callback,
174 SyncStatusCode status,
176 void DidGetDriveRootResourceId(const SyncStatusCallback& callback,
177 google_apis::GDataErrorCode error,
178 const std::string& root_resource_id);
180 void UpdateServiceStateFromLastOperationStatus(
181 SyncStatusCode sync_status,
182 google_apis::GDataErrorCode gdata_error);
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);
189 void DoRegisterOrigin(
191 const SyncStatusCallback& callback);
194 const SyncStatusCallback& callback);
195 void DoDisableOrigin(
197 const SyncStatusCallback& callback);
198 void DoUninstallOrigin(
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);
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);
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,
231 const base::Time& last_updated,
232 webkit_blob::ScopedFile downloaded);
234 void UpdateRegisteredOrigins();
236 void StartBatchSync(const SyncStatusCallback& callback);
237 void GetDriveDirectoryForOrigin(const GURL& origin,
238 const SyncStatusCallback& callback,
239 const std::string& sync_root_resource_id);
240 void DidGetDriveDirectoryForOrigin(const GURL& origin,
241 const SyncStatusCallback& callback,
242 SyncStatusCode status,
243 const std::string& resource_id);
244 void DidUninstallOrigin(const GURL& origin,
245 const SyncStatusCallback& callback,
246 google_apis::GDataErrorCode error);
247 void DidGetLargestChangeStampForBatchSync(
248 const SyncStatusCallback& callback,
250 const std::string& resource_id,
251 google_apis::GDataErrorCode error,
252 int64 largest_changestamp);
253 void DidGetDirectoryContentForBatchSync(
254 const SyncStatusCallback& callback,
256 const std::string& resource_id,
257 int64 largest_changestamp,
258 google_apis::GDataErrorCode error,
259 scoped_ptr<google_apis::ResourceList> feed);
261 void DidProcessRemoteChange(const SyncFileCallback& sync_callback,
262 const SyncStatusCallback& completion_callback,
263 SyncStatusCode status);
264 void DidApplyLocalChange(const SyncStatusCallback& callback,
265 SyncStatusCode status);
267 // Returns true if |pending_changes_| was updated.
268 bool AppendRemoteChange(
270 const google_apis::ResourceEntry& entry,
272 bool AppendFetchChange(
274 const base::FilePath& path,
275 const std::string& resource_id,
276 SyncFileType file_type);
277 bool AppendRemoteChangeInternal(
279 const base::FilePath& path,
281 const std::string& resource_id,
283 const std::string& remote_file_md5,
284 const base::Time& updated_time,
285 SyncFileType file_type);
286 void RemoveRemoteChange(const fileapi::FileSystemURL& url);
287 void MaybeMarkAsIncrementalSyncOrigin(const GURL& origin);
289 // TODO(kinuko,tzik): Move this out of DriveFileSyncService.
291 const fileapi::FileSystemURL& url,
292 DriveMetadata* drive_metadata,
293 const SyncStatusCallback& callback);
295 const fileapi::FileSystemURL& url,
296 const SyncStatusCallback& callback,
297 SyncStatusCode status);
299 // A wrapper implementation to GDataErrorCodeToSyncStatusCode which returns
300 // authentication error if the user is not signed in.
301 SyncStatusCode GDataErrorCodeToSyncStatusCodeWrapper(
302 google_apis::GDataErrorCode error);
304 base::FilePath temporary_file_dir_;
306 // May start batch sync or incremental sync.
307 // This posts either one of following tasks:
308 // - StartBatchSyncForOrigin() if it has any pending batch sync origins, or
309 // - FetchChangesForIncrementalSync() otherwise.
311 // These two methods are called only from this method.
312 void MaybeStartFetchChanges();
314 void FetchChangesForIncrementalSync(const SyncStatusCallback& callback);
315 void DidFetchChangesForIncrementalSync(
316 const SyncStatusCallback& callback,
317 bool has_new_changes,
318 google_apis::GDataErrorCode error,
319 scoped_ptr<google_apis::ResourceList> changes);
320 bool GetOriginForEntry(const google_apis::ResourceEntry& entry, GURL* origin);
321 void NotifyObserversFileStatusChanged(const fileapi::FileSystemURL& url,
322 SyncFileStatus sync_status,
323 SyncAction action_taken,
324 SyncDirection direction);
326 void HandleSyncRootDirectoryChange(const google_apis::ResourceEntry& entry);
327 void HandleOriginRootDirectoryChange(const google_apis::ResourceEntry& entry);
329 void EnsureSyncRootDirectory(const ResourceIdCallback& callback);
330 void DidEnsureSyncRoot(const ResourceIdCallback& callback,
331 google_apis::GDataErrorCode error,
332 const std::string& sync_root_resource_id);
333 void EnsureOriginRootDirectory(const GURL& origin,
334 const ResourceIdCallback& callback);
335 void DidEnsureSyncRootForOriginRoot(const GURL& origin,
336 const ResourceIdCallback& callback,
337 SyncStatusCode status,
338 const std::string& sync_root_resource_id);
339 void DidEnsureOriginRoot(const GURL& origin,
340 const ResourceIdCallback& callback,
341 google_apis::GDataErrorCode error,
342 const std::string& resource_id);
344 // This function returns Resouce ID for the sync root directory if available.
345 // Returns an empty string 1) when the resource ID has not been initialized
346 // yet, and 2) after the service has detected the remote sync root folder was
348 std::string sync_root_resource_id();
350 scoped_ptr<DriveMetadataStore> metadata_store_;
351 scoped_ptr<drive_backend::APIUtilInterface> api_util_;
355 scoped_ptr<SyncTaskManager> task_manager_;
357 scoped_ptr<drive_backend::LocalSyncDelegate> running_local_sync_task_;
358 scoped_ptr<drive_backend::RemoteSyncDelegate> running_remote_sync_task_;
360 // The current remote service state. This does NOT reflect the
361 // sync_enabled_ flag, while GetCurrentState() DOES reflect the flag
362 // value (i.e. it returns REMOTE_SERVICE_DISABLED when sync_enabled_
363 // is false even if state_ is REMOTE_SERVICE_OK).
364 RemoteServiceState state_;
366 // Indicates if sync is enabled or not. This flag can be turned on or
367 // off by SetSyncEnabled() method. To start synchronization
368 // this needs to be true and state_ needs to be REMOTE_SERVICE_OK.
371 int64 largest_fetched_changestamp_;
373 std::map<GURL, std::string> pending_batch_sync_origins_;
375 // Is set to true when there's a fair possibility that we have some
376 // remote changes that haven't been fetched yet.
378 // This flag is set when:
379 // - This gets invalidation notification,
380 // - The service is authenticated or becomes online, and
381 // - The polling timer is fired.
383 // This flag is cleared when:
384 // - A batch or incremental sync has been started, and
385 // - When all pending batch sync tasks have been finished.
386 bool may_have_unfetched_changes_;
388 ObserverList<Observer> service_observers_;
389 ObserverList<FileStatusObserver> file_status_observers_;
391 RemoteChangeHandler remote_change_handler_;
392 RemoteChangeProcessor* remote_change_processor_;
394 google_apis::GDataErrorCode last_gdata_error_;
396 ConflictResolutionResolver conflict_resolution_resolver_;
398 OriginOperationQueue pending_origin_operations_;
400 DISALLOW_COPY_AND_ASSIGN(DriveFileSyncService);
403 } // namespace sync_file_system
405 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_V1_DRIVE_FILE_SYNC_SERVICE_H_