| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |