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

Side by Side Diff: chrome/browser/chromeos/file_system_provider/provided_file_system.cc

Issue 642023003: [fsp] Allow to create multiple observers for a directory, up to one per origin. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed comments + fixed tests. Created 6 years, 1 month 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h" 5 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/files/file.h" 10 #include "base/files/file.h"
(...skipping 24 matching lines...) Expand all
35 } // namespace net 35 } // namespace net
36 36
37 namespace chromeos { 37 namespace chromeos {
38 namespace file_system_provider { 38 namespace file_system_provider {
39 namespace { 39 namespace {
40 40
41 // Discards the result of Abort() when called from the destructor. 41 // Discards the result of Abort() when called from the destructor.
42 void EmptyStatusCallback(base::File::Error /* result */) { 42 void EmptyStatusCallback(base::File::Error /* result */) {
43 } 43 }
44 44
45 // Discards the error code and always calls the callback with a success.
46 void AlwaysSuccessCallback(
47 const storage::AsyncFileUtil::StatusCallback& callback,
48 base::File::Error /* result */) {
49 callback.Run(base::File::FILE_OK);
50 }
51
45 } // namespace 52 } // namespace
46 53
47 AutoUpdater::AutoUpdater(const base::Closure& update_callback) 54 AutoUpdater::AutoUpdater(const base::Closure& update_callback)
48 : update_callback_(update_callback), 55 : update_callback_(update_callback),
49 created_callbacks_(0), 56 created_callbacks_(0),
50 pending_callbacks_(0) { 57 pending_callbacks_(0) {
51 } 58 }
52 59
53 base::Closure AutoUpdater::CreateCallback() { 60 base::Closure AutoUpdater::CreateCallback() {
54 ++created_callbacks_; 61 ++created_callbacks_;
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 if (!request_id) { 358 if (!request_id) {
352 callback.Run(base::File::FILE_ERROR_SECURITY); 359 callback.Run(base::File::FILE_ERROR_SECURITY);
353 return AbortCallback(); 360 return AbortCallback();
354 } 361 }
355 362
356 return base::Bind( 363 return base::Bind(
357 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 364 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
358 } 365 }
359 366
360 ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory( 367 ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory(
368 const GURL& origin,
361 const base::FilePath& directory_path, 369 const base::FilePath& directory_path,
362 bool recursive, 370 bool recursive,
371 bool persistent,
363 const storage::AsyncFileUtil::StatusCallback& callback) { 372 const storage::AsyncFileUtil::StatusCallback& callback) {
364 // TODO(mtomasz): Wrap the entire method body with an asynchronous queue to 373 // TODO(mtomasz): Wrap the entire method body with an asynchronous queue to
365 // avoid races. 374 // avoid races.
375 if (persistent && !file_system_info_.supports_notify_tag()) {
376 OnObserveDirectoryCompleted(origin,
377 directory_path,
378 recursive,
379 persistent,
380 callback,
381 base::File::FILE_ERROR_INVALID_OPERATION);
382 return AbortCallback();
383 }
384
366 const ObservedEntryKey key(directory_path, recursive); 385 const ObservedEntryKey key(directory_path, recursive);
367 const ObservedEntries::const_iterator it = observed_entries_.find(key); 386 const ObservedEntries::const_iterator it = observed_entries_.find(key);
368 if (it != observed_entries_.end()) { 387 if (it != observed_entries_.end()) {
388 const bool exists =
389 it->second.subscribers.find(origin) != it->second.subscribers.end();
369 OnObserveDirectoryCompleted( 390 OnObserveDirectoryCompleted(
370 directory_path, recursive, callback, base::File::FILE_ERROR_EXISTS); 391 origin,
392 directory_path,
393 recursive,
394 persistent,
395 callback,
396 exists ? base::File::FILE_ERROR_EXISTS : base::File::FILE_OK);
371 return AbortCallback(); 397 return AbortCallback();
372 } 398 }
373 399
374 const int request_id = request_manager_->CreateRequest( 400 const int request_id = request_manager_->CreateRequest(
375 OBSERVE_DIRECTORY, 401 OBSERVE_DIRECTORY,
376 scoped_ptr<RequestManager::HandlerInterface>( 402 scoped_ptr<RequestManager::HandlerInterface>(
377 new operations::ObserveDirectory( 403 new operations::ObserveDirectory(
378 event_router_, 404 event_router_,
379 file_system_info_, 405 file_system_info_,
380 directory_path, 406 directory_path,
381 recursive, 407 recursive,
382 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted, 408 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted,
383 weak_ptr_factory_.GetWeakPtr(), 409 weak_ptr_factory_.GetWeakPtr(),
410 origin,
384 directory_path, 411 directory_path,
385 recursive, 412 recursive,
413 persistent,
386 callback)))); 414 callback))));
415
387 if (!request_id) { 416 if (!request_id) {
388 callback.Run(base::File::FILE_ERROR_SECURITY); 417 OnObserveDirectoryCompleted(origin,
418 directory_path,
419 recursive,
420 persistent,
421 callback,
422 base::File::FILE_ERROR_SECURITY);
389 return AbortCallback(); 423 return AbortCallback();
390 } 424 }
391 425
392 return base::Bind( 426 return base::Bind(
393 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 427 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
394 } 428 }
395 429
396 void ProvidedFileSystem::UnobserveEntry( 430 void ProvidedFileSystem::UnobserveEntry(
431 const GURL& origin,
397 const base::FilePath& entry_path, 432 const base::FilePath& entry_path,
398 bool recursive, 433 bool recursive,
399 const storage::AsyncFileUtil::StatusCallback& callback) { 434 const storage::AsyncFileUtil::StatusCallback& callback) {
400 const ObservedEntryKey key(entry_path, recursive); 435 const ObservedEntryKey key(entry_path, recursive);
401 const ObservedEntries::const_iterator it = observed_entries_.find(key); 436 const ObservedEntries::iterator it = observed_entries_.find(key);
402 if (it == observed_entries_.end()) { 437 if (it == observed_entries_.end() ||
438 it->second.subscribers.find(origin) == it->second.subscribers.end()) {
403 callback.Run(base::File::FILE_ERROR_NOT_FOUND); 439 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
404 return; 440 return;
405 } 441 }
406 442
407 // Delete the watcher in advance since the list of observed entries is owned 443 // Delete the subscriber in advance, since the list of observed entries is
408 // by the C++ layer, not by the extension. 444 // owned by the C++ layer, not by the extension.
409 observed_entries_.erase(it); 445 it->second.subscribers.erase(origin);
410 446
411 FOR_EACH_OBSERVER( 447 FOR_EACH_OBSERVER(
412 ProvidedFileSystemObserver, 448 ProvidedFileSystemObserver,
413 observers_, 449 observers_,
414 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 450 OnObservedEntryListChanged(file_system_info_, observed_entries_));
415 451
416 // TODO(mtomasz): Consider returning always an OK error code, since for the 452 // If there are other subscribers, then do not remove the obsererver, but
417 // callers it's important that the entry is not watched anymore. The watcher 453 // simply return a success.
418 // is removed even if the extension returns an error. 454 if (it->second.subscribers.size()) {
455 callback.Run(base::File::FILE_OK);
456 return;
457 }
458
459 // Delete the watcher in advance.
460 observed_entries_.erase(it);
461
462 // Even if the extension returns an error, the callback is called with base::
463 // File::FILE_OK. The reason for that is that the observed is not watched
464 // anymore anyway, as it's removed in advance.
419 const int request_id = request_manager_->CreateRequest( 465 const int request_id = request_manager_->CreateRequest(
420 UNOBSERVE_ENTRY, 466 UNOBSERVE_ENTRY,
421 scoped_ptr<RequestManager::HandlerInterface>( 467 scoped_ptr<RequestManager::HandlerInterface>(
422 new operations::UnobserveEntry(event_router_, 468 new operations::UnobserveEntry(
423 file_system_info_, 469 event_router_,
424 entry_path, 470 file_system_info_,
425 recursive, 471 entry_path,
426 callback))); 472 recursive,
473 base::Bind(&AlwaysSuccessCallback, callback))));
427 if (!request_id) 474 if (!request_id)
428 callback.Run(base::File::FILE_ERROR_SECURITY); 475 callback.Run(base::File::FILE_OK);
429 } 476 }
430 477
431 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const { 478 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
432 return file_system_info_; 479 return file_system_info_;
433 } 480 }
434 481
435 RequestManager* ProvidedFileSystem::GetRequestManager() { 482 RequestManager* ProvidedFileSystem::GetRequestManager() {
436 return request_manager_.get(); 483 return request_manager_.get();
437 } 484 }
438 485
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 scoped_ptr<RequestManager::HandlerInterface>( 552 scoped_ptr<RequestManager::HandlerInterface>(
506 new operations::Abort(event_router_, 553 new operations::Abort(event_router_,
507 file_system_info_, 554 file_system_info_,
508 operation_request_id, 555 operation_request_id,
509 callback)))) { 556 callback)))) {
510 callback.Run(base::File::FILE_ERROR_SECURITY); 557 callback.Run(base::File::FILE_ERROR_SECURITY);
511 } 558 }
512 } 559 }
513 560
514 void ProvidedFileSystem::OnObserveDirectoryCompleted( 561 void ProvidedFileSystem::OnObserveDirectoryCompleted(
562 const GURL& origin,
515 const base::FilePath& directory_path, 563 const base::FilePath& directory_path,
516 bool recursive, 564 bool recursive,
565 bool persistent,
517 const storage::AsyncFileUtil::StatusCallback& callback, 566 const storage::AsyncFileUtil::StatusCallback& callback,
518 base::File::Error result) { 567 base::File::Error result) {
519 if (result != base::File::FILE_OK) { 568 if (result != base::File::FILE_OK) {
520 callback.Run(result); 569 callback.Run(result);
521 return; 570 return;
522 } 571 }
523 572
524 const ObservedEntryKey key(directory_path, recursive); 573 const ObservedEntryKey key(directory_path, recursive);
525 const ObservedEntries::iterator it = observed_entries_.find(key); 574 const ObservedEntries::iterator it = observed_entries_.find(key);
526 if (it != observed_entries_.end()) { 575 if (it != observed_entries_.end()) {
527 callback.Run(base::File::FILE_OK); 576 callback.Run(base::File::FILE_OK);
528 return; 577 return;
529 } 578 }
530 579
531 observed_entries_[key].entry_path = directory_path; 580 ObservedEntry* const observed_entry = &observed_entries_[key];
532 observed_entries_[key].recursive = recursive; 581 observed_entry->entry_path = directory_path;
582 observed_entry->recursive = recursive;
583 observed_entry->subscribers[origin].origin = origin;
584 observed_entry->subscribers[origin].persistent |= persistent;
533 585
534 FOR_EACH_OBSERVER( 586 FOR_EACH_OBSERVER(
535 ProvidedFileSystemObserver, 587 ProvidedFileSystemObserver,
536 observers_, 588 observers_,
537 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 589 OnObservedEntryListChanged(file_system_info_, observed_entries_));
538 590
539 callback.Run(base::File::FILE_OK); 591 callback.Run(base::File::FILE_OK);
540 } 592 }
541 593
542 void ProvidedFileSystem::OnNotifyCompleted( 594 void ProvidedFileSystem::OnNotifyCompleted(
(...skipping 19 matching lines...) Expand all
562 if (!tag.empty() && tag == it->second.last_tag) 614 if (!tag.empty() && tag == it->second.last_tag)
563 LOG(ERROR) << "Tag specified, but same as the previous one."; 615 LOG(ERROR) << "Tag specified, but same as the previous one.";
564 616
565 it->second.last_tag = tag; 617 it->second.last_tag = tag;
566 618
567 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, 619 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
568 observers_, 620 observers_,
569 OnObservedEntryTagUpdated(file_system_info_, it->second)); 621 OnObservedEntryTagUpdated(file_system_info_, it->second));
570 622
571 // If the observed entry is deleted, then unobserve it. 623 // If the observed entry is deleted, then unobserve it.
572 if (change_type == ProvidedFileSystemObserver::DELETED) 624 if (change_type == ProvidedFileSystemObserver::DELETED) {
573 UnobserveEntry(observed_path, recursive, base::Bind(&EmptyStatusCallback)); 625 // Make a copy, since the |it| iterator will get invalidated on the last
626 // subscriber.
627 Subscribers subscribers = it->second.subscribers;
628 for (const auto& subscriber_it : subscribers) {
629 UnobserveEntry(subscriber_it.second.origin,
630 observed_path,
631 recursive,
632 base::Bind(&EmptyStatusCallback));
633 }
634 }
574 } 635 }
575 636
576 } // namespace file_system_provider 637 } // namespace file_system_provider
577 } // namespace chromeos 638 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698