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_
14 #include "base/basictypes.h"
15 #include "base/callback.h"
16 #include "base/files/file.h"
17 #include "base/files/file_path.h"
18 #include "base/logging.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/weak_ptr.h"
22 #include "base/observer_list.h"
23 #include "base/timer/timer.h"
24 #include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
25 #include "chrome/browser/sync_file_system/sync_callbacks.h"
26 #include "chrome/browser/sync_file_system/sync_status_code.h"
30 class SingleThreadTaskRunner
;
34 class FileSystemContext
;
46 namespace sync_file_system
{
49 class LocalFileChangeTracker
;
50 struct LocalFileSyncInfo
;
51 class LocalOriginChangeObserver
;
52 class RootDeleteHelper
;
53 class SyncableFileOperationRunner
;
55 // This class works as a bridge between LocalFileSyncService (which is a
56 // per-profile object) and FileSystemContext's (which is a per-storage-partition
57 // object and may exist multiple in a profile).
58 // An instance of this class is shared by FileSystemContexts and outlives
59 // LocalFileSyncService.
60 class LocalFileSyncContext
61 : public base::RefCountedThreadSafe
<LocalFileSyncContext
>,
62 public LocalFileSyncStatus::Observer
{
69 typedef base::Callback
<void(SyncStatusCode status
,
70 const LocalFileSyncInfo
& sync_file_info
,
71 storage::ScopedFile snapshot
)>
72 LocalFileSyncInfoCallback
;
74 typedef base::Callback
<void(SyncStatusCode status
,
75 bool has_pending_changes
)>
76 HasPendingLocalChangeCallback
;
78 LocalFileSyncContext(const base::FilePath
& base_path
,
79 leveldb::Env
* env_override
,
80 base::SingleThreadTaskRunner
* ui_task_runner
,
81 base::SingleThreadTaskRunner
* io_task_runner
);
83 // Initializes |file_system_context| for syncable file operations
84 // and registers the it into the internal map.
85 // Calling this multiple times for the same file_system_context is valid.
86 // This method must be called on UI thread.
87 void MaybeInitializeFileSystemContext(
88 const GURL
& source_url
,
89 storage::FileSystemContext
* file_system_context
,
90 const SyncStatusCallback
& callback
);
92 // Called when the corresponding LocalFileSyncService exits.
93 // This method must be called on UI thread.
94 void ShutdownOnUIThread();
96 // Picks a file for next local sync and returns it after disabling writes
98 // This method must be called on UI thread.
99 void GetFileForLocalSync(storage::FileSystemContext
* file_system_context
,
100 const LocalFileSyncInfoCallback
& callback
);
102 // TODO(kinuko): Make this private.
103 // Clears all pending local changes for |url|. |done_callback| is called
104 // when the changes are cleared.
105 // This method must be called on UI thread.
106 void ClearChangesForURL(storage::FileSystemContext
* file_system_context
,
107 const storage::FileSystemURL
& url
,
108 const base::Closure
& done_callback
);
110 // Finalizes SnapshotSync, which must have been started by
111 // PrepareForSync with SYNC_SNAPSHOT.
112 // Updates the on-disk dirty flag for |url| in the tracker DB.
113 // This will clear the dirty flag if |sync_finish_status| is SYNC_STATUS_OK
114 // or SYNC_STATUS_HAS_CONFLICT.
115 // |done_callback| is called when the changes are committed.
116 void FinalizeSnapshotSync(storage::FileSystemContext
* file_system_context
,
117 const storage::FileSystemURL
& url
,
118 SyncStatusCode sync_finish_status
,
119 const base::Closure
& done_callback
);
121 // Finalizes ExclusiveSync, which must have been started by
122 // PrepareForSync with SYNC_EXCLUSIVE.
123 void FinalizeExclusiveSync(storage::FileSystemContext
* file_system_context
,
124 const storage::FileSystemURL
& url
,
125 bool clear_local_changes
,
126 const base::Closure
& done_callback
);
128 // Prepares for sync |url| by disabling writes on |url|.
129 // If the target |url| is being written and cannot start sync it
130 // returns SYNC_STATUS_WRITING status code via |callback|.
131 // Otherwise returns the current change sets made on |url|.
133 // If |sync_mode| is SYNC_EXCLUSIVE this leaves the target file locked.
134 // If |sync_mode| is SYNC_SNAPSHOT this creates a snapshot (if the
135 // target file is not deleted) and unlocks the file before returning.
137 // For SYNC_EXCLUSIVE, caller must call FinalizeExclusiveSync() to finalize
138 // sync and unlock the file.
139 // For SYNC_SNAPSHOT, caller must call FinalizeSnapshotSync() to finalize
140 // sync to reset the mirrored change status and decrement writing count.
142 // This method must be called on UI thread.
143 void PrepareForSync(storage::FileSystemContext
* file_system_context
,
144 const storage::FileSystemURL
& url
,
146 const LocalFileSyncInfoCallback
& callback
);
148 // Registers |url| to wait until sync is enabled for |url|.
149 // |on_syncable_callback| is to be called when |url| becomes syncable
150 // (i.e. when we have no pending writes and the file is successfully locked
153 // Calling this method again while this already has another URL waiting
154 // for sync will overwrite the previously registered URL.
156 // This method must be called on UI thread.
157 void RegisterURLForWaitingSync(const storage::FileSystemURL
& url
,
158 const base::Closure
& on_syncable_callback
);
160 // Applies a remote change.
161 // This method must be called on UI thread.
162 void ApplyRemoteChange(storage::FileSystemContext
* file_system_context
,
163 const FileChange
& change
,
164 const base::FilePath
& local_path
,
165 const storage::FileSystemURL
& url
,
166 const SyncStatusCallback
& callback
);
168 // Records a fake local change in the local change tracker.
169 void RecordFakeLocalChange(storage::FileSystemContext
* file_system_context
,
170 const storage::FileSystemURL
& url
,
171 const FileChange
& change
,
172 const SyncStatusCallback
& callback
);
174 // This must be called on UI thread.
175 void GetFileMetadata(storage::FileSystemContext
* file_system_context
,
176 const storage::FileSystemURL
& url
,
177 const SyncFileMetadataCallback
& callback
);
179 // Returns true via |callback| if the given file |url| has local pending
181 void HasPendingLocalChanges(storage::FileSystemContext
* file_system_context
,
182 const storage::FileSystemURL
& url
,
183 const HasPendingLocalChangeCallback
& callback
);
185 void PromoteDemotedChanges(const GURL
& origin
,
186 storage::FileSystemContext
* file_system_context
,
187 const base::Closure
& callback
);
188 void UpdateChangesForOrigin(const GURL
& origin
,
189 const base::Closure
& callback
);
191 // They must be called on UI thread.
192 void AddOriginChangeObserver(LocalOriginChangeObserver
* observer
);
193 void RemoveOriginChangeObserver(LocalOriginChangeObserver
* observer
);
195 // OperationRunner is accessible only on IO thread.
196 base::WeakPtr
<SyncableFileOperationRunner
> operation_runner() const;
198 // SyncContext is accessible only on IO thread.
199 LocalFileSyncStatus
* sync_status() const;
201 // For testing; override the duration to notify changes from the
203 void set_mock_notify_changes_duration_in_sec(int duration
) {
204 mock_notify_changes_duration_in_sec_
= duration
;
208 // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
209 void OnSyncEnabled(const storage::FileSystemURL
& url
) override
;
210 void OnWriteEnabled(const storage::FileSystemURL
& url
) override
;
213 typedef base::Callback
<void(base::File::Error result
)> StatusCallback
;
214 typedef std::deque
<SyncStatusCallback
> StatusCallbackQueue
;
215 typedef std::deque
<storage::FileSystemURL
> FileSystemURLQueue
;
216 friend class base::RefCountedThreadSafe
<LocalFileSyncContext
>;
217 friend class CannedSyncableFileSystem
;
219 ~LocalFileSyncContext() override
;
221 void ShutdownOnIOThread();
223 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
224 // The caller is expected to update origins_with_pending_changes_ before
226 void ScheduleNotifyChangesUpdatedOnIOThread(const base::Closure
& callback
);
228 // Called by the internal timer on IO thread to notify changes to UI thread.
229 void NotifyAvailableChangesOnIOThread();
231 // Called from NotifyAvailableChangesOnIOThread.
232 void NotifyAvailableChanges(const std::set
<GURL
>& origins
,
233 const std::vector
<base::Closure
>& callbacks
);
235 // Helper routines for MaybeInitializeFileSystemContext.
236 void InitializeFileSystemContextOnIOThread(
237 const GURL
& source_url
,
238 storage::FileSystemContext
* file_system_context
,
239 const GURL
& /* root */,
240 const std::string
& /* name */,
241 base::File::Error error
);
242 SyncStatusCode
InitializeChangeTrackerOnFileThread(
243 scoped_ptr
<LocalFileChangeTracker
>* tracker_ptr
,
244 storage::FileSystemContext
* file_system_context
,
245 std::set
<GURL
>* origins_with_changes
);
246 void DidInitializeChangeTrackerOnIOThread(
247 scoped_ptr
<LocalFileChangeTracker
>* tracker_ptr
,
248 const GURL
& source_url
,
249 storage::FileSystemContext
* file_system_context
,
250 std::set
<GURL
>* origins_with_changes
,
251 SyncStatusCode status
);
252 void DidInitialize(const GURL
& source_url
,
253 storage::FileSystemContext
* file_system_context
,
254 SyncStatusCode status
);
256 // Helper routines for GetFileForLocalSync.
257 scoped_ptr
<FileSystemURLQueue
> GetNextURLsForSyncOnFileThread(
258 storage::FileSystemContext
* file_system_context
);
259 void TryPrepareForLocalSync(storage::FileSystemContext
* file_system_context
,
260 const LocalFileSyncInfoCallback
& callback
,
261 scoped_ptr
<FileSystemURLQueue
> urls
);
262 void DidTryPrepareForLocalSync(
263 storage::FileSystemContext
* file_system_context
,
264 scoped_ptr
<FileSystemURLQueue
> remaining_urls
,
265 const LocalFileSyncInfoCallback
& callback
,
266 SyncStatusCode status
,
267 const LocalFileSyncInfo
& sync_file_info
,
268 storage::ScopedFile snapshot
);
269 void PromoteDemotedChangesForURL(
270 storage::FileSystemContext
* file_system_context
,
271 const storage::FileSystemURL
& url
);
272 void PromoteDemotedChangesForURLs(
273 storage::FileSystemContext
* file_system_context
,
274 scoped_ptr
<FileSystemURLQueue
> url
);
276 // Callback routine for PrepareForSync and GetFileForLocalSync.
277 void DidGetWritingStatusForSync(
278 storage::FileSystemContext
* file_system_context
,
279 SyncStatusCode status
,
280 const storage::FileSystemURL
& url
,
282 const LocalFileSyncInfoCallback
& callback
);
284 // Helper routine for sync/writing flag handling.
286 // If |for_snapshot_sync| is true, this increments the writing counter
287 // for |url| (after clearing syncing flag), so that other sync activities
288 // won't step in while snapshot sync is ongoing.
289 // In this case FinalizeSnapshotSyncOnIOThread must be called after the
290 // snapshot sync is finished to decrement the writing counter.
291 void ClearSyncFlagOnIOThread(const storage::FileSystemURL
& url
,
292 bool for_snapshot_sync
);
293 void FinalizeSnapshotSyncOnIOThread(const storage::FileSystemURL
& url
);
295 void HandleRemoteDelete(storage::FileSystemContext
* file_system_context
,
296 const storage::FileSystemURL
& url
,
297 const SyncStatusCallback
& callback
);
298 void HandleRemoteAddOrUpdate(storage::FileSystemContext
* file_system_context
,
299 const FileChange
& change
,
300 const base::FilePath
& local_path
,
301 const storage::FileSystemURL
& url
,
302 const SyncStatusCallback
& callback
);
303 void DidRemoveExistingEntryForRemoteAddOrUpdate(
304 storage::FileSystemContext
* file_system_context
,
305 const FileChange
& change
,
306 const base::FilePath
& local_path
,
307 const storage::FileSystemURL
& url
,
308 const SyncStatusCallback
& callback
,
309 base::File::Error error
);
311 // Callback routine for ApplyRemoteChange.
312 void DidApplyRemoteChange(const storage::FileSystemURL
& url
,
313 const SyncStatusCallback
& callback_on_ui
,
314 base::File::Error file_error
);
316 void DidGetFileMetadata(
317 const SyncFileMetadataCallback
& callback
,
318 base::File::Error file_error
,
319 const base::File::Info
& file_info
);
321 base::TimeDelta
NotifyChangesDuration();
323 void DidCreateDirectoryForCopyIn(
324 storage::FileSystemContext
* file_system_context
,
325 const base::FilePath
& local_file_path
,
326 const storage::FileSystemURL
& dest_url
,
327 const StatusCallback
& callback
,
328 base::File::Error error
);
330 const base::FilePath local_base_path_
;
331 leveldb::Env
* env_override_
;
333 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner_
;
334 scoped_refptr
<base::SingleThreadTaskRunner
> io_task_runner_
;
336 // Indicates if the sync service is shutdown.
337 bool shutdown_on_ui_
; // Updated and referred only on UI thread.
338 bool shutdown_on_io_
; // Updated and referred only on IO thread.
340 // OperationRunner. This must be accessed only on IO thread.
341 scoped_ptr
<SyncableFileOperationRunner
> operation_runner_
;
343 // Keeps track of writing/syncing status.
344 // This must be accessed only on IO thread.
345 scoped_ptr
<LocalFileSyncStatus
> sync_status_
;
347 // Pointers to file system contexts that have been initialized for
348 // synchronization (i.e. that own this instance).
349 // This must be accessed only on UI thread.
350 std::set
<storage::FileSystemContext
*> file_system_contexts_
;
352 // Accessed only on UI thread.
353 std::map
<storage::FileSystemContext
*, StatusCallbackQueue
>
354 pending_initialize_callbacks_
;
356 // A URL and associated callback waiting for sync is enabled.
357 // Accessed only on IO thread.
358 storage::FileSystemURL url_waiting_sync_on_io_
;
359 base::Closure url_syncable_callback_
;
361 // Used only on IO thread for available changes notifications.
362 base::Time last_notified_changes_
;
363 scoped_ptr
<base::OneShotTimer
<LocalFileSyncContext
> > timer_on_io_
;
364 std::vector
<base::Closure
> pending_completion_callbacks_
;
365 std::set
<GURL
> origins_with_pending_changes_
;
367 // Populated while root directory deletion is being handled for
368 // ApplyRemoteChange(). Modified only on IO thread.
369 scoped_ptr
<RootDeleteHelper
> root_delete_helper_
;
371 base::ObserverList
<LocalOriginChangeObserver
> origin_change_observers_
;
373 int mock_notify_changes_duration_in_sec_
;
375 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext
);
378 } // namespace sync_file_system
380 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_