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