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