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

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: Fixed. 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()) {
369 OnObserveDirectoryCompleted( 388 OnObserveDirectoryCompleted(origin,
370 directory_path, recursive, callback, base::File::FILE_ERROR_EXISTS); 389 directory_path,
390 recursive,
391 persistent,
392 callback,
393 base::File::FILE_ERROR_EXISTS);
371 return AbortCallback(); 394 return AbortCallback();
372 } 395 }
373 396
397 if (it != observed_entries_.end()) {
hirono 2014/10/27 04:50:31 it != observed_entries_.end() is always false beca
mtomasz 2014/10/27 05:01:18 Right. Done.
398 if (it->second.subscribers.find(origin) != it->second.subscribers.end()) {
399 OnObserveDirectoryCompleted(origin,
400 directory_path,
401 recursive,
402 persistent,
403 callback,
404 base::File::FILE_ERROR_EXISTS);
405 return AbortCallback();
406 }
407 }
408
374 const int request_id = request_manager_->CreateRequest( 409 const int request_id = request_manager_->CreateRequest(
375 OBSERVE_DIRECTORY, 410 OBSERVE_DIRECTORY,
376 scoped_ptr<RequestManager::HandlerInterface>( 411 scoped_ptr<RequestManager::HandlerInterface>(
377 new operations::ObserveDirectory( 412 new operations::ObserveDirectory(
378 event_router_, 413 event_router_,
379 file_system_info_, 414 file_system_info_,
380 directory_path, 415 directory_path,
381 recursive, 416 recursive,
382 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted, 417 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted,
383 weak_ptr_factory_.GetWeakPtr(), 418 weak_ptr_factory_.GetWeakPtr(),
419 origin,
384 directory_path, 420 directory_path,
385 recursive, 421 recursive,
422 persistent,
386 callback)))); 423 callback))));
424
387 if (!request_id) { 425 if (!request_id) {
388 callback.Run(base::File::FILE_ERROR_SECURITY); 426 OnObserveDirectoryCompleted(origin,
427 directory_path,
428 recursive,
429 persistent,
430 callback,
431 base::File::FILE_ERROR_SECURITY);
389 return AbortCallback(); 432 return AbortCallback();
390 } 433 }
391 434
392 return base::Bind( 435 return base::Bind(
393 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 436 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
394 } 437 }
395 438
396 void ProvidedFileSystem::UnobserveEntry( 439 void ProvidedFileSystem::UnobserveEntry(
440 const GURL& origin,
397 const base::FilePath& entry_path, 441 const base::FilePath& entry_path,
398 bool recursive, 442 bool recursive,
399 const storage::AsyncFileUtil::StatusCallback& callback) { 443 const storage::AsyncFileUtil::StatusCallback& callback) {
400 const ObservedEntryKey key(entry_path, recursive); 444 const ObservedEntryKey key(entry_path, recursive);
401 const ObservedEntries::const_iterator it = observed_entries_.find(key); 445 const ObservedEntries::iterator it = observed_entries_.find(key);
402 if (it == observed_entries_.end()) { 446 if (it == observed_entries_.end() ||
447 it->second.subscribers.find(origin) == it->second.subscribers.end()) {
403 callback.Run(base::File::FILE_ERROR_NOT_FOUND); 448 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
404 return; 449 return;
405 } 450 }
406 451
407 // Delete the watcher in advance since the list of observed entries is owned 452 // Delete the subscriber in advance, since the list of observed entries is
408 // by the C++ layer, not by the extension. 453 // owned by the C++ layer, not by the extension.
409 observed_entries_.erase(it); 454 it->second.subscribers.erase(origin);
410 455
411 FOR_EACH_OBSERVER( 456 FOR_EACH_OBSERVER(
412 ProvidedFileSystemObserver, 457 ProvidedFileSystemObserver,
413 observers_, 458 observers_,
414 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 459 OnObservedEntryListChanged(file_system_info_, observed_entries_));
415 460
416 // TODO(mtomasz): Consider returning always an OK error code, since for the 461 // 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 462 // simply return a success.
418 // is removed even if the extension returns an error. 463 if (it->second.subscribers.size()) {
464 callback.Run(base::File::FILE_OK);
465 return;
466 }
467
468 // Delete the watcher in advance.
469 observed_entries_.erase(it);
470
471 // Even if the extension returns an error, the callback is called with base::
472 // File::FILE_OK. The reason for that is that the observed is not watched
473 // anymore anyway, as it's removed in advance.
419 const int request_id = request_manager_->CreateRequest( 474 const int request_id = request_manager_->CreateRequest(
420 UNOBSERVE_ENTRY, 475 UNOBSERVE_ENTRY,
421 scoped_ptr<RequestManager::HandlerInterface>( 476 scoped_ptr<RequestManager::HandlerInterface>(
422 new operations::UnobserveEntry(event_router_, 477 new operations::UnobserveEntry(
423 file_system_info_, 478 event_router_,
424 entry_path, 479 file_system_info_,
425 recursive, 480 entry_path,
426 callback))); 481 recursive,
482 base::Bind(&AlwaysSuccessCallback, callback))));
427 if (!request_id) 483 if (!request_id)
428 callback.Run(base::File::FILE_ERROR_SECURITY); 484 callback.Run(base::File::FILE_OK);
429 } 485 }
430 486
431 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const { 487 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
432 return file_system_info_; 488 return file_system_info_;
433 } 489 }
434 490
435 RequestManager* ProvidedFileSystem::GetRequestManager() { 491 RequestManager* ProvidedFileSystem::GetRequestManager() {
436 return request_manager_.get(); 492 return request_manager_.get();
437 } 493 }
438 494
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 scoped_ptr<RequestManager::HandlerInterface>( 561 scoped_ptr<RequestManager::HandlerInterface>(
506 new operations::Abort(event_router_, 562 new operations::Abort(event_router_,
507 file_system_info_, 563 file_system_info_,
508 operation_request_id, 564 operation_request_id,
509 callback)))) { 565 callback)))) {
510 callback.Run(base::File::FILE_ERROR_SECURITY); 566 callback.Run(base::File::FILE_ERROR_SECURITY);
511 } 567 }
512 } 568 }
513 569
514 void ProvidedFileSystem::OnObserveDirectoryCompleted( 570 void ProvidedFileSystem::OnObserveDirectoryCompleted(
571 const GURL& origin,
515 const base::FilePath& directory_path, 572 const base::FilePath& directory_path,
516 bool recursive, 573 bool recursive,
574 bool persistent,
517 const storage::AsyncFileUtil::StatusCallback& callback, 575 const storage::AsyncFileUtil::StatusCallback& callback,
518 base::File::Error result) { 576 base::File::Error result) {
519 if (result != base::File::FILE_OK) { 577 if (result != base::File::FILE_OK) {
520 callback.Run(result); 578 callback.Run(result);
521 return; 579 return;
522 } 580 }
523 581
524 const ObservedEntryKey key(directory_path, recursive); 582 const ObservedEntryKey key(directory_path, recursive);
525 const ObservedEntries::iterator it = observed_entries_.find(key); 583 const ObservedEntries::iterator it = observed_entries_.find(key);
526 if (it != observed_entries_.end()) { 584 if (it != observed_entries_.end()) {
527 callback.Run(base::File::FILE_OK); 585 callback.Run(base::File::FILE_OK);
528 return; 586 return;
529 } 587 }
530 588
531 observed_entries_[key].entry_path = directory_path; 589 ObservedEntry* const observed_entry = &observed_entries_[key];
532 observed_entries_[key].recursive = recursive; 590 observed_entry->entry_path = directory_path;
591 observed_entry->recursive = recursive;
592 observed_entry->subscribers[origin].origin = origin;
593 observed_entry->subscribers[origin].persistent |= persistent;
533 594
534 FOR_EACH_OBSERVER( 595 FOR_EACH_OBSERVER(
535 ProvidedFileSystemObserver, 596 ProvidedFileSystemObserver,
536 observers_, 597 observers_,
537 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 598 OnObservedEntryListChanged(file_system_info_, observed_entries_));
538 599
539 callback.Run(base::File::FILE_OK); 600 callback.Run(base::File::FILE_OK);
540 } 601 }
541 602
542 void ProvidedFileSystem::OnNotifyCompleted( 603 void ProvidedFileSystem::OnNotifyCompleted(
(...skipping 19 matching lines...) Expand all
562 if (!tag.empty() && tag == it->second.last_tag) 623 if (!tag.empty() && tag == it->second.last_tag)
563 LOG(ERROR) << "Tag specified, but same as the previous one."; 624 LOG(ERROR) << "Tag specified, but same as the previous one.";
564 625
565 it->second.last_tag = tag; 626 it->second.last_tag = tag;
566 627
567 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, 628 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
568 observers_, 629 observers_,
569 OnObservedEntryTagUpdated(file_system_info_, it->second)); 630 OnObservedEntryTagUpdated(file_system_info_, it->second));
570 631
571 // If the observed entry is deleted, then unobserve it. 632 // If the observed entry is deleted, then unobserve it.
572 if (change_type == ProvidedFileSystemObserver::DELETED) 633 if (change_type == ProvidedFileSystemObserver::DELETED) {
573 UnobserveEntry(observed_path, recursive, base::Bind(&EmptyStatusCallback)); 634 // Make a copy, since the |it| iterator will get invalidated on the last
635 // subscriber.
636 Subscribers subscribers = it->second.subscribers;
637 for (const auto& subscriber_it : subscribers) {
638 UnobserveEntry(subscriber_it.second.origin,
639 observed_path,
640 recursive,
641 base::Bind(&EmptyStatusCallback));
642 }
643 }
574 } 644 }
575 645
576 } // namespace file_system_provider 646 } // namespace file_system_provider
577 } // namespace chromeos 647 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698