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