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 void UpdateChangesForOrigin(const GURL& origin);
195 // They must be called on UI thread.
196 void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
197 void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
199 // OperationRunner is accessible only on IO thread.
200 base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
202 // SyncContext is accessible only on IO thread.
203 LocalFileSyncStatus* sync_status() const;
205 // For testing; override the duration to notify changes from the
207 void set_mock_notify_changes_duration_in_sec(int duration) {
208 mock_notify_changes_duration_in_sec_ = duration;
212 // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
213 virtual void OnSyncEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
214 virtual void OnWriteEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
217 typedef base::Callback<void(base::File::Error result)> StatusCallback;
218 typedef std::deque<SyncStatusCallback> StatusCallbackQueue;
219 friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
220 friend class CannedSyncableFileSystem;
222 virtual ~LocalFileSyncContext();
224 void ShutdownOnIOThread();
226 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
227 // The caller is expected to update origins_with_pending_changes_ before
229 void ScheduleNotifyChangesUpdatedOnIOThread();
231 // Called by the internal timer on IO thread to notify changes to UI thread.
232 void NotifyAvailableChangesOnIOThread();
234 // Called from NotifyAvailableChangesOnIOThread.
235 void NotifyAvailableChanges(const std::set<GURL>& origins);
237 // Helper routines for MaybeInitializeFileSystemContext.
238 void InitializeFileSystemContextOnIOThread(
239 const GURL& source_url,
240 fileapi::FileSystemContext* file_system_context,
241 const GURL& /* root */,
242 const std::string& /* name */,
243 base::File::Error error);
244 SyncStatusCode InitializeChangeTrackerOnFileThread(
245 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
246 fileapi::FileSystemContext* file_system_context,
247 std::set<GURL>* origins_with_changes);
248 void DidInitializeChangeTrackerOnIOThread(
249 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
250 const GURL& source_url,
251 fileapi::FileSystemContext* file_system_context,
252 std::set<GURL>* origins_with_changes,
253 SyncStatusCode status);
255 const GURL& source_url,
256 fileapi::FileSystemContext* file_system_context,
257 SyncStatusCode status);
259 // Helper routines for GetFileForLocalSync.
260 void GetNextURLsForSyncOnFileThread(
261 fileapi::FileSystemContext* file_system_context,
262 std::deque<fileapi::FileSystemURL>* urls);
263 void TryPrepareForLocalSync(
264 fileapi::FileSystemContext* file_system_context,
265 std::deque<fileapi::FileSystemURL>* urls,
266 const LocalFileSyncInfoCallback& callback);
267 void DidTryPrepareForLocalSync(
268 fileapi::FileSystemContext* file_system_context,
269 std::deque<fileapi::FileSystemURL>* remaining_urls,
270 const LocalFileSyncInfoCallback& callback,
271 SyncStatusCode status,
272 const LocalFileSyncInfo& sync_file_info,
273 webkit_blob::ScopedFile snapshot);
275 // Callback routine for PrepareForSync and GetFileForLocalSync.
276 void DidGetWritingStatusForSync(
277 fileapi::FileSystemContext* file_system_context,
278 SyncStatusCode status,
279 const fileapi::FileSystemURL& url,
281 const LocalFileSyncInfoCallback& callback);
283 // Helper routine for sync/writing flag handling.
285 // If |for_snapshot_sync| is true, this increments the writing counter
286 // for |url| (after clearing syncing flag), so that other sync activities
287 // won't step in while snapshot sync is ongoing.
288 // In this case FinalizeSnapshotSyncOnIOThread must be called after the
289 // snapshot sync is finished to decrement the writing counter.
290 void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL& url,
291 bool for_snapshot_sync);
292 void FinalizeSnapshotSyncOnIOThread(const fileapi::FileSystemURL& url);
294 void HandleRemoteDelete(
295 fileapi::FileSystemContext* file_system_context,
296 const fileapi::FileSystemURL& url,
297 const SyncStatusCallback& callback);
298 void HandleRemoteAddOrUpdate(
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 void DidRemoveExistingEntryForRemoteAddOrUpdate(
305 fileapi::FileSystemContext* file_system_context,
306 const FileChange& change,
307 const base::FilePath& local_path,
308 const fileapi::FileSystemURL& url,
309 const SyncStatusCallback& callback,
310 base::File::Error error);
312 // Callback routine for ApplyRemoteChange.
313 void DidApplyRemoteChange(
314 const fileapi::FileSystemURL& url,
315 const SyncStatusCallback& callback_on_ui,
316 base::File::Error file_error);
318 void DidGetFileMetadata(
319 const SyncFileMetadataCallback& callback,
320 base::File::Error file_error,
321 const base::File::Info& file_info);
323 base::TimeDelta NotifyChangesDuration();
325 void DidCreateDirectoryForCopyIn(
326 fileapi::FileSystemContext* file_system_context,
327 const base::FilePath& local_file_path,
328 const fileapi::FileSystemURL& dest_url,
329 const StatusCallback& callback,
330 base::File::Error error);
332 const base::FilePath local_base_path_;
333 leveldb::Env* env_override_;
335 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
336 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
338 // Indicates if the sync service is shutdown.
339 bool shutdown_on_ui_; // Updated and referred only on UI thread.
340 bool shutdown_on_io_; // Updated and referred only on IO thread.
342 // OperationRunner. This must be accessed only on IO thread.
343 scoped_ptr<SyncableFileOperationRunner> operation_runner_;
345 // Keeps track of writing/syncing status.
346 // This must be accessed only on IO thread.
347 scoped_ptr<LocalFileSyncStatus> sync_status_;
349 // Pointers to file system contexts that have been initialized for
350 // synchronization (i.e. that own this instance).
351 // This must be accessed only on UI thread.
352 std::set<fileapi::FileSystemContext*> file_system_contexts_;
354 // Accessed only on UI thread.
355 std::map<fileapi::FileSystemContext*, StatusCallbackQueue>
356 pending_initialize_callbacks_;
358 // A URL and associated callback waiting for sync is enabled.
359 // Accessed only on IO thread.
360 fileapi::FileSystemURL url_waiting_sync_on_io_;
361 base::Closure url_syncable_callback_;
363 // Used only on IO thread for available changes notifications.
364 base::Time last_notified_changes_;
365 scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_;
366 std::set<GURL> origins_with_pending_changes_;
368 // Populated while root directory deletion is being handled for
369 // ApplyRemoteChange(). Modified only on IO thread.
370 scoped_ptr<RootDeleteHelper> root_delete_helper_;
372 ObserverList<LocalOriginChangeObserver> origin_change_observers_;
374 int mock_notify_changes_duration_in_sec_;
376 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
379 } // namespace sync_file_system
381 #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_