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