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