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