Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: webkit/fileapi/syncable/local_file_sync_context.cc

Issue 15806012: Move webkit/fileapi/syncable/* code to webkit/browser/fileapi (final!) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "webkit/fileapi/syncable/local_file_sync_context.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/platform_file.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/task_runner_util.h"
13 #include "webkit/browser/fileapi/file_system_context.h"
14 #include "webkit/browser/fileapi/file_system_file_util.h"
15 #include "webkit/browser/fileapi/file_system_operation_context.h"
16 #include "webkit/browser/fileapi/file_system_task_runners.h"
17 #include "webkit/browser/fileapi/local_file_system_operation.h"
18 #include "webkit/common/fileapi/file_system_util.h"
19 #include "webkit/fileapi/syncable/file_change.h"
20 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
21 #include "webkit/fileapi/syncable/local_origin_change_observer.h"
22 #include "webkit/fileapi/syncable/sync_file_metadata.h"
23 #include "webkit/fileapi/syncable/syncable_file_operation_runner.h"
24 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
25
26 using fileapi::FileSystemContext;
27 using fileapi::FileSystemFileUtil;
28 using fileapi::FileSystemOperation;
29 using fileapi::FileSystemOperationContext;
30 using fileapi::FileSystemURL;
31 using fileapi::LocalFileSystemOperation;
32
33 namespace sync_file_system {
34
35 namespace {
36 const int kMaxConcurrentSyncableOperation = 3;
37 const int kNotifyChangesDurationInSec = 1;
38 const int kMaxURLsToFetchForLocalSync = 5;
39 } // namespace
40
41 LocalFileSyncContext::LocalFileSyncContext(
42 base::SingleThreadTaskRunner* ui_task_runner,
43 base::SingleThreadTaskRunner* io_task_runner)
44 : ui_task_runner_(ui_task_runner),
45 io_task_runner_(io_task_runner),
46 shutdown_on_ui_(false),
47 mock_notify_changes_duration_in_sec_(-1) {
48 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
49 }
50
51 void LocalFileSyncContext::MaybeInitializeFileSystemContext(
52 const GURL& source_url,
53 const std::string& service_name,
54 FileSystemContext* file_system_context,
55 const SyncStatusCallback& callback) {
56 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
57 if (ContainsKey(file_system_contexts_, file_system_context)) {
58 // The context has been already initialized. Just dispatch the callback
59 // with SYNC_STATUS_OK.
60 ui_task_runner_->PostTask(FROM_HERE,
61 base::Bind(callback,
62 SYNC_STATUS_OK));
63 return;
64 }
65
66 StatusCallbackQueue& callback_queue =
67 pending_initialize_callbacks_[file_system_context];
68 callback_queue.push_back(callback);
69 if (callback_queue.size() > 1)
70 return;
71
72 io_task_runner_->PostTask(
73 FROM_HERE,
74 base::Bind(&LocalFileSyncContext::InitializeFileSystemContextOnIOThread,
75 this, source_url, service_name,
76 make_scoped_refptr(file_system_context)));
77 }
78
79 void LocalFileSyncContext::ShutdownOnUIThread() {
80 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
81 shutdown_on_ui_ = true;
82 io_task_runner_->PostTask(
83 FROM_HERE,
84 base::Bind(&LocalFileSyncContext::ShutdownOnIOThread,
85 this));
86 }
87
88 void LocalFileSyncContext::GetFileForLocalSync(
89 FileSystemContext* file_system_context,
90 const LocalFileSyncInfoCallback& callback) {
91 DCHECK(file_system_context);
92 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
93
94 std::deque<FileSystemURL>* urls = new std::deque<FileSystemURL>;
95 file_system_context->task_runners()->file_task_runner()->PostTaskAndReply(
96 FROM_HERE,
97 base::Bind(&LocalFileSyncContext::GetNextURLsForSyncOnFileThread,
98 this, make_scoped_refptr(file_system_context),
99 base::Unretained(urls)),
100 base::Bind(&LocalFileSyncContext::TryPrepareForLocalSync,
101 this, make_scoped_refptr(file_system_context),
102 base::Owned(urls), callback));
103 }
104
105 void LocalFileSyncContext::ClearChangesForURL(
106 FileSystemContext* file_system_context,
107 const FileSystemURL& url,
108 const base::Closure& done_callback) {
109 // This is initially called on UI thread and to be relayed to FILE thread.
110 DCHECK(file_system_context);
111 if (!file_system_context->task_runners()->file_task_runner()->
112 RunsTasksOnCurrentThread()) {
113 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
114 file_system_context->task_runners()->file_task_runner()->PostTask(
115 FROM_HERE,
116 base::Bind(&LocalFileSyncContext::ClearChangesForURL,
117 this, make_scoped_refptr(file_system_context),
118 url, done_callback));
119 return;
120 }
121 DCHECK(file_system_context->change_tracker());
122 file_system_context->change_tracker()->ClearChangesForURL(url);
123
124 // Call the completion callback on UI thread.
125 ui_task_runner_->PostTask(FROM_HERE, done_callback);
126 }
127
128 void LocalFileSyncContext::ClearSyncFlagForURL(const FileSystemURL& url) {
129 // This is initially called on UI thread and to be relayed to IO thread.
130 io_task_runner_->PostTask(
131 FROM_HERE,
132 base::Bind(&LocalFileSyncContext::EnableWritingOnIOThread,
133 this, url));
134 }
135
136 void LocalFileSyncContext::PrepareForSync(
137 FileSystemContext* file_system_context,
138 const FileSystemURL& url,
139 const LocalFileSyncInfoCallback& callback) {
140 // This is initially called on UI thread and to be relayed to IO thread.
141 if (!io_task_runner_->RunsTasksOnCurrentThread()) {
142 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
143 io_task_runner_->PostTask(
144 FROM_HERE,
145 base::Bind(&LocalFileSyncContext::PrepareForSync, this,
146 make_scoped_refptr(file_system_context), url, callback));
147 return;
148 }
149 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
150 const bool syncable = sync_status()->IsSyncable(url);
151 // Disable writing if it's ready to be synced.
152 if (syncable)
153 sync_status()->StartSyncing(url);
154 ui_task_runner_->PostTask(
155 FROM_HERE,
156 base::Bind(&LocalFileSyncContext::DidGetWritingStatusForSync,
157 this, make_scoped_refptr(file_system_context),
158 syncable ? SYNC_STATUS_OK :
159 SYNC_STATUS_FILE_BUSY,
160 url, callback));
161 }
162
163 void LocalFileSyncContext::RegisterURLForWaitingSync(
164 const FileSystemURL& url,
165 const base::Closure& on_syncable_callback) {
166 // This is initially called on UI thread and to be relayed to IO thread.
167 if (!io_task_runner_->RunsTasksOnCurrentThread()) {
168 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
169 io_task_runner_->PostTask(
170 FROM_HERE,
171 base::Bind(&LocalFileSyncContext::RegisterURLForWaitingSync,
172 this, url, on_syncable_callback));
173 return;
174 }
175 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
176 if (sync_status()->IsSyncable(url)) {
177 // No need to register; fire the callback now.
178 ui_task_runner_->PostTask(FROM_HERE, on_syncable_callback);
179 return;
180 }
181 url_waiting_sync_on_io_ = url;
182 url_syncable_callback_ = on_syncable_callback;
183 }
184
185 void LocalFileSyncContext::ApplyRemoteChange(
186 FileSystemContext* file_system_context,
187 const FileChange& change,
188 const base::FilePath& local_path,
189 const FileSystemURL& url,
190 const SyncStatusCallback& callback) {
191 if (!io_task_runner_->RunsTasksOnCurrentThread()) {
192 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
193 io_task_runner_->PostTask(
194 FROM_HERE,
195 base::Bind(&LocalFileSyncContext::ApplyRemoteChange, this,
196 make_scoped_refptr(file_system_context),
197 change, local_path, url, callback));
198 return;
199 }
200 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
201 DCHECK(!sync_status()->IsWritable(url));
202 DCHECK(!sync_status()->IsWriting(url));
203 LocalFileSystemOperation* operation = CreateFileSystemOperationForSync(
204 file_system_context);
205 DCHECK(operation);
206
207 FileSystemOperation::StatusCallback operation_callback;
208 if (change.change() == FileChange::FILE_CHANGE_ADD_OR_UPDATE) {
209 operation_callback = base::Bind(
210 &LocalFileSyncContext::DidRemoveExistingEntryForApplyRemoteChange,
211 this,
212 make_scoped_refptr(file_system_context),
213 change,
214 local_path,
215 url,
216 callback);
217 } else {
218 DCHECK_EQ(FileChange::FILE_CHANGE_DELETE, change.change());
219 operation_callback = base::Bind(
220 &LocalFileSyncContext::DidApplyRemoteChange, this, url, callback);
221 }
222 operation->Remove(url, true /* recursive */, operation_callback);
223 }
224
225 void LocalFileSyncContext::DidRemoveExistingEntryForApplyRemoteChange(
226 FileSystemContext* file_system_context,
227 const FileChange& change,
228 const base::FilePath& local_path,
229 const FileSystemURL& url,
230 const SyncStatusCallback& callback,
231 base::PlatformFileError error) {
232 // Remove() may fail if the target entry does not exist (which is ok),
233 // so we ignore |error| here.
234
235 if (!sync_status()) {
236 callback.Run(SYNC_FILE_ERROR_ABORT);
237 return;
238 }
239
240 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
241 DCHECK(!sync_status()->IsWritable(url));
242 DCHECK(!sync_status()->IsWriting(url));
243 LocalFileSystemOperation* operation =
244 CreateFileSystemOperationForSync(file_system_context);
245 DCHECK(operation);
246 FileSystemOperation::StatusCallback operation_callback = base::Bind(
247 &LocalFileSyncContext::DidApplyRemoteChange, this, url, callback);
248
249 DCHECK_EQ(FileChange::FILE_CHANGE_ADD_OR_UPDATE, change.change());
250 switch (change.file_type()) {
251 case SYNC_FILE_TYPE_FILE: {
252 DCHECK(!local_path.empty());
253 base::FilePath dir_path = fileapi::VirtualPath::DirName(url.path());
254 if (dir_path.empty() ||
255 fileapi::VirtualPath::DirName(dir_path) == dir_path) {
256 // Copying into the root directory.
257 operation->CopyInForeignFile(local_path, url, operation_callback);
258 } else {
259 FileSystemURL dir_url = file_system_context->CreateCrackedFileSystemURL(
260 url.origin(),
261 url.mount_type(),
262 fileapi::VirtualPath::DirName(url.virtual_path()));
263 operation->CreateDirectory(
264 dir_url,
265 false /* exclusive */,
266 true /* recursive */,
267 base::Bind(&LocalFileSyncContext::DidCreateDirectoryForCopyIn,
268 this,
269 make_scoped_refptr(file_system_context),
270 local_path,
271 url,
272 operation_callback));
273 }
274 break;
275 }
276 case SYNC_FILE_TYPE_DIRECTORY:
277 operation->CreateDirectory(
278 url, false /* exclusive */, true /* recursive */, operation_callback);
279 break;
280 case SYNC_FILE_TYPE_UNKNOWN:
281 NOTREACHED() << "File type unknown for ADD_OR_UPDATE change";
282 }
283 }
284
285 void LocalFileSyncContext::RecordFakeLocalChange(
286 FileSystemContext* file_system_context,
287 const FileSystemURL& url,
288 const FileChange& change,
289 const SyncStatusCallback& callback) {
290 // This is called on UI thread and to be relayed to FILE thread.
291 DCHECK(file_system_context);
292 if (!file_system_context->task_runners()->file_task_runner()->
293 RunsTasksOnCurrentThread()) {
294 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
295 file_system_context->task_runners()->file_task_runner()->PostTask(
296 FROM_HERE,
297 base::Bind(&LocalFileSyncContext::RecordFakeLocalChange,
298 this, make_scoped_refptr(file_system_context),
299 url, change, callback));
300 return;
301 }
302
303 DCHECK(file_system_context->change_tracker());
304 file_system_context->change_tracker()->MarkDirtyOnDatabase(url);
305 file_system_context->change_tracker()->RecordChange(url, change);
306
307 // Fire the callback on UI thread.
308 ui_task_runner_->PostTask(FROM_HERE,
309 base::Bind(callback,
310 SYNC_STATUS_OK));
311 }
312
313 void LocalFileSyncContext::GetFileMetadata(
314 FileSystemContext* file_system_context,
315 const FileSystemURL& url,
316 const SyncFileMetadataCallback& callback) {
317 // This is initially called on UI thread and to be relayed to IO thread.
318 if (!io_task_runner_->RunsTasksOnCurrentThread()) {
319 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
320 io_task_runner_->PostTask(
321 FROM_HERE,
322 base::Bind(&LocalFileSyncContext::GetFileMetadata, this,
323 make_scoped_refptr(file_system_context), url, callback));
324 return;
325 }
326 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
327 LocalFileSystemOperation* operation = CreateFileSystemOperationForSync(
328 file_system_context);
329 DCHECK(operation);
330 operation->GetMetadata(
331 url, base::Bind(&LocalFileSyncContext::DidGetFileMetadata,
332 this, callback));
333 }
334
335 void LocalFileSyncContext::HasPendingLocalChanges(
336 FileSystemContext* file_system_context,
337 const FileSystemURL& url,
338 const HasPendingLocalChangeCallback& callback) {
339 // This gets called on UI thread and relays the task on FILE thread.
340 DCHECK(file_system_context);
341 if (!file_system_context->task_runners()->file_task_runner()->
342 RunsTasksOnCurrentThread()) {
343 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
344 file_system_context->task_runners()->file_task_runner()->PostTask(
345 FROM_HERE,
346 base::Bind(&LocalFileSyncContext::HasPendingLocalChanges,
347 this, make_scoped_refptr(file_system_context),
348 url, callback));
349 return;
350 }
351
352 DCHECK(file_system_context->change_tracker());
353 FileChangeList changes;
354 file_system_context->change_tracker()->GetChangesForURL(url, &changes);
355
356 // Fire the callback on UI thread.
357 ui_task_runner_->PostTask(FROM_HERE,
358 base::Bind(callback,
359 SYNC_STATUS_OK,
360 !changes.empty()));
361 }
362
363 void LocalFileSyncContext::AddOriginChangeObserver(
364 LocalOriginChangeObserver* observer) {
365 origin_change_observers_.AddObserver(observer);
366 }
367
368 void LocalFileSyncContext::RemoveOriginChangeObserver(
369 LocalOriginChangeObserver* observer) {
370 origin_change_observers_.RemoveObserver(observer);
371 }
372
373 base::WeakPtr<SyncableFileOperationRunner>
374 LocalFileSyncContext::operation_runner() const {
375 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
376 if (operation_runner_)
377 return operation_runner_->AsWeakPtr();
378 return base::WeakPtr<SyncableFileOperationRunner>();
379 }
380
381 LocalFileSyncStatus* LocalFileSyncContext::sync_status() const {
382 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
383 return sync_status_.get();
384 }
385
386 void LocalFileSyncContext::OnSyncEnabled(const FileSystemURL& url) {
387 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
388 origins_with_pending_changes_.insert(url.origin());
389 ScheduleNotifyChangesUpdatedOnIOThread();
390 if (url_syncable_callback_.is_null() ||
391 sync_status()->IsWriting(url_waiting_sync_on_io_)) {
392 return;
393 }
394 // TODO(kinuko): may want to check how many pending tasks we have.
395 ui_task_runner_->PostTask(FROM_HERE, url_syncable_callback_);
396 url_syncable_callback_.Reset();
397 }
398
399 void LocalFileSyncContext::OnWriteEnabled(const FileSystemURL& url) {
400 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
401 // Nothing to do for now.
402 }
403
404 LocalFileSyncContext::~LocalFileSyncContext() {
405 }
406
407 void LocalFileSyncContext::ScheduleNotifyChangesUpdatedOnIOThread() {
408 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
409 if (base::Time::Now() > last_notified_changes_ + NotifyChangesDuration()) {
410 NotifyAvailableChangesOnIOThread();
411 } else if (!timer_on_io_->IsRunning()) {
412 timer_on_io_->Start(
413 FROM_HERE, NotifyChangesDuration(), this,
414 &LocalFileSyncContext::NotifyAvailableChangesOnIOThread);
415 }
416 }
417
418 void LocalFileSyncContext::NotifyAvailableChangesOnIOThread() {
419 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
420 ui_task_runner_->PostTask(
421 FROM_HERE,
422 base::Bind(&LocalFileSyncContext::NotifyAvailableChanges,
423 this, origins_with_pending_changes_));
424 last_notified_changes_ = base::Time::Now();
425 origins_with_pending_changes_.clear();
426 }
427
428 void LocalFileSyncContext::NotifyAvailableChanges(
429 const std::set<GURL>& origins) {
430 FOR_EACH_OBSERVER(LocalOriginChangeObserver, origin_change_observers_,
431 OnChangesAvailableInOrigins(origins));
432 }
433
434 void LocalFileSyncContext::ShutdownOnIOThread() {
435 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
436 operation_runner_.reset();
437 sync_status_.reset();
438 timer_on_io_.reset();
439 }
440
441 void LocalFileSyncContext::InitializeFileSystemContextOnIOThread(
442 const GURL& source_url,
443 const std::string& service_name,
444 FileSystemContext* file_system_context) {
445 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
446 DCHECK(file_system_context);
447 if (!file_system_context->change_tracker()) {
448 // First registers the service name.
449 RegisterSyncableFileSystem(service_name);
450 // Create and initialize LocalFileChangeTracker and call back this method
451 // later again.
452 std::set<GURL>* origins_with_changes = new std::set<GURL>;
453 scoped_ptr<LocalFileChangeTracker>* tracker_ptr(
454 new scoped_ptr<LocalFileChangeTracker>);
455 base::PostTaskAndReplyWithResult(
456 file_system_context->task_runners()->file_task_runner(),
457 FROM_HERE,
458 base::Bind(&LocalFileSyncContext::InitializeChangeTrackerOnFileThread,
459 this, tracker_ptr,
460 make_scoped_refptr(file_system_context),
461 origins_with_changes),
462 base::Bind(&LocalFileSyncContext::DidInitializeChangeTrackerOnIOThread,
463 this, base::Owned(tracker_ptr),
464 source_url, service_name,
465 make_scoped_refptr(file_system_context),
466 base::Owned(origins_with_changes)));
467 return;
468 }
469 if (!operation_runner_) {
470 DCHECK(!sync_status_);
471 DCHECK(!timer_on_io_);
472 sync_status_.reset(new LocalFileSyncStatus);
473 timer_on_io_.reset(new base::OneShotTimer<LocalFileSyncContext>);
474 operation_runner_.reset(new SyncableFileOperationRunner(
475 kMaxConcurrentSyncableOperation,
476 sync_status_.get()));
477 sync_status_->AddObserver(this);
478 }
479 file_system_context->set_sync_context(this);
480 DidInitialize(source_url, file_system_context,
481 SYNC_STATUS_OK);
482 }
483
484 SyncStatusCode LocalFileSyncContext::InitializeChangeTrackerOnFileThread(
485 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
486 FileSystemContext* file_system_context,
487 std::set<GURL>* origins_with_changes) {
488 DCHECK(file_system_context);
489 DCHECK(tracker_ptr);
490 DCHECK(origins_with_changes);
491 tracker_ptr->reset(new LocalFileChangeTracker(
492 file_system_context->partition_path(),
493 file_system_context->task_runners()->file_task_runner()));
494 const SyncStatusCode status = (*tracker_ptr)->Initialize(file_system_context);
495 if (status != SYNC_STATUS_OK)
496 return status;
497
498 // Get all origins that have pending changes.
499 std::deque<FileSystemURL> urls;
500 (*tracker_ptr)->GetNextChangedURLs(&urls, 0);
501 for (std::deque<FileSystemURL>::iterator iter = urls.begin();
502 iter != urls.end(); ++iter) {
503 origins_with_changes->insert(iter->origin());
504 }
505 return status;
506 }
507
508 void LocalFileSyncContext::DidInitializeChangeTrackerOnIOThread(
509 scoped_ptr<LocalFileChangeTracker>* tracker_ptr,
510 const GURL& source_url,
511 const std::string& service_name,
512 FileSystemContext* file_system_context,
513 std::set<GURL>* origins_with_changes,
514 SyncStatusCode status) {
515 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
516 DCHECK(file_system_context);
517 DCHECK(origins_with_changes);
518 if (status != SYNC_STATUS_OK) {
519 DidInitialize(source_url, file_system_context, status);
520 return;
521 }
522 file_system_context->SetLocalFileChangeTracker(tracker_ptr->Pass());
523
524 origins_with_pending_changes_.insert(origins_with_changes->begin(),
525 origins_with_changes->end());
526 ScheduleNotifyChangesUpdatedOnIOThread();
527
528 InitializeFileSystemContextOnIOThread(source_url, service_name,
529 file_system_context);
530 }
531
532 void LocalFileSyncContext::DidInitialize(
533 const GURL& source_url,
534 FileSystemContext* file_system_context,
535 SyncStatusCode status) {
536 if (!ui_task_runner_->RunsTasksOnCurrentThread()) {
537 ui_task_runner_->PostTask(
538 FROM_HERE,
539 base::Bind(&LocalFileSyncContext::DidInitialize,
540 this, source_url,
541 make_scoped_refptr(file_system_context), status));
542 return;
543 }
544 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
545 DCHECK(!ContainsKey(file_system_contexts_, file_system_context));
546 DCHECK(ContainsKey(pending_initialize_callbacks_, file_system_context));
547 DCHECK(file_system_context->change_tracker());
548
549 file_system_contexts_.insert(file_system_context);
550
551 StatusCallbackQueue& callback_queue =
552 pending_initialize_callbacks_[file_system_context];
553 for (StatusCallbackQueue::iterator iter = callback_queue.begin();
554 iter != callback_queue.end(); ++iter) {
555 ui_task_runner_->PostTask(FROM_HERE, base::Bind(*iter, status));
556 }
557 pending_initialize_callbacks_.erase(file_system_context);
558 }
559
560 void LocalFileSyncContext::GetNextURLsForSyncOnFileThread(
561 FileSystemContext* file_system_context,
562 std::deque<FileSystemURL>* urls) {
563 DCHECK(file_system_context);
564 DCHECK(file_system_context->task_runners()->file_task_runner()->
565 RunsTasksOnCurrentThread());
566 DCHECK(file_system_context->change_tracker());
567 file_system_context->change_tracker()->GetNextChangedURLs(
568 urls, kMaxURLsToFetchForLocalSync);
569 }
570
571 void LocalFileSyncContext::TryPrepareForLocalSync(
572 FileSystemContext* file_system_context,
573 std::deque<FileSystemURL>* urls,
574 const LocalFileSyncInfoCallback& callback) {
575 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
576 DCHECK(urls);
577
578 if (shutdown_on_ui_) {
579 callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo());
580 return;
581 }
582
583 if (urls->empty()) {
584 callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC,
585 LocalFileSyncInfo());
586 return;
587 }
588
589 const FileSystemURL url = urls->front();
590 urls->pop_front();
591 std::deque<FileSystemURL>* remaining = new std::deque<FileSystemURL>;
592 remaining->swap(*urls);
593
594 PrepareForSync(
595 file_system_context, url,
596 base::Bind(&LocalFileSyncContext::DidTryPrepareForLocalSync,
597 this, make_scoped_refptr(file_system_context),
598 base::Owned(remaining), callback));
599 }
600
601 void LocalFileSyncContext::DidTryPrepareForLocalSync(
602 FileSystemContext* file_system_context,
603 std::deque<FileSystemURL>* remaining_urls,
604 const LocalFileSyncInfoCallback& callback,
605 SyncStatusCode status,
606 const LocalFileSyncInfo& sync_file_info) {
607 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
608 if (status != SYNC_STATUS_FILE_BUSY) {
609 callback.Run(status, sync_file_info);
610 return;
611 }
612 // Recursively call TryPrepareForLocalSync with remaining_urls.
613 TryPrepareForLocalSync(file_system_context, remaining_urls, callback);
614 }
615
616 void LocalFileSyncContext::DidGetWritingStatusForSync(
617 FileSystemContext* file_system_context,
618 SyncStatusCode status,
619 const FileSystemURL& url,
620 const LocalFileSyncInfoCallback& callback) {
621 // This gets called on UI thread and relays the task on FILE thread.
622 DCHECK(file_system_context);
623 if (!file_system_context->task_runners()->file_task_runner()->
624 RunsTasksOnCurrentThread()) {
625 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
626 if (shutdown_on_ui_) {
627 callback.Run(SYNC_STATUS_ABORT, LocalFileSyncInfo());
628 return;
629 }
630 file_system_context->task_runners()->file_task_runner()->PostTask(
631 FROM_HERE,
632 base::Bind(&LocalFileSyncContext::DidGetWritingStatusForSync,
633 this, make_scoped_refptr(file_system_context),
634 status, url, callback));
635 return;
636 }
637
638 DCHECK(file_system_context->change_tracker());
639 FileChangeList changes;
640 file_system_context->change_tracker()->GetChangesForURL(url, &changes);
641
642 base::FilePath platform_path;
643 base::PlatformFileInfo file_info;
644 FileSystemFileUtil* file_util = file_system_context->GetFileUtil(url.type());
645 DCHECK(file_util);
646 base::PlatformFileError file_error = file_util->GetFileInfo(
647 make_scoped_ptr(
648 new FileSystemOperationContext(file_system_context)).get(),
649 url,
650 &file_info,
651 &platform_path);
652 if (status == SYNC_STATUS_OK &&
653 file_error != base::PLATFORM_FILE_OK &&
654 file_error != base::PLATFORM_FILE_ERROR_NOT_FOUND)
655 status = PlatformFileErrorToSyncStatusCode(file_error);
656
657 DCHECK(!file_info.is_symbolic_link);
658
659 SyncFileType file_type = SYNC_FILE_TYPE_FILE;
660 if (file_error == base::PLATFORM_FILE_ERROR_NOT_FOUND)
661 file_type = SYNC_FILE_TYPE_UNKNOWN;
662 else if (file_info.is_directory)
663 file_type = SYNC_FILE_TYPE_DIRECTORY;
664
665 LocalFileSyncInfo sync_file_info;
666 sync_file_info.url = url;
667 sync_file_info.local_file_path = platform_path;
668 sync_file_info.metadata.file_type = file_type;
669 sync_file_info.metadata.size = file_info.size;
670 sync_file_info.metadata.last_modified = file_info.last_modified;
671 sync_file_info.changes = changes;
672
673 ui_task_runner_->PostTask(FROM_HERE,
674 base::Bind(callback, status, sync_file_info));
675 }
676
677 void LocalFileSyncContext::EnableWritingOnIOThread(
678 const FileSystemURL& url) {
679 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
680 if (!sync_status()) {
681 // The service might have been shut down.
682 return;
683 }
684 sync_status()->EndSyncing(url);
685 // Since a sync has finished the number of changes must have been updated.
686 origins_with_pending_changes_.insert(url.origin());
687 ScheduleNotifyChangesUpdatedOnIOThread();
688 }
689
690 void LocalFileSyncContext::DidApplyRemoteChange(
691 const FileSystemURL& url,
692 const SyncStatusCallback& callback_on_ui,
693 base::PlatformFileError file_error) {
694 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
695 ui_task_runner_->PostTask(
696 FROM_HERE,
697 base::Bind(callback_on_ui,
698 PlatformFileErrorToSyncStatusCode(file_error)));
699 EnableWritingOnIOThread(url);
700 }
701
702 void LocalFileSyncContext::DidGetFileMetadata(
703 const SyncFileMetadataCallback& callback,
704 base::PlatformFileError file_error,
705 const base::PlatformFileInfo& file_info,
706 const base::FilePath& platform_path) {
707 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
708 SyncFileMetadata metadata;
709 if (file_error == base::PLATFORM_FILE_OK) {
710 metadata.file_type = file_info.is_directory ?
711 SYNC_FILE_TYPE_DIRECTORY : SYNC_FILE_TYPE_FILE;
712 metadata.size = file_info.size;
713 metadata.last_modified = file_info.last_modified;
714 }
715 ui_task_runner_->PostTask(
716 FROM_HERE,
717 base::Bind(callback,
718 PlatformFileErrorToSyncStatusCode(file_error),
719 metadata));
720 }
721
722 base::TimeDelta LocalFileSyncContext::NotifyChangesDuration() {
723 if (mock_notify_changes_duration_in_sec_ >= 0)
724 return base::TimeDelta::FromSeconds(mock_notify_changes_duration_in_sec_);
725 return base::TimeDelta::FromSeconds(kNotifyChangesDurationInSec);
726 }
727
728 void LocalFileSyncContext::DidCreateDirectoryForCopyIn(
729 FileSystemContext* file_system_context,
730 const base::FilePath& local_path,
731 const FileSystemURL& dest_url,
732 const StatusCallback& callback,
733 base::PlatformFileError error) {
734 if (error != base::PLATFORM_FILE_OK) {
735 callback.Run(error);
736 return;
737 }
738
739 LocalFileSystemOperation* operation = CreateFileSystemOperationForSync(
740 file_system_context);
741 DCHECK(operation);
742 operation->CopyInForeignFile(local_path, dest_url, callback);
743 }
744
745 } // namespace sync_file_system
OLDNEW
« no previous file with comments | « webkit/fileapi/syncable/local_file_sync_context.h ('k') | webkit/fileapi/syncable/local_file_sync_context_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698