local_file_sync_context.h revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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 // Clears all pending local changes for |url|. |done_callback| is called 96 // when the changes are cleared. 97 // This method must be called on UI thread. 98 void ClearChangesForURL(fileapi::FileSystemContext* file_system_context, 99 const fileapi::FileSystemURL& url, 100 const base::Closure& done_callback); 101 102 // Updates the on-disk dirty flag for |url| in the tracker DB. 103 // This will clear the dirty flag if |sync_finish_status| is SYNC_STATUS_OK 104 // or SYNC_STATUS_HAS_CONFLICT. 105 // |done_callback| is called when the changes are committed. 106 void CommitChangeStatusForURL( 107 fileapi::FileSystemContext* file_system_context, 108 const fileapi::FileSystemURL& url, 109 SyncStatusCode sync_finish_status, 110 const base::Closure& done_callback); 111 112 // A local or remote sync has been finished (either successfully or 113 // with an error). Clears the internal sync flag and enable writing for |url|. 114 // This method must be called on UI thread. 115 void ClearSyncFlagForURL(const fileapi::FileSystemURL& url); 116 117 // Prepares for sync |url| by disabling writes on |url|. 118 // If the target |url| is being written and cannot start sync it 119 // returns SYNC_STATUS_WRITING status code via |callback|. 120 // Otherwise returns the current change sets made on |url|. 121 // 122 // If |sync_mode| is SYNC_EXCLUSIVE this leaves the target file. 123 // If |sync_mode| is SYNC_SNAPSHOT this creates a snapshot (if the 124 // target file is not deleted) and unlocks the file before returning. 125 // 126 // This method must be called on UI thread. 127 void PrepareForSync(fileapi::FileSystemContext* file_system_context, 128 const fileapi::FileSystemURL& url, 129 SyncMode sync_mode, 130 const LocalFileSyncInfoCallback& callback); 131 132 // Registers |url| to wait until sync is enabled for |url|. 133 // |on_syncable_callback| is to be called when |url| becomes syncable 134 // (i.e. when we have no pending writes and the file is successfully locked 135 // for sync). 136 // 137 // Calling this method again while this already has another URL waiting 138 // for sync will overwrite the previously registered URL. 139 // 140 // This method must be called on UI thread. 141 void RegisterURLForWaitingSync(const fileapi::FileSystemURL& url, 142 const base::Closure& on_syncable_callback); 143 144 // Applies a remote change. 145 // This method must be called on UI thread. 146 void ApplyRemoteChange( 147 fileapi::FileSystemContext* file_system_context, 148 const FileChange& change, 149 const base::FilePath& local_path, 150 const fileapi::FileSystemURL& url, 151 const SyncStatusCallback& callback); 152 153 // Records a fake local change in the local change tracker. 154 void RecordFakeLocalChange( 155 fileapi::FileSystemContext* file_system_context, 156 const fileapi::FileSystemURL& url, 157 const FileChange& change, 158 const SyncStatusCallback& callback); 159 160 // This must be called on UI thread. 161 void GetFileMetadata( 162 fileapi::FileSystemContext* file_system_context, 163 const fileapi::FileSystemURL& url, 164 const SyncFileMetadataCallback& callback); 165 166 // Returns true via |callback| if the given file |url| has local pending 167 // changes. 168 void HasPendingLocalChanges( 169 fileapi::FileSystemContext* file_system_context, 170 const fileapi::FileSystemURL& url, 171 const HasPendingLocalChangeCallback& callback); 172 173 // They must be called on UI thread. 174 void AddOriginChangeObserver(LocalOriginChangeObserver* observer); 175 void RemoveOriginChangeObserver(LocalOriginChangeObserver* observer); 176 177 // OperationRunner is accessible only on IO thread. 178 base::WeakPtr<SyncableFileOperationRunner> operation_runner() const; 179 180 // SyncContext is accessible only on IO thread. 181 LocalFileSyncStatus* sync_status() const; 182 183 // For testing; override the duration to notify changes from the 184 // default value. 185 void set_mock_notify_changes_duration_in_sec(int duration) { 186 mock_notify_changes_duration_in_sec_ = duration; 187 } 188 189 protected: 190 // LocalFileSyncStatus::Observer overrides. They are called on IO thread. 191 virtual void OnSyncEnabled(const fileapi::FileSystemURL& url) OVERRIDE; 192 virtual void OnWriteEnabled(const fileapi::FileSystemURL& url) OVERRIDE; 193 194 private: 195 typedef base::Callback<void(base::PlatformFileError result)> StatusCallback; 196 typedef std::deque<SyncStatusCallback> StatusCallbackQueue; 197 friend class base::RefCountedThreadSafe<LocalFileSyncContext>; 198 friend class CannedSyncableFileSystem; 199 200 virtual ~LocalFileSyncContext(); 201 202 void ShutdownOnIOThread(); 203 204 // Starts a timer to eventually call NotifyAvailableChangesOnIOThread. 205 // The caller is expected to update origins_with_pending_changes_ before 206 // calling this. 207 void ScheduleNotifyChangesUpdatedOnIOThread(); 208 209 // Called by the internal timer on IO thread to notify changes to UI thread. 210 void NotifyAvailableChangesOnIOThread(); 211 212 // Called from NotifyAvailableChangesOnIOThread. 213 void NotifyAvailableChanges(const std::set<GURL>& origins); 214 215 // Helper routines for MaybeInitializeFileSystemContext. 216 void InitializeFileSystemContextOnIOThread( 217 const GURL& source_url, 218 fileapi::FileSystemContext* file_system_context); 219 SyncStatusCode InitializeChangeTrackerOnFileThread( 220 scoped_ptr<LocalFileChangeTracker>* tracker_ptr, 221 fileapi::FileSystemContext* file_system_context, 222 std::set<GURL>* origins_with_changes); 223 void DidInitializeChangeTrackerOnIOThread( 224 scoped_ptr<LocalFileChangeTracker>* tracker_ptr, 225 const GURL& source_url, 226 fileapi::FileSystemContext* file_system_context, 227 std::set<GURL>* origins_with_changes, 228 SyncStatusCode status); 229 void DidInitialize( 230 const GURL& source_url, 231 fileapi::FileSystemContext* file_system_context, 232 SyncStatusCode status); 233 234 // Helper routines for GetFileForLocalSync. 235 void GetNextURLsForSyncOnFileThread( 236 fileapi::FileSystemContext* file_system_context, 237 std::deque<fileapi::FileSystemURL>* urls); 238 void TryPrepareForLocalSync( 239 fileapi::FileSystemContext* file_system_context, 240 std::deque<fileapi::FileSystemURL>* urls, 241 const LocalFileSyncInfoCallback& callback); 242 void DidTryPrepareForLocalSync( 243 fileapi::FileSystemContext* file_system_context, 244 std::deque<fileapi::FileSystemURL>* remaining_urls, 245 const LocalFileSyncInfoCallback& callback, 246 SyncStatusCode status, 247 const LocalFileSyncInfo& sync_file_info, 248 scoped_ptr<webkit_blob::ScopedFile> snapshot); 249 250 // Callback routine for PrepareForSync and GetFileForLocalSync. 251 void DidGetWritingStatusForSync( 252 fileapi::FileSystemContext* file_system_context, 253 SyncStatusCode status, 254 const fileapi::FileSystemURL& url, 255 SyncMode sync_mode, 256 const LocalFileSyncInfoCallback& callback); 257 258 // Helper routine for sync/writing flag handling, primarily for 259 // ClearSyncFlagForURL but is also called by other internal routines. 260 // If |keep_url_in_writing| is true this increments the writing counter 261 // for |url| (after clearing syncing flag), so that the caller can 262 // continue to hold a shared lock on the URL. 263 // (The counter must be manually decremented by EndWritingOnIOThread 264 // if that's the case) 265 void ClearSyncFlagOnIOThread(const fileapi::FileSystemURL& url, 266 bool keep_url_in_writing); 267 void EndWritingOnIOThread(const fileapi::FileSystemURL& url); 268 269 void DidRemoveExistingEntryForApplyRemoteChange( 270 fileapi::FileSystemContext* file_system_context, 271 const FileChange& change, 272 const base::FilePath& local_path, 273 const fileapi::FileSystemURL& url, 274 const SyncStatusCallback& callback, 275 base::PlatformFileError error); 276 277 // Callback routine for ApplyRemoteChange. 278 void DidApplyRemoteChange( 279 const fileapi::FileSystemURL& url, 280 const SyncStatusCallback& callback_on_ui, 281 base::PlatformFileError file_error); 282 283 void DidGetFileMetadata( 284 const SyncFileMetadataCallback& callback, 285 base::PlatformFileError file_error, 286 const base::PlatformFileInfo& file_info); 287 288 base::TimeDelta NotifyChangesDuration(); 289 290 void DidCreateDirectoryForCopyIn( 291 fileapi::FileSystemContext* file_system_context, 292 const base::FilePath& local_file_path, 293 const fileapi::FileSystemURL& dest_url, 294 const StatusCallback& callback, 295 base::PlatformFileError error); 296 297 const base::FilePath local_base_path_; 298 299 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 300 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 301 302 // Indicates if the sync service is shutdown on UI thread. 303 bool shutdown_on_ui_; 304 305 // OperationRunner. This must be accessed only on IO thread. 306 scoped_ptr<SyncableFileOperationRunner> operation_runner_; 307 308 // Keeps track of writing/syncing status. 309 // This must be accessed only on IO thread. 310 scoped_ptr<LocalFileSyncStatus> sync_status_; 311 312 // Pointers to file system contexts that have been initialized for 313 // synchronization (i.e. that own this instance). 314 // This must be accessed only on UI thread. 315 std::set<fileapi::FileSystemContext*> file_system_contexts_; 316 317 // Accessed only on UI thread. 318 std::map<fileapi::FileSystemContext*, StatusCallbackQueue> 319 pending_initialize_callbacks_; 320 321 // A URL and associated callback waiting for sync is enabled. 322 // Accessed only on IO thread. 323 fileapi::FileSystemURL url_waiting_sync_on_io_; 324 base::Closure url_syncable_callback_; 325 326 // Used only on IO thread for available changes notifications. 327 base::Time last_notified_changes_; 328 scoped_ptr<base::OneShotTimer<LocalFileSyncContext> > timer_on_io_; 329 std::set<GURL> origins_with_pending_changes_; 330 331 ObserverList<LocalOriginChangeObserver> origin_change_observers_; 332 333 int mock_notify_changes_duration_in_sec_; 334 335 DISALLOW_COPY_AND_ASSIGN(LocalFileSyncContext); 336}; 337 338} // namespace sync_file_system 339 340#endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_LOCAL_LOCAL_FILE_SYNC_CONTEXT_H_ 341