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 RootDeleteHelper
;
47 class SyncableFileOperationRunner
;
49 // This class works as a bridge between LocalFileSyncService (which is a
50 // per-profile object) and FileSystemContext's (which is a per-storage-partition
51 // object and may exist multiple in a profile).
52 // An instance of this class is shared by FileSystemContexts and outlives
53 // LocalFileSyncService.
54 class LocalFileSyncContext
55 : public base::RefCountedThreadSafe
<LocalFileSyncContext
>,
56 public LocalFileSyncStatus::Observer
{
63 typedef base::Callback
<void(
64 SyncStatusCode status
,
65 const LocalFileSyncInfo
& sync_file_info
,
66 webkit_blob::ScopedFile snapshot
)>
67 LocalFileSyncInfoCallback
;
69 typedef base::Callback
<void(SyncStatusCode status
,
70 bool has_pending_changes
)>
71 HasPendingLocalChangeCallback
;
73 LocalFileSyncContext(const base::FilePath
& base_path
,
74 base::SingleThreadTaskRunner
* ui_task_runner
,
75 base::SingleThreadTaskRunner
* io_task_runner
);
77 // Initializes |file_system_context| for syncable file operations
78 // and registers the it into the internal map.
79 // Calling this multiple times for the same file_system_context is valid.
80 // This method must be called on UI thread.
81 void MaybeInitializeFileSystemContext(
82 const GURL
& source_url
,
83 fileapi::FileSystemContext
* file_system_context
,
84 const SyncStatusCallback
& callback
);
86 // Called when the corresponding LocalFileSyncService exits.
87 // This method must be called on UI thread.
88 void ShutdownOnUIThread();
90 // Picks a file for next local sync and returns it after disabling writes
92 // This method must be called on UI thread.
93 void GetFileForLocalSync(fileapi::FileSystemContext
* file_system_context
,
94 const LocalFileSyncInfoCallback
& callback
);
96 // TODO(kinuko): Make this private.
97 // Clears all pending local changes for |url|. |done_callback| is called
98 // when the changes are cleared.
99 // This method must be called on UI thread.
100 void ClearChangesForURL(fileapi::FileSystemContext
* file_system_context
,
101 const fileapi::FileSystemURL
& url
,
102 const base::Closure
& done_callback
);
104 // Finalizes SnapshotSync, which must have been started by
105 // PrepareForSync with SYNC_SNAPSHOT.
106 // Updates the on-disk dirty flag for |url| in the tracker DB.
107 // This will clear the dirty flag if |sync_finish_status| is SYNC_STATUS_OK
108 // or SYNC_STATUS_HAS_CONFLICT.
109 // |done_callback| is called when the changes are committed.
110 void FinalizeSnapshotSync(
111 fileapi::FileSystemContext
* file_system_context
,
112 const fileapi::FileSystemURL
& url
,
113 SyncStatusCode sync_finish_status
,
114 const base::Closure
& done_callback
);
116 // Finalizes ExclusiveSync, which must have been started by
117 // PrepareForSync with SYNC_EXCLUSIVE.
118 void FinalizeExclusiveSync(
119 fileapi::FileSystemContext
* file_system_context
,
120 const fileapi::FileSystemURL
& url
,
121 bool clear_local_changes
,
122 const base::Closure
& done_callback
);
124 // Prepares for sync |url| by disabling writes on |url|.
125 // If the target |url| is being written and cannot start sync it
126 // returns SYNC_STATUS_WRITING status code via |callback|.
127 // Otherwise returns the current change sets made on |url|.
129 // If |sync_mode| is SYNC_EXCLUSIVE this leaves the target file locked.
130 // If |sync_mode| is SYNC_SNAPSHOT this creates a snapshot (if the
131 // target file is not deleted) and unlocks the file before returning.
133 // For SYNC_EXCLUSIVE, caller must call FinalizeExclusiveSync() to finalize
134 // sync and unlock the file.
135 // For SYNC_SNAPSHOT, caller must call FinalizeSnapshotSync() to finalize
136 // sync to reset the mirrored change status and decrement writing count.
138 // This method must be called on UI thread.
139 void PrepareForSync(fileapi::FileSystemContext
* file_system_context
,
140 const fileapi::FileSystemURL
& url
,
142 const LocalFileSyncInfoCallback
& callback
);
144 // Registers |url| to wait until sync is enabled for |url|.
145 // |on_syncable_callback| is to be called when |url| becomes syncable
146 // (i.e. when we have no pending writes and the file is successfully locked
149 // Calling this method again while this already has another URL waiting
150 // for sync will overwrite the previously registered URL.
152 // This method must be called on UI thread.
153 void RegisterURLForWaitingSync(const fileapi::FileSystemURL
& url
,
154 const base::Closure
& on_syncable_callback
);
156 // Applies a remote change.
157 // This method must be called on UI thread.
158 void ApplyRemoteChange(
159 fileapi::FileSystemContext
* file_system_context
,
160 const FileChange
& change
,
161 const base::FilePath
& local_path
,
162 const fileapi::FileSystemURL
& url
,
163 const SyncStatusCallback
& callback
);
165 // Records a fake local change in the local change tracker.
166 void RecordFakeLocalChange(
167 fileapi::FileSystemContext
* file_system_context
,
168 const fileapi::FileSystemURL
& url
,
169 const FileChange
& change
,
170 const SyncStatusCallback
& callback
);
172 // This must be called on UI thread.
173 void GetFileMetadata(
174 fileapi::FileSystemContext
* file_system_context
,
175 const fileapi::FileSystemURL
& url
,
176 const SyncFileMetadataCallback
& callback
);
178 // Returns true via |callback| if the given file |url| has local pending
180 void HasPendingLocalChanges(
181 fileapi::FileSystemContext
* file_system_context
,
182 const fileapi::FileSystemURL
& url
,
183 const HasPendingLocalChangeCallback
& callback
);
185 void PromoteDemotedChanges(const GURL
& origin
,
186 fileapi::FileSystemContext
* file_system_context
);
187 void UpdateChangesForOrigin(const GURL
& origin
);
189 // They must be called on UI thread.
190 void AddOriginChangeObserver(LocalOriginChangeObserver
* observer
);
191 void RemoveOriginChangeObserver(LocalOriginChangeObserver
* observer
);
193 // OperationRunner is accessible only on IO thread.
194 base::WeakPtr
<SyncableFileOperationRunner
> operation_runner() const;
196 // SyncContext is accessible only on IO thread.
197 LocalFileSyncStatus
* sync_status() const;
199 // For testing; override the duration to notify changes from the
201 void set_mock_notify_changes_duration_in_sec(int duration
) {
202 mock_notify_changes_duration_in_sec_
= duration
;
206 // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
207 virtual void OnSyncEnabled(const fileapi::FileSystemURL
& url
) OVERRIDE
;
208 virtual void OnWriteEnabled(const fileapi::FileSystemURL
& url
) OVERRIDE
;
211 typedef base::Callback
<void(base::PlatformFileError result
)> StatusCallback
;
212 typedef std::deque
<SyncStatusCallback
> StatusCallbackQueue
;
213 friend class base::RefCountedThreadSafe
<LocalFileSyncContext
>;
214 friend class CannedSyncableFileSystem
;
216 virtual ~LocalFileSyncContext();
218 void ShutdownOnIOThread();
220 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
221 // The caller is expected to update origins_with_pending_changes_ before
223 void ScheduleNotifyChangesUpdatedOnIOThread();
225 // Called by the internal timer on IO thread to notify changes to UI thread.
226 void NotifyAvailableChangesOnIOThread();
228 // Called from NotifyAvailableChangesOnIOThread.
229 void NotifyAvailableChanges(const std::set
<GURL
>& origins
);
231 // Helper routines for MaybeInitializeFileSystemContext.
232 void InitializeFileSystemContextOnIOThread(
233 const GURL
& source_url
,
234 fileapi::FileSystemContext
* file_system_context
,
235 const GURL
& /* root */,
236 const std::string
& /* name */,
237 base::PlatformFileError error
);
238 SyncStatusCode
InitializeChangeTrackerOnFileThread(
239 scoped_ptr
<LocalFileChangeTracker
>* tracker_ptr
,
240 fileapi::FileSystemContext
* file_system_context
,
241 std::set
<GURL
>* origins_with_changes
);
242 void DidInitializeChangeTrackerOnIOThread(
243 scoped_ptr
<LocalFileChangeTracker
>* tracker_ptr
,
244 const GURL
& source_url
,
245 fileapi::FileSystemContext
* file_system_context
,
246 std::set
<GURL
>* origins_with_changes
,
247 SyncStatusCode status
);
249 const GURL
& source_url
,
250 fileapi::FileSystemContext
* file_system_context
,
251 SyncStatusCode status
);
253 // Helper routines for GetFileForLocalSync.
254 void GetNextURLsForSyncOnFileThread(
255 fileapi::FileSystemContext
* file_system_context
,
256 std::deque
<fileapi::FileSystemURL
>* urls
);
257 void TryPrepareForLocalSync(
258 fileapi::FileSystemContext
* file_system_context
,
259 std::deque
<fileapi::FileSystemURL
>* urls
,
260 const LocalFileSyncInfoCallback
& callback
);
261 void DidTryPrepareForLocalSync(
262 fileapi::FileSystemContext
* file_system_context
,
263 std::deque
<fileapi::FileSystemURL
>* remaining_urls
,
264 const LocalFileSyncInfoCallback
& callback
,
265 SyncStatusCode status
,
266 const LocalFileSyncInfo
& sync_file_info
,
267 webkit_blob::ScopedFile snapshot
);
269 // Callback routine for PrepareForSync and GetFileForLocalSync.
270 void DidGetWritingStatusForSync(
271 fileapi::FileSystemContext
* file_system_context
,
272 SyncStatusCode status
,
273 const fileapi::FileSystemURL
& url
,
275 const LocalFileSyncInfoCallback
& callback
);
277 // Helper routine for sync/writing flag handling.
279 // If |for_snapshot_sync| is true, this increments the writing counter
280 // for |url| (after clearing syncing flag), so that other sync activities
281 // won't step in while snapshot sync is ongoing.
282 // In this case FinalizeSnapshotSyncOnIOThread must be called after the
283 // snapshot sync is finished to decrement the writing counter.
284 void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL
& url
,
285 bool for_snapshot_sync
);
286 void FinalizeSnapshotSyncOnIOThread(const fileapi::FileSystemURL
& url
);
288 void HandleRemoteDelete(
289 fileapi::FileSystemContext
* file_system_context
,
290 const fileapi::FileSystemURL
& url
,
291 const SyncStatusCallback
& callback
);
292 void HandleRemoteAddOrUpdate(
293 fileapi::FileSystemContext
* file_system_context
,
294 const FileChange
& change
,
295 const base::FilePath
& local_path
,
296 const fileapi::FileSystemURL
& url
,
297 const SyncStatusCallback
& callback
);
298 void DidRemoveExistingEntryForRemoteAddOrUpdate(
299 fileapi::FileSystemContext
* file_system_context
,
300 const FileChange
& change
,
301 const base::FilePath
& local_path
,
302 const fileapi::FileSystemURL
& url
,
303 const SyncStatusCallback
& callback
,
304 base::PlatformFileError error
);
306 // Callback routine for ApplyRemoteChange.
307 void DidApplyRemoteChange(
308 const fileapi::FileSystemURL
& url
,
309 const SyncStatusCallback
& callback_on_ui
,
310 base::PlatformFileError file_error
);
312 void DidGetFileMetadata(
313 const SyncFileMetadataCallback
& callback
,
314 base::PlatformFileError file_error
,
315 const base::PlatformFileInfo
& file_info
);
317 base::TimeDelta
NotifyChangesDuration();
319 void DidCreateDirectoryForCopyIn(
320 fileapi::FileSystemContext
* file_system_context
,
321 const base::FilePath
& local_file_path
,
322 const fileapi::FileSystemURL
& dest_url
,
323 const StatusCallback
& callback
,
324 base::PlatformFileError error
);
326 const base::FilePath local_base_path_
;
328 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner_
;
329 scoped_refptr
<base::SingleThreadTaskRunner
> io_task_runner_
;
331 // Indicates if the sync service is shutdown.
332 bool shutdown_on_ui_
; // Updated and referred only on UI thread.
333 bool shutdown_on_io_
; // Updated and referred only on IO thread.
335 // OperationRunner. This must be accessed only on IO thread.
336 scoped_ptr
<SyncableFileOperationRunner
> operation_runner_
;
338 // Keeps track of writing/syncing status.
339 // This must be accessed only on IO thread.
340 scoped_ptr
<LocalFileSyncStatus
> sync_status_
;
342 // Pointers to file system contexts that have been initialized for
343 // synchronization (i.e. that own this instance).
344 // This must be accessed only on UI thread.
345 std::set
<fileapi::FileSystemContext
*> file_system_contexts_
;
347 // Accessed only on UI thread.
348 std::map
<fileapi::FileSystemContext
*, StatusCallbackQueue
>
349 pending_initialize_callbacks_
;
351 // A URL and associated callback waiting for sync is enabled.
352 // Accessed only on IO thread.
353 fileapi::FileSystemURL url_waiting_sync_on_io_
;
354 base::Closure url_syncable_callback_
;
356 // Used only on IO thread for available changes notifications.
357 base::Time last_notified_changes_
;
358 scoped_ptr
<base::OneShotTimer
<LocalFileSyncContext
> > timer_on_io_
;
359 std::set
<GURL
> origins_with_pending_changes_
;
361 // Populated while root directory deletion is being handled for
362 // ApplyRemoteChange(). Modified only on IO thread.
363 scoped_ptr
<RootDeleteHelper
> root_delete_helper_
;
365 ObserverList
<LocalOriginChangeObserver
> origin_change_observers_
;
367 int mock_notify_changes_duration_in_sec_
;
369 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext
);
372 } // namespace sync_file_system
374 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_