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_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_
6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_
13 #include "base/basictypes.h"
14 #include "base/callback.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/weak_ptr.h"
20 #include "base/observer_list.h"
21 #include "base/timer/timer.h"
22 #include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
23 #include "chrome/browser/sync_file_system/sync_callbacks.h"
24 #include "chrome/browser/sync_file_system/sync_status_code.h"
28 class SingleThreadTaskRunner;
32 class FileSystemContext;
36 namespace webkit_blob {
40 namespace sync_file_system {
43 class LocalFileChangeTracker;
44 struct LocalFileSyncInfo;
45 class LocalOriginChangeObserver;
46 class SyncableFileOperationRunner;
48 // This class works as a bridge between LocalFileSyncService (which is a
49 // per-profile object) and FileSystemContext's (which is a per-storage-partition
50 // object and may exist multiple in a profile).
51 // An instance of this class is shared by FileSystemContexts and outlives
52 // LocalFileSyncService.
53 class LocalFileSyncContext
54 : public base::RefCountedThreadSafe<LocalFileSyncContext>,
55 public LocalFileSyncStatus::Observer {
62 typedef base::Callback<void(
63 SyncStatusCode status,
64 const LocalFileSyncInfo& sync_file_info,
65 webkit_blob::ScopedFile snapshot)>
66 LocalFileSyncInfoCallback;
68 typedef base::Callback<void(SyncStatusCode status,
69 bool has_pending_changes)>
70 HasPendingLocalChangeCallback;
72 LocalFileSyncContext(const base::FilePath& base_path,
73 base::SingleThreadTaskRunner* ui_task_runner,
74 base::SingleThreadTaskRunner* io_task_runner);
76 // Initializes |file_system_context| for syncable file operations
77 // and registers the it into the internal map.
78 // Calling this multiple times for the same file_system_context is valid.
79 // This method must be called on UI thread.
80 void MaybeInitializeFileSystemContext(
81 const GURL& source_url,
82 fileapi::FileSystemContext* file_system_context,
83 const SyncStatusCallback& callback);
85 // Called when the corresponding LocalFileSyncService exits.
86 // This method must be called on UI thread.
87 void ShutdownOnUIThread();
89 // Picks a file for next local sync and returns it after disabling writes
91 // This method must be called on UI thread.
92 void GetFileForLocalSync(fileapi::FileSystemContext* file_system_context,
93 const LocalFileSyncInfoCallback& callback);
95 // TODO(kinuko): Make this private.
96 // Clears all pending local changes for |url|. |done_callback| is called
97 // when the changes are cleared.
98 // This method must be called on UI thread.
99 void ClearChangesForURL(fileapi::FileSystemContext* file_system_context,
100 const fileapi::FileSystemURL& url,
101 const base::Closure& done_callback);
103 // Finalizes SnapshotSync, which must have been started by
104 // PrepareForSync with SYNC_SNAPSHOT.
105 // Updates the on-disk dirty flag for |url| in the tracker DB.
106 // This will clear the dirty flag if |sync_finish_status| is SYNC_STATUS_OK
107 // or SYNC_STATUS_HAS_CONFLICT.
108 // |done_callback| is called when the changes are committed.
109 void FinalizeSnapshotSync(
110 fileapi::FileSystemContext* file_system_context,
111 const fileapi::FileSystemURL& url,
112 SyncStatusCode sync_finish_status,
113 const base::Closure& done_callback);
115 // Finalizes ExclusiveSync, which must have been started by
116 // PrepareForSync with SYNC_EXCLUSIVE.
117 void FinalizeExclusiveSync(
118 fileapi::FileSystemContext* file_system_context,
119 const fileapi::FileSystemURL& url,
120 bool clear_local_changes,
121 const base::Closure& done_callback);
123 // Prepares for sync |url| by disabling writes on |url|.
124 // If the target |url| is being written and cannot start sync it
125 // returns SYNC_STATUS_WRITING status code via |callback|.
126 // Otherwise returns the current change sets made on |url|.
128 // If |sync_mode| is SYNC_EXCLUSIVE this leaves the target file locked.
129 // If |sync_mode| is SYNC_SNAPSHOT this creates a snapshot (if the
130 // target file is not deleted) and unlocks the file before returning.
132 // For SYNC_EXCLUSIVE, caller must call FinalizeExclusiveSync() to finalize
133 // sync and unlock the file.
134 // For SYNC_SNAPSHOT, caller must call FinalizeSnapshotSync() to finalize
135 // sync to reset the mirrored change status and decrement writing count.
137 // This method must be called on UI thread.
138 void PrepareForSync(fileapi::FileSystemContext* file_system_context,
139 const fileapi::FileSystemURL& url,
141 const LocalFileSyncInfoCallback& callback);
143 // Registers |url| to wait until sync is enabled for |url|.
144 // |on_syncable_callback| is to be called when |url| becomes syncable
145 // (i.e. when we have no pending writes and the file is successfully locked
148 // Calling this method again while this already has another URL waiting
149 // for sync will overwrite the previously registered URL.
151 // This method must be called on UI thread.
152 void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url,
153 const base::Closure& on_syncable_callback);
155 // Applies a remote change.
156 // This method must be called on UI thread.
157 void ApplyRemoteChange(
158 fileapi::FileSystemContext* file_system_context,
159 const FileChange& change,
160 const base::FilePath& local_path,
161 const fileapi::FileSystemURL& url,
162 const SyncStatusCallback& callback);
164 // Records a fake local change in the local change tracker.
165 void RecordFakeLocalChange(
166 fileapi::FileSystemContext* file_system_context,
167 const fileapi::FileSystemURL& url,
168 const FileChange& change,
169 const SyncStatusCallback& callback);
171 // This must be called on UI thread.
172 void GetFileMetadata(
173 fileapi::FileSystemContext* file_system_context,
174 const fileapi::FileSystemURL& url,
175 const SyncFileMetadataCallback& callback);
177 // Returns true via |callback| if the given file |url| has local pending
179 void HasPendingLocalChanges(
180 fileapi::FileSystemContext* file_system_context,
181 const fileapi::FileSystemURL& url,
182 const HasPendingLocalChangeCallback& callback);
184 // They must be called on UI thread.
185 void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
186 void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
188 // OperationRunner is accessible only on IO thread.
189 base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
191 // SyncContext is accessible only on IO thread.
192 LocalFileSyncStatus* sync_status() const;
194 // For testing; override the duration to notify changes from the
196 void set_mock_notify_changes_duration_in_sec(int duration) {
197 mock_notify_changes_duration_in_sec_ = duration;
201 // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
202 virtual void OnSyncEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
203 virtual void OnWriteEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
206 typedef base::Callback<void(base::PlatformFileError result)> StatusCallback;
207 typedef std::deque<SyncStatusCallback> StatusCallbackQueue;
208 friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
209 friend class CannedSyncableFileSystem;
211 virtual ~LocalFileSyncContext();
213 void ShutdownOnIOThread();
215 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
216 // The caller is expected to update origins_with_pending_changes_ before
218 void ScheduleNotifyChangesUpdatedOnIOThread();
220 // Called by the internal timer on IO thread to notify changes to UI thread.
221 void NotifyAvailableChangesOnIOThread();
223 // Called from NotifyAvailableChangesOnIOThread.
224 void NotifyAvailableChanges(const std::set<GURL>& origins);
226 // Helper routines for MaybeInitializeFileSystemContext.
227 void InitializeFileSystemContextOnIOThread(
228 const GURL& source_url,
229 fileapi::FileSystemContext* file_system_context);
230 SyncStatusCode InitializeChangeTrackerOnFileThread(
231 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
232 fileapi::FileSystemContext* file_system_context,
233 std::set<GURL>* origins_with_changes);
234 void DidInitializeChangeTrackerOnIOThread(
235 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
236 const GURL& source_url,
237 fileapi::FileSystemContext* file_system_context,
238 std::set<GURL>* origins_with_changes,
239 SyncStatusCode status);
241 const GURL& source_url,
242 fileapi::FileSystemContext* file_system_context,
243 SyncStatusCode status);
245 // Helper routines for GetFileForLocalSync.
246 void GetNextURLsForSyncOnFileThread(
247 fileapi::FileSystemContext* file_system_context,
248 std::deque<fileapi::FileSystemURL>* urls);
249 void TryPrepareForLocalSync(
250 fileapi::FileSystemContext* file_system_context,
251 std::deque<fileapi::FileSystemURL>* urls,
252 const LocalFileSyncInfoCallback& callback);
253 void DidTryPrepareForLocalSync(
254 fileapi::FileSystemContext* file_system_context,
255 std::deque<fileapi::FileSystemURL>* remaining_urls,
256 const LocalFileSyncInfoCallback& callback,
257 SyncStatusCode status,
258 const LocalFileSyncInfo& sync_file_info,
259 webkit_blob::ScopedFile snapshot);
261 // Callback routine for PrepareForSync and GetFileForLocalSync.
262 void DidGetWritingStatusForSync(
263 fileapi::FileSystemContext* file_system_context,
264 SyncStatusCode status,
265 const fileapi::FileSystemURL& url,
267 const LocalFileSyncInfoCallback& callback);
269 // Helper routine for sync/writing flag handling.
271 // If |for_snapshot_sync| is true, this increments the writing counter
272 // for |url| (after clearing syncing flag), so that other sync activities
273 // won't step in while snapshot sync is ongoing.
274 // In this case FinalizeSnapshotSyncOnIOThread must be called after the
275 // snapshot sync is finished to decrement the writing counter.
276 void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL& url,
277 bool for_snapshot_sync);
278 void FinalizeSnapshotSyncOnIOThread(const fileapi::FileSystemURL& url);
280 void DidRemoveExistingEntryForApplyRemoteChange(
281 fileapi::FileSystemContext* file_system_context,
282 const FileChange& change,
283 const base::FilePath& local_path,
284 const fileapi::FileSystemURL& url,
285 const SyncStatusCallback& callback,
286 base::PlatformFileError error);
288 // Callback routine for ApplyRemoteChange.
289 void DidApplyRemoteChange(
290 const fileapi::FileSystemURL& url,
291 const SyncStatusCallback& callback_on_ui,
292 base::PlatformFileError file_error);
294 void DidGetFileMetadata(
295 const SyncFileMetadataCallback& callback,
296 base::PlatformFileError file_error,
297 const base::PlatformFileInfo& file_info);
299 base::TimeDelta NotifyChangesDuration();
301 void DidCreateDirectoryForCopyIn(
302 fileapi::FileSystemContext* file_system_context,
303 const base::FilePath& local_file_path,
304 const fileapi::FileSystemURL& dest_url,
305 const StatusCallback& callback,
306 base::PlatformFileError error);
308 const base::FilePath local_base_path_;
310 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
311 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
313 // Indicates if the sync service is shutdown on UI thread.
314 bool shutdown_on_ui_;
316 // OperationRunner. This must be accessed only on IO thread.
317 scoped_ptr<SyncableFileOperationRunner> operation_runner_;
319 // Keeps track of writing/syncing status.
320 // This must be accessed only on IO thread.
321 scoped_ptr<LocalFileSyncStatus> sync_status_;
323 // Pointers to file system contexts that have been initialized for
324 // synchronization (i.e. that own this instance).
325 // This must be accessed only on UI thread.
326 std::set<fileapi::FileSystemContext*> file_system_contexts_;
328 // Accessed only on UI thread.
329 std::map<fileapi::FileSystemContext*, StatusCallbackQueue>
330 pending_initialize_callbacks_;
332 // A URL and associated callback waiting for sync is enabled.
333 // Accessed only on IO thread.
334 fileapi::FileSystemURL url_waiting_sync_on_io_;
335 base::Closure url_syncable_callback_;
337 // Used only on IO thread for available changes notifications.
338 base::Time last_notified_changes_;
339 scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_;
340 std::set<GURL> origins_with_pending_changes_;
342 ObserverList<LocalOriginChangeObserver> origin_change_observers_;
344 int mock_notify_changes_duration_in_sec_;
346 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
349 } // namespace sync_file_system
351 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_