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