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