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_SERVICE_H_
      6 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_SERVICE_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <string>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/callback.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "base/observer_list.h"
     17 #include "chrome/browser/sync_file_system/local/local_origin_change_observer.h"
     18 #include "chrome/browser/sync_file_system/remote_change_processor.h"
     19 #include "chrome/browser/sync_file_system/sync_callbacks.h"
     20 #include "chrome/browser/sync_file_system/sync_status_code.h"
     21 
     22 class GURL;
     23 class Profile;
     24 
     25 namespace fileapi {
     26 class FileSystemContext;
     27 }
     28 
     29 namespace leveldb {
     30 class Env;
     31 }
     32 
     33 namespace webkit_blob {
     34 class ScopedFile;
     35 }
     36 
     37 namespace sync_file_system {
     38 
     39 class FileChange;
     40 class LocalChangeProcessor;
     41 class LocalFileSyncContext;
     42 struct LocalFileSyncInfo;
     43 
     44 // Maintains local file change tracker and sync status.
     45 // Owned by SyncFileSystemService (which is a per-profile object).
     46 class LocalFileSyncService
     47     : public RemoteChangeProcessor,
     48       public LocalOriginChangeObserver,
     49       public base::SupportsWeakPtr<LocalFileSyncService> {
     50  public:
     51   typedef base::Callback<LocalChangeProcessor*(const GURL& origin)>
     52       GetLocalChangeProcessorCallback;
     53 
     54   class Observer {
     55    public:
     56     Observer() {}
     57     virtual ~Observer() {}
     58 
     59     // This is called when there're one or more local changes available.
     60     // |pending_changes_hint| indicates the pending queue length to help sync
     61     // scheduling but the value may not be accurately reflect the real-time
     62     // value.
     63     virtual void OnLocalChangeAvailable(int64 pending_changes_hint) = 0;
     64 
     65    private:
     66     DISALLOW_COPY_AND_ASSIGN(Observer);
     67   };
     68 
     69   typedef base::Callback<void(SyncStatusCode status,
     70                               bool has_pending_changes)>
     71       HasPendingLocalChangeCallback;
     72 
     73   static scoped_ptr<LocalFileSyncService> Create(Profile* profile);
     74   static scoped_ptr<LocalFileSyncService> CreateForTesting(
     75       Profile* profile,
     76       leveldb::Env* env_override);
     77   virtual ~LocalFileSyncService();
     78 
     79   void Shutdown();
     80 
     81   void MaybeInitializeFileSystemContext(
     82       const GURL& app_origin,
     83       fileapi::FileSystemContext* file_system_context,
     84       const SyncStatusCallback& callback);
     85 
     86   void AddChangeObserver(Observer* observer);
     87 
     88   // Registers |url| to wait until sync is enabled for |url|.
     89   // |on_syncable_callback| is to be called when |url| becomes syncable
     90   // (i.e. when we have no pending writes and the file is successfully locked
     91   // for sync).
     92   // Calling this method again while this already has another URL waiting
     93   // for sync will overwrite the previously registered URL.
     94   void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url,
     95                                  const base::Closure& on_syncable_callback);
     96 
     97   // Synchronize one (or a set of) local change(s) to the remote server
     98   // using local_change_processor given by SetLocalChangeProcessor().
     99   // |processor| must have same or longer lifetime than this service.
    100   // It is invalid to call this method before calling SetLocalChangeProcessor().
    101   void ProcessLocalChange(const SyncFileCallback& callback);
    102 
    103   // Sets a local change processor. The value is ignored if
    104   // SetLocalChangeProcessorCallback() is called separately.
    105   // Either this or SetLocalChangeProcessorCallback() must be called before
    106   // any ProcessLocalChange().
    107   void SetLocalChangeProcessor(LocalChangeProcessor* local_change_processor);
    108 
    109   // Sets a closure which gets a local change processor for the given origin.
    110   // Note that once this is called it overrides the direct processor setting
    111   // done by SetLocalChangeProcessor().
    112   // Either this or SetLocalChangeProcessor() must be called before any
    113   // ProcessLocalChange().
    114   //
    115   // TODO(kinuko): Remove this method once we stop using multiple backends
    116   // (crbug.com/324215), or deprecate the other if we keep doing so.
    117   void SetLocalChangeProcessorCallback(
    118       const GetLocalChangeProcessorCallback& get_local_change_processor);
    119 
    120   // Returns true via |callback| if the given file |url| has local pending
    121   // changes.
    122   void HasPendingLocalChanges(
    123       const fileapi::FileSystemURL& url,
    124       const HasPendingLocalChangeCallback& callback);
    125 
    126   void PromoteDemotedChanges();
    127 
    128   // Returns the metadata of a remote file pointed by |url|.
    129   virtual void GetLocalFileMetadata(
    130       const fileapi::FileSystemURL& url,
    131       const SyncFileMetadataCallback& callback);
    132 
    133   // RemoteChangeProcessor overrides.
    134   virtual void PrepareForProcessRemoteChange(
    135       const fileapi::FileSystemURL& url,
    136       const PrepareChangeCallback& callback) OVERRIDE;
    137   virtual void ApplyRemoteChange(
    138       const FileChange& change,
    139       const base::FilePath& local_path,
    140       const fileapi::FileSystemURL& url,
    141       const SyncStatusCallback& callback) OVERRIDE;
    142   virtual void FinalizeRemoteSync(
    143       const fileapi::FileSystemURL& url,
    144       bool clear_local_changes,
    145       const base::Closure& completion_callback) OVERRIDE;
    146   virtual void RecordFakeLocalChange(
    147       const fileapi::FileSystemURL& url,
    148       const FileChange& change,
    149       const SyncStatusCallback& callback) OVERRIDE;
    150 
    151   // LocalOriginChangeObserver override.
    152   virtual void OnChangesAvailableInOrigins(
    153       const std::set<GURL>& origins) OVERRIDE;
    154 
    155   // Called when a particular origin (app) is disabled/enabled while
    156   // the service is running. This may be called for origins/apps that
    157   // are not initialized for the service.
    158   void SetOriginEnabled(const GURL& origin, bool enabled);
    159 
    160  private:
    161   typedef std::map<GURL, fileapi::FileSystemContext*> OriginToContext;
    162   friend class OriginChangeMapTest;
    163 
    164   class OriginChangeMap {
    165    public:
    166     typedef std::map<GURL, int64> Map;
    167 
    168     OriginChangeMap();
    169     ~OriginChangeMap();
    170 
    171     // Sets |origin| to the next origin to process. (For now we simply apply
    172     // round-robin to pick the next origin to avoid starvation.)
    173     // Returns false if no origins to process.
    174     bool NextOriginToProcess(GURL* origin);
    175 
    176     int64 GetTotalChangeCount() const;
    177 
    178     // Update change_count_map_ for |origin|.
    179     void SetOriginChangeCount(const GURL& origin, int64 changes);
    180 
    181     void SetOriginEnabled(const GURL& origin, bool enabled);
    182 
    183    private:
    184     // Per-origin changes (cached info, could be stale).
    185     Map change_count_map_;
    186     Map::iterator next_;
    187 
    188     // Holds a set of disabled (but initialized) origins.
    189     std::set<GURL> disabled_origins_;
    190   };
    191 
    192   LocalFileSyncService(Profile* profile, leveldb::Env* env_override);
    193 
    194   void DidInitializeFileSystemContext(
    195       const GURL& app_origin,
    196       fileapi::FileSystemContext* file_system_context,
    197       const SyncStatusCallback& callback,
    198       SyncStatusCode status);
    199   void DidInitializeForRemoteSync(
    200       const fileapi::FileSystemURL& url,
    201       fileapi::FileSystemContext* file_system_context,
    202       const PrepareChangeCallback& callback,
    203       SyncStatusCode status);
    204 
    205   // Runs local_sync_callback_ and resets it.
    206   void RunLocalSyncCallback(
    207       SyncStatusCode status,
    208       const fileapi::FileSystemURL& url);
    209 
    210   // Callback for ApplyRemoteChange.
    211   void DidApplyRemoteChange(
    212       const SyncStatusCallback& callback,
    213       SyncStatusCode status);
    214 
    215   // Callbacks for ProcessLocalChange.
    216   void DidGetFileForLocalSync(
    217       SyncStatusCode status,
    218       const LocalFileSyncInfo& sync_file_info,
    219       webkit_blob::ScopedFile snapshot);
    220   void ProcessNextChangeForURL(
    221       webkit_blob::ScopedFile snapshot,
    222       const LocalFileSyncInfo& sync_file_info,
    223       const FileChange& last_change,
    224       const FileChangeList& changes,
    225       SyncStatusCode status);
    226 
    227   // A thin wrapper of get_local_change_processor_.
    228   LocalChangeProcessor* GetLocalChangeProcessor(
    229       const fileapi::FileSystemURL& url);
    230 
    231   Profile* profile_;
    232 
    233   scoped_refptr<LocalFileSyncContext> sync_context_;
    234 
    235   // Origin to context map. (Assuming that as far as we're in the same
    236   // profile single origin wouldn't belong to multiple FileSystemContexts.)
    237   OriginToContext origin_to_contexts_;
    238 
    239   // Origins which have pending changes but have not been initialized yet.
    240   // (Used only for handling dirty files left in the local tracker database
    241   // after a restart.)
    242   std::set<GURL> pending_origins_with_changes_;
    243 
    244   OriginChangeMap origin_change_map_;
    245 
    246   // This callback is non-null while a local sync is running (i.e.
    247   // ProcessLocalChange has been called and has not been returned yet).
    248   SyncFileCallback local_sync_callback_;
    249 
    250   LocalChangeProcessor* local_change_processor_;
    251   GetLocalChangeProcessorCallback get_local_change_processor_;
    252 
    253   ObserverList<Observer> change_observers_;
    254 
    255   DISALLOW_COPY_AND_ASSIGN(LocalFileSyncService);
    256 };
    257 
    258 }  // namespace sync_file_system
    259 
    260 #endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_SERVICE_H_
    261