Home | History | Annotate | Download | only in local
      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 
     28 namespace base {
     29 class SingleThreadTaskRunner;
     30 }
     31 
     32 namespace fileapi {
     33 class FileSystemContext;
     34 class FileSystemURL;
     35 }
     36 
     37 namespace leveldb {
     38 class Env;
     39 }
     40 
     41 namespace webkit_blob {
     42 class ScopedFile;
     43 }
     44 
     45 namespace sync_file_system {
     46 
     47 class FileChange;
     48 class LocalFileChangeTracker;
     49 struct LocalFileSyncInfo;
     50 class LocalOriginChangeObserver;
     51 class RootDeleteHelper;
     52 class 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.
     59 class 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   friend class base::RefCountedThreadSafe<LocalFileSyncContext>;
    220   friend class CannedSyncableFileSystem;
    221 
    222   virtual ~LocalFileSyncContext();
    223 
    224   void ShutdownOnIOThread();
    225 
    226   // Starts a timer to eventually call NotifyAvailableChangesOnIOThread.
    227   // The caller is expected to update origins_with_pending_changes_ before
    228   // calling this.
    229   void ScheduleNotifyChangesUpdatedOnIOThread();
    230 
    231   // Called by the internal timer on IO thread to notify changes to UI thread.
    232   void NotifyAvailableChangesOnIOThread();
    233 
    234   // Called from NotifyAvailableChangesOnIOThread.
    235   void NotifyAvailableChanges(const std::set<GURL>& origins);
    236 
    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);
    254   void DidInitialize(
    255       const GURL& source_url,
    256       fileapi::FileSystemContext* file_system_context,
    257       SyncStatusCode status);
    258 
    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);
    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