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.h"
16 #include "base/files/file_path.h"
17 #include "base/logging.h"
18 #include "base/memory/ref_counted.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/observer_list.h"
22 #include "base/timer/timer.h"
23 #include "chrome/browser/sync_file_system/local/local_file_sync_status.h"
24 #include "chrome/browser/sync_file_system/sync_callbacks.h"
25 #include "chrome/browser/sync_file_system/sync_status_code.h"
29 class SingleThreadTaskRunner;
33 class FileSystemContext;
41 namespace webkit_blob {
45 namespace sync_file_system {
48 class LocalFileChangeTracker;
49 struct LocalFileSyncInfo;
50 class LocalOriginChangeObserver;
51 class RootDeleteHelper;
52 class SyncableFileOperationRunner;
54 // This class works as a bridge between LocalFileSyncService (which is a
55 // per-profile object) and FileSystemContext's (which is a per-storage-partition
56 // object and may exist multiple in a profile).
57 // An instance of this class is shared by FileSystemContexts and outlives
58 // LocalFileSyncService.
59 class LocalFileSyncContext
60 : public base::RefCountedThreadSafe<LocalFileSyncContext>,
61 public LocalFileSyncStatus::Observer {
68 typedef base::Callback<void(
69 SyncStatusCode status,
70 const LocalFileSyncInfo& sync_file_info,
71 webkit_blob::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 fileapi::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(fileapi::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(fileapi::FileSystemContext* file_system_context,
107 const fileapi::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(
117 fileapi::FileSystemContext* file_system_context,
118 const fileapi::FileSystemURL& url,
119 SyncStatusCode sync_finish_status,
120 const base::Closure& done_callback);
122 // Finalizes ExclusiveSync, which must have been started by
123 // PrepareForSync with SYNC_EXCLUSIVE.
124 void FinalizeExclusiveSync(
125 fileapi::FileSystemContext* file_system_context,
126 const fileapi::FileSystemURL& url,
127 bool clear_local_changes,
128 const base::Closure& done_callback);
130 // Prepares for sync |url| by disabling writes on |url|.
131 // If the target |url| is being written and cannot start sync it
132 // returns SYNC_STATUS_WRITING status code via |callback|.
133 // Otherwise returns the current change sets made on |url|.
135 // If |sync_mode| is SYNC_EXCLUSIVE this leaves the target file locked.
136 // If |sync_mode| is SYNC_SNAPSHOT this creates a snapshot (if the
137 // target file is not deleted) and unlocks the file before returning.
139 // For SYNC_EXCLUSIVE, caller must call FinalizeExclusiveSync() to finalize
140 // sync and unlock the file.
141 // For SYNC_SNAPSHOT, caller must call FinalizeSnapshotSync() to finalize
142 // sync to reset the mirrored change status and decrement writing count.
144 // This method must be called on UI thread.
145 void PrepareForSync(fileapi::FileSystemContext* file_system_context,
146 const fileapi::FileSystemURL& url,
148 const LocalFileSyncInfoCallback& callback);
150 // Registers |url| to wait until sync is enabled for |url|.
151 // |on_syncable_callback| is to be called when |url| becomes syncable
152 // (i.e. when we have no pending writes and the file is successfully locked
155 // Calling this method again while this already has another URL waiting
156 // for sync will overwrite the previously registered URL.
158 // This method must be called on UI thread.
159 void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url,
160 const base::Closure& on_syncable_callback);
162 // Applies a remote change.
163 // This method must be called on UI thread.
164 void ApplyRemoteChange(
165 fileapi::FileSystemContext* file_system_context,
166 const FileChange& change,
167 const base::FilePath& local_path,
168 const fileapi::FileSystemURL& url,
169 const SyncStatusCallback& callback);
171 // Records a fake local change in the local change tracker.
172 void RecordFakeLocalChange(
173 fileapi::FileSystemContext* file_system_context,
174 const fileapi::FileSystemURL& url,
175 const FileChange& change,
176 const SyncStatusCallback& callback);
178 // This must be called on UI thread.
179 void GetFileMetadata(
180 fileapi::FileSystemContext* file_system_context,
181 const fileapi::FileSystemURL& url,
182 const SyncFileMetadataCallback& callback);
184 // Returns true via |callback| if the given file |url| has local pending
186 void HasPendingLocalChanges(
187 fileapi::FileSystemContext* file_system_context,
188 const fileapi::FileSystemURL& url,
189 const HasPendingLocalChangeCallback& callback);
191 void PromoteDemotedChanges(const GURL& origin,
192 fileapi::FileSystemContext* file_system_context,
193 const base::Closure& callback);
194 void UpdateChangesForOrigin(const GURL& origin,
195 const base::Closure& callback);
197 // They must be called on UI thread.
198 void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
199 void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
201 // OperationRunner is accessible only on IO thread.
202 base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
204 // SyncContext is accessible only on IO thread.
205 LocalFileSyncStatus* sync_status() const;
207 // For testing; override the duration to notify changes from the
209 void set_mock_notify_changes_duration_in_sec(int duration) {
210 mock_notify_changes_duration_in_sec_ = duration;
214 // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
215 virtual void OnSyncEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
216 virtual void OnWriteEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
219 typedef base::Callback<void(base::File::Error result)> StatusCallback;
220 typedef std::deque<SyncStatusCallback> StatusCallbackQueue;
221 typedef std::deque<fileapi::FileSystemURL> FileSystemURLQueue;
222 friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
223 friend class CannedSyncableFileSystem;
225 virtual ~LocalFileSyncContext();
227 void ShutdownOnIOThread();
229 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
230 // The caller is expected to update origins_with_pending_changes_ before
232 void ScheduleNotifyChangesUpdatedOnIOThread(const base::Closure& callback);
234 // Called by the internal timer on IO thread to notify changes to UI thread.
235 void NotifyAvailableChangesOnIOThread(const base::Closure& callback);
237 // Called from NotifyAvailableChangesOnIOThread.
238 void NotifyAvailableChanges(const std::set<GURL>& origins,
239 const base::Closure& callback);
241 // Helper routines for MaybeInitializeFileSystemContext.
242 void InitializeFileSystemContextOnIOThread(
243 const GURL& source_url,
244 fileapi::FileSystemContext* file_system_context,
245 const GURL& /* root */,
246 const std::string& /* name */,
247 base::File::Error error);
248 SyncStatusCode InitializeChangeTrackerOnFileThread(
249 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
250 fileapi::FileSystemContext* file_system_context,
251 std::set<GURL>* origins_with_changes);
252 void DidInitializeChangeTrackerOnIOThread(
253 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
254 const GURL& source_url,
255 fileapi::FileSystemContext* file_system_context,
256 std::set<GURL>* origins_with_changes,
257 SyncStatusCode status);
259 const GURL& source_url,
260 fileapi::FileSystemContext* file_system_context,
261 SyncStatusCode status);
263 // Helper routines for GetFileForLocalSync.
264 scoped_ptr<FileSystemURLQueue> GetNextURLsForSyncOnFileThread(
265 fileapi::FileSystemContext* file_system_context);
266 void TryPrepareForLocalSync(
267 fileapi::FileSystemContext* file_system_context,
268 const LocalFileSyncInfoCallback& callback,
269 scoped_ptr<FileSystemURLQueue> urls);
270 void DidTryPrepareForLocalSync(
271 fileapi::FileSystemContext* file_system_context,
272 scoped_ptr<FileSystemURLQueue> remaining_urls,
273 const LocalFileSyncInfoCallback& callback,
274 SyncStatusCode status,
275 const LocalFileSyncInfo& sync_file_info,
276 webkit_blob::ScopedFile snapshot);
277 void PromoteDemotedChangesForURL(
278 fileapi::FileSystemContext* file_system_context,
279 const fileapi::FileSystemURL& url);
280 void PromoteDemotedChangesForURLs(
281 fileapi::FileSystemContext* file_system_context,
282 scoped_ptr<FileSystemURLQueue> url);
284 // Callback routine for PrepareForSync and GetFileForLocalSync.
285 void DidGetWritingStatusForSync(
286 fileapi::FileSystemContext* file_system_context,
287 SyncStatusCode status,
288 const fileapi::FileSystemURL& url,
290 const LocalFileSyncInfoCallback& callback);
292 // Helper routine for sync/writing flag handling.
294 // If |for_snapshot_sync| is true, this increments the writing counter
295 // for |url| (after clearing syncing flag), so that other sync activities
296 // won't step in while snapshot sync is ongoing.
297 // In this case FinalizeSnapshotSyncOnIOThread must be called after the
298 // snapshot sync is finished to decrement the writing counter.
299 void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL& url,
300 bool for_snapshot_sync);
301 void FinalizeSnapshotSyncOnIOThread(const fileapi::FileSystemURL& url);
303 void HandleRemoteDelete(
304 fileapi::FileSystemContext* file_system_context,
305 const fileapi::FileSystemURL& url,
306 const SyncStatusCallback& callback);
307 void HandleRemoteAddOrUpdate(
308 fileapi::FileSystemContext* file_system_context,
309 const FileChange& change,
310 const base::FilePath& local_path,
311 const fileapi::FileSystemURL& url,
312 const SyncStatusCallback& callback);
313 void DidRemoveExistingEntryForRemoteAddOrUpdate(
314 fileapi::FileSystemContext* file_system_context,
315 const FileChange& change,
316 const base::FilePath& local_path,
317 const fileapi::FileSystemURL& url,
318 const SyncStatusCallback& callback,
319 base::File::Error error);
321 // Callback routine for ApplyRemoteChange.
322 void DidApplyRemoteChange(
323 const fileapi::FileSystemURL& url,
324 const SyncStatusCallback& callback_on_ui,
325 base::File::Error file_error);
327 void DidGetFileMetadata(
328 const SyncFileMetadataCallback& callback,
329 base::File::Error file_error,
330 const base::File::Info& file_info);
332 base::TimeDelta NotifyChangesDuration();
334 void DidCreateDirectoryForCopyIn(
335 fileapi::FileSystemContext* file_system_context,
336 const base::FilePath& local_file_path,
337 const fileapi::FileSystemURL& dest_url,
338 const StatusCallback& callback,
339 base::File::Error error);
341 const base::FilePath local_base_path_;
342 leveldb::Env* env_override_;
344 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
345 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
347 // Indicates if the sync service is shutdown.
348 bool shutdown_on_ui_; // Updated and referred only on UI thread.
349 bool shutdown_on_io_; // Updated and referred only on IO thread.
351 // OperationRunner. This must be accessed only on IO thread.
352 scoped_ptr<SyncableFileOperationRunner> operation_runner_;
354 // Keeps track of writing/syncing status.
355 // This must be accessed only on IO thread.
356 scoped_ptr<LocalFileSyncStatus> sync_status_;
358 // Pointers to file system contexts that have been initialized for
359 // synchronization (i.e. that own this instance).
360 // This must be accessed only on UI thread.
361 std::set<fileapi::FileSystemContext*> file_system_contexts_;
363 // Accessed only on UI thread.
364 std::map<fileapi::FileSystemContext*, StatusCallbackQueue>
365 pending_initialize_callbacks_;
367 // A URL and associated callback waiting for sync is enabled.
368 // Accessed only on IO thread.
369 fileapi::FileSystemURL url_waiting_sync_on_io_;
370 base::Closure url_syncable_callback_;
372 // Used only on IO thread for available changes notifications.
373 base::Time last_notified_changes_;
374 scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_;
375 std::set<GURL> origins_with_pending_changes_;
377 // Populated while root directory deletion is being handled for
378 // ApplyRemoteChange(). Modified only on IO thread.
379 scoped_ptr<RootDeleteHelper> root_delete_helper_;
381 ObserverList<LocalOriginChangeObserver> origin_change_observers_;
383 int mock_notify_changes_duration_in_sec_;
385 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
388 } // namespace sync_file_system
390 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_