local_file_sync_context.h revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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.
4
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_
7
8#include <deque>
9#include <map>
10#include <set>
11#include <string>
12
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"
25#include "url/gurl.h"
26
27namespace base {
28class SingleThreadTaskRunner;
29}
30
31namespace fileapi {
32class FileSystemContext;
33class FileSystemURL;
34}
35
36namespace webkit_blob {
37class ScopedFile;
38}
39
40namespace sync_file_system {
41
42class FileChange;
43class LocalFileChangeTracker;
44struct LocalFileSyncInfo;
45class LocalOriginChangeObserver;
46class RootDeleteHelper;
47class SyncableFileOperationRunner;
48
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.
54class LocalFileSyncContext
55    : public base::RefCountedThreadSafe<LocalFileSyncContext>,
56      public LocalFileSyncStatus::Observer {
57 public:
58  enum SyncMode {
59    SYNC_EXCLUSIVE,
60    SYNC_SNAPSHOT,
61  };
62
63  typedef base::Callback<void(
64      SyncStatusCode status,
65      const LocalFileSyncInfo& sync_file_info,
66      webkit_blob::ScopedFile snapshot)>
67          LocalFileSyncInfoCallback;
68
69  typedef base::Callback<void(SyncStatusCode status,
70                              bool has_pending_changes)>
71      HasPendingLocalChangeCallback;
72
73  LocalFileSyncContext(const base::FilePath& base_path,
74                       base::SingleThreadTaskRunner* ui_task_runner,
75                       base::SingleThreadTaskRunner* io_task_runner);
76
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);
85
86  // Called when the corresponding LocalFileSyncService exits.
87  // This method must be called on UI thread.
88  void ShutdownOnUIThread();
89
90  // Picks a file for next local sync and returns it after disabling writes
91  // for the file.
92  // This method must be called on UI thread.
93  void GetFileForLocalSync(fileapi::FileSystemContext* file_system_context,
94                           const LocalFileSyncInfoCallback& callback);
95
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);
103
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);
115
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);
123
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|.
128  //
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.
132  //
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.
137  //
138  // This method must be called on UI thread.
139  void PrepareForSync(fileapi::FileSystemContext* file_system_context,
140                      const fileapi::FileSystemURL& url,
141                      SyncMode sync_mode,
142                      const LocalFileSyncInfoCallback& callback);
143
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
147  // for sync).
148  //
149  // Calling this method again while this already has another URL waiting
150  // for sync will overwrite the previously registered URL.
151  //
152  // This method must be called on UI thread.
153  void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url,
154                                 const base::Closure& on_syncable_callback);
155
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);
164
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);
171
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);
177
178  // Returns true via |callback| if the given file |url| has local pending
179  // changes.
180  void HasPendingLocalChanges(
181      fileapi::FileSystemContext* file_system_context,
182      const fileapi::FileSystemURL& url,
183      const HasPendingLocalChangeCallback& callback);
184
185  // They must be called on UI thread.
186  void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
187  void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
188
189  // OperationRunner is accessible only on IO thread.
190  base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
191
192  // SyncContext is accessible only on IO thread.
193  LocalFileSyncStatus* sync_status() const;
194
195  // For testing; override the duration to notify changes from the
196  // default value.
197  void set_mock_notify_changes_duration_in_sec(int duration) {
198    mock_notify_changes_duration_in_sec_ = duration;
199  }
200
201 protected:
202  // LocalFileSyncStatus::Observer overrides. They are called on IO thread.
203  virtual void OnSyncEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
204  virtual void OnWriteEnabled(const fileapi::FileSystemURL& url) OVERRIDE;
205
206 private:
207  typedef base::Callback<void(base::PlatformFileError result)> StatusCallback;
208  typedef std::deque<SyncStatusCallback> StatusCallbackQueue;
209  friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
210  friend class CannedSyncableFileSystem;
211
212  virtual ~LocalFileSyncContext();
213
214  void ShutdownOnIOThread();
215
216  // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
217  // The caller is expected to update origins_with_pending_changes_ before
218  // calling this.
219  void ScheduleNotifyChangesUpdatedOnIOThread();
220
221  // Called by the internal timer on IO thread to notify changes to UI thread.
222  void NotifyAvailableChangesOnIOThread();
223
224  // Called from NotifyAvailableChangesOnIOThread.
225  void NotifyAvailableChanges(const std::set<GURL>& origins);
226
227  // Helper routines for MaybeInitializeFileSystemContext.
228  void InitializeFileSystemContextOnIOThread(
229      const GURL& source_url,
230      fileapi::FileSystemContext* file_system_context,
231      const GURL& /* root */,
232      const std::string& /* name */,
233      base::PlatformFileError error);
234  SyncStatusCode InitializeChangeTrackerOnFileThread(
235      scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
236      fileapi::FileSystemContext* file_system_context,
237      std::set<GURL>* origins_with_changes);
238  void DidInitializeChangeTrackerOnIOThread(
239      scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
240      const GURL& source_url,
241      fileapi::FileSystemContext* file_system_context,
242      std::set<GURL>* origins_with_changes,
243      SyncStatusCode status);
244  void DidInitialize(
245      const GURL& source_url,
246      fileapi::FileSystemContext* file_system_context,
247      SyncStatusCode status);
248
249  // Helper routines for GetFileForLocalSync.
250  void GetNextURLsForSyncOnFileThread(
251      fileapi::FileSystemContext* file_system_context,
252      std::deque<fileapi::FileSystemURL>* urls);
253  void TryPrepareForLocalSync(
254      fileapi::FileSystemContext* file_system_context,
255      std::deque<fileapi::FileSystemURL>* urls,
256      const LocalFileSyncInfoCallback& callback);
257  void DidTryPrepareForLocalSync(
258      fileapi::FileSystemContext* file_system_context,
259      std::deque<fileapi::FileSystemURL>* remaining_urls,
260      const LocalFileSyncInfoCallback& callback,
261      SyncStatusCode status,
262      const LocalFileSyncInfo& sync_file_info,
263      webkit_blob::ScopedFile snapshot);
264
265  // Callback routine for PrepareForSync and GetFileForLocalSync.
266  void DidGetWritingStatusForSync(
267      fileapi::FileSystemContext* file_system_context,
268      SyncStatusCode status,
269      const fileapi::FileSystemURL& url,
270      SyncMode sync_mode,
271      const LocalFileSyncInfoCallback& callback);
272
273  // Helper routine for sync/writing flag handling.
274  //
275  // If |for_snapshot_sync| is true, this increments the writing counter
276  // for |url| (after clearing syncing flag), so that other sync activities
277  // won't step in while snapshot sync is ongoing.
278  // In this case FinalizeSnapshotSyncOnIOThread must be called after the
279  // snapshot sync is finished to decrement the writing counter.
280  void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL& url,
281                               bool for_snapshot_sync);
282  void FinalizeSnapshotSyncOnIOThread(const fileapi::FileSystemURL& url);
283
284  void HandleRemoteDelete(
285      fileapi::FileSystemContext* file_system_context,
286      const fileapi::FileSystemURL& url,
287      const SyncStatusCallback& callback);
288  void HandleRemoteAddOrUpdate(
289      fileapi::FileSystemContext* file_system_context,
290      const FileChange& change,
291      const base::FilePath& local_path,
292      const fileapi::FileSystemURL& url,
293      const SyncStatusCallback& callback);
294  void DidRemoveExistingEntryForRemoteAddOrUpdate(
295      fileapi::FileSystemContext* file_system_context,
296      const FileChange& change,
297      const base::FilePath& local_path,
298      const fileapi::FileSystemURL& url,
299      const SyncStatusCallback& callback,
300      base::PlatformFileError error);
301
302  // Callback routine for ApplyRemoteChange.
303  void DidApplyRemoteChange(
304      const fileapi::FileSystemURL& url,
305      const SyncStatusCallback& callback_on_ui,
306      base::PlatformFileError file_error);
307
308  void DidGetFileMetadata(
309      const SyncFileMetadataCallback& callback,
310      base::PlatformFileError file_error,
311      const base::PlatformFileInfo& file_info);
312
313  base::TimeDelta NotifyChangesDuration();
314
315  void DidCreateDirectoryForCopyIn(
316      fileapi::FileSystemContext* file_system_context,
317      const base::FilePath& local_file_path,
318      const fileapi::FileSystemURL& dest_url,
319      const StatusCallback& callback,
320      base::PlatformFileError error);
321
322  const base::FilePath local_base_path_;
323
324  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
325  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
326
327  // Indicates if the sync service is shutdown.
328  bool shutdown_on_ui_;  // Updated and referred only on UI thread.
329  bool shutdown_on_io_;  // Updated and referred only on IO thread.
330
331  // OperationRunner. This must be accessed only on IO thread.
332  scoped_ptr<SyncableFileOperationRunner> operation_runner_;
333
334  // Keeps track of writing/syncing status.
335  // This must be accessed only on IO thread.
336  scoped_ptr<LocalFileSyncStatus> sync_status_;
337
338  // Pointers to file system contexts that have been initialized for
339  // synchronization (i.e. that own this instance).
340  // This must be accessed only on UI thread.
341  std::set<fileapi::FileSystemContext*> file_system_contexts_;
342
343  // Accessed only on UI thread.
344  std::map<fileapi::FileSystemContext*, StatusCallbackQueue>
345      pending_initialize_callbacks_;
346
347  // A URL and associated callback waiting for sync is enabled.
348  // Accessed only on IO thread.
349  fileapi::FileSystemURL url_waiting_sync_on_io_;
350  base::Closure url_syncable_callback_;
351
352  // Used only on IO thread for available changes notifications.
353  base::Time last_notified_changes_;
354  scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_;
355  std::set<GURL> origins_with_pending_changes_;
356
357  // Populated while root directory deletion is being handled for
358  // ApplyRemoteChange(). Modified only on IO thread.
359  scoped_ptr<RootDeleteHelper> root_delete_helper_;
360
361  ObserverList<LocalOriginChangeObserver> origin_change_observers_;
362
363  int mock_notify_changes_duration_in_sec_;
364
365  DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
366};
367
368}  // namespace sync_file_system
369
370#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_
371