local_file_sync_context.h revision 116680a4aac90f2aa7413d9095a592090648e557
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.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"
26#include "url/gurl.h"
27
28namespace base {
29class SingleThreadTaskRunner;
30}
31
32namespace fileapi {
33class FileSystemContext;
34class FileSystemURL;
35}
36
37namespace leveldb {
38class Env;
39}
40
41namespace webkit_blob {
42class ScopedFile;
43}
44
45namespace sync_file_system {
46
47class FileChange;
48class LocalFileChangeTracker;
49struct LocalFileSyncInfo;
50class LocalOriginChangeObserver;
51class RootDeleteHelper;
52class SyncableFileOperationRunner;
53
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.
59class LocalFileSyncContext
60    : public base::RefCountedThreadSafe<LocalFileSyncContext>,
61      public LocalFileSyncStatus::Observer {
62 public:
63  enum SyncMode {
64    SYNC_EXCLUSIVE,
65    SYNC_SNAPSHOT,
66  };
67
68  typedef base::Callback<void(
69      SyncStatusCode status,
70      const LocalFileSyncInfo& sync_file_info,
71      webkit_blob::ScopedFile snapshot)>
72          LocalFileSyncInfoCallback;
73
74  typedef base::Callback<void(SyncStatusCode status,
75                              bool has_pending_changes)>
76      HasPendingLocalChangeCallback;
77
78  LocalFileSyncContext(const base::FilePath& base_path,
79                       leveldb::Env* env_override,
80                       base::SingleThreadTaskRunner* ui_task_runner,
81                       base::SingleThreadTaskRunner* io_task_runner);
82
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);
91
92  // Called when the corresponding LocalFileSyncService exits.
93  // This method must be called on UI thread.
94  void ShutdownOnUIThread();
95
96  // Picks a file for next local sync and returns it after disabling writes
97  // for the file.
98  // This method must be called on UI thread.
99  void GetFileForLocalSync(fileapi::FileSystemContext* file_system_context,
100                           const LocalFileSyncInfoCallback& callback);
101
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);
109
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);
121
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);
129
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|.
134  //
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.
138  //
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.
143  //
144  // This method must be called on UI thread.
145  void PrepareForSync(fileapi::FileSystemContext* file_system_context,
146                      const fileapi::FileSystemURL& url,
147                      SyncMode sync_mode,
148                      const LocalFileSyncInfoCallback& callback);
149
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
153  // for sync).
154  //
155  // Calling this method again while this already has another URL waiting
156  // for sync will overwrite the previously registered URL.
157  //
158  // This method must be called on UI thread.
159  void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url,
160                                 const base::Closure& on_syncable_callback);
161
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);
170
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);
177
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);
183
184  // Returns true via |callback| if the given file |url| has local pending
185  // changes.
186  void HasPendingLocalChanges(
187      fileapi::FileSystemContext* file_system_context,
188      const fileapi::FileSystemURL& url,
189      const HasPendingLocalChangeCallback& callback);
190
191  void PromoteDemotedChanges(const GURL& origin,
192                             fileapi::FileSystemContext* file_system_context);
193  void UpdateChangesForOrigin(const GURL& origin);
194
195  // They must be called on UI thread.
196  void AddOriginChangeObserver(LocalOriginChangeObserver* observer);
197  void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer);
198
199  // OperationRunner is accessible only on IO thread.
200  base::WeakPtr<SyncableFileOperationRunner> operation_runner() const;
201
202  // SyncContext is accessible only on IO thread.
203  LocalFileSyncStatus* sync_status() const;
204
205  // For testing; override the duration to notify changes from the
206  // default value.
207  void set_mock_notify_changes_duration_in_sec(int duration) {
208    mock_notify_changes_duration_in_sec_ = duration;
209  }
210
211 protected:
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;
215
216 private:
217  typedef base::Callback<void(base::File::Error result)> StatusCallback;
218  typedef std::deque<SyncStatusCallback> StatusCallbackQueue;
219  typedef std::deque<fileapi::FileSystemURL> FileSystemURLQueue;
220  friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
221  friend class CannedSyncableFileSystem;
222
223  virtual ~LocalFileSyncContext();
224
225  void ShutdownOnIOThread();
226
227  // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
228  // The caller is expected to update origins_with_pending_changes_ before
229  // calling this.
230  void ScheduleNotifyChangesUpdatedOnIOThread();
231
232  // Called by the internal timer on IO thread to notify changes to UI thread.
233  void NotifyAvailableChangesOnIOThread();
234
235  // Called from NotifyAvailableChangesOnIOThread.
236  void NotifyAvailableChanges(const std::set<GURL>& origins);
237
238  // Helper routines for MaybeInitializeFileSystemContext.
239  void InitializeFileSystemContextOnIOThread(
240      const GURL& source_url,
241      fileapi::FileSystemContext* file_system_context,
242      const GURL& /* root */,
243      const std::string& /* name */,
244      base::File::Error error);
245  SyncStatusCode InitializeChangeTrackerOnFileThread(
246      scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
247      fileapi::FileSystemContext* file_system_context,
248      std::set<GURL>* origins_with_changes);
249  void DidInitializeChangeTrackerOnIOThread(
250      scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
251      const GURL& source_url,
252      fileapi::FileSystemContext* file_system_context,
253      std::set<GURL>* origins_with_changes,
254      SyncStatusCode status);
255  void DidInitialize(
256      const GURL& source_url,
257      fileapi::FileSystemContext* file_system_context,
258      SyncStatusCode status);
259
260  // Helper routines for GetFileForLocalSync.
261  scoped_ptr<FileSystemURLQueue> GetNextURLsForSyncOnFileThread(
262      fileapi::FileSystemContext* file_system_context);
263  void TryPrepareForLocalSync(
264      fileapi::FileSystemContext* file_system_context,
265      const LocalFileSyncInfoCallback& callback,
266      scoped_ptr<FileSystemURLQueue> urls);
267  void DidTryPrepareForLocalSync(
268      fileapi::FileSystemContext* file_system_context,
269      scoped_ptr<FileSystemURLQueue> remaining_urls,
270      const LocalFileSyncInfoCallback& callback,
271      SyncStatusCode status,
272      const LocalFileSyncInfo& sync_file_info,
273      webkit_blob::ScopedFile snapshot);
274
275  // Callback routine for PrepareForSync and GetFileForLocalSync.
276  void DidGetWritingStatusForSync(
277      fileapi::FileSystemContext* file_system_context,
278      SyncStatusCode status,
279      const fileapi::FileSystemURL& url,
280      SyncMode sync_mode,
281      const LocalFileSyncInfoCallback& callback);
282
283  // Helper routine for sync/writing flag handling.
284  //
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);
293
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);
311
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);
317
318  void DidGetFileMetadata(
319      const SyncFileMetadataCallback& callback,
320      base::File::Error file_error,
321      const base::File::Info& file_info);
322
323  base::TimeDelta NotifyChangesDuration();
324
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);
331
332  const base::FilePath local_base_path_;
333  leveldb::Env* env_override_;
334
335  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
336  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
337
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.
341
342  // OperationRunner. This must be accessed only on IO thread.
343  scoped_ptr<SyncableFileOperationRunner> operation_runner_;
344
345  // Keeps track of writing/syncing status.
346  // This must be accessed only on IO thread.
347  scoped_ptr<LocalFileSyncStatus> sync_status_;
348
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_;
353
354  // Accessed only on UI thread.
355  std::map<fileapi::FileSystemContext*, StatusCallbackQueue>
356      pending_initialize_callbacks_;
357
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_;
362
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_;
367
368  // Populated while root directory deletion is being handled for
369  // ApplyRemoteChange(). Modified only on IO thread.
370  scoped_ptr<RootDeleteHelper> root_delete_helper_;
371
372  ObserverList<LocalOriginChangeObserver> origin_change_observers_;
373
374  int mock_notify_changes_duration_in_sec_;
375
376  DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext);
377};
378
379}  // namespace sync_file_system
380
381#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_
382