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

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: Created 6 years, 2 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
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.
366 const ObservedEntries::const_iterator it = 375
367 observed_entries_.find(directory_path); 376 if (persistent && !file_system_info_.supports_notify_tag()) {
377 OnObserveDirectoryCompleted(origin,
378 directory_path,
379 recursive,
380 persistent,
381 callback,
382 base::File::FILE_ERROR_INVALID_OPERATION);
383 return AbortCallback();
384 }
385
386 const ObservedEntries::iterator it = observed_entries_.find(directory_path);
368 if (it != observed_entries_.end()) { 387 if (it != observed_entries_.end()) {
388 if (it->second.subscribers.find(origin) != it->second.subscribers.end()) {
389 OnObserveDirectoryCompleted(origin,
390 directory_path,
391 recursive,
392 persistent,
393 callback,
394 base::File::FILE_ERROR_EXISTS);
395 return AbortCallback();
396 }
369 if (!recursive || it->second.recursive) { 397 if (!recursive || it->second.recursive) {
hirono 2014/10/22 06:00:35 If extension A requests with recursive=false and t
mtomasz 2014/10/24 05:48:42 After offline discussion we decided to split recur
370 callback.Run(base::File::FILE_ERROR_EXISTS); 398 OnObserveDirectoryCompleted(origin,
399 directory_path,
400 recursive,
401 persistent,
402 callback,
403 base::File::FILE_OK);
371 return AbortCallback(); 404 return AbortCallback();
372 } 405 }
373 } 406 }
374 407
375 const int request_id = request_manager_->CreateRequest( 408 const int request_id = request_manager_->CreateRequest(
376 OBSERVE_DIRECTORY, 409 OBSERVE_DIRECTORY,
377 scoped_ptr<RequestManager::HandlerInterface>( 410 scoped_ptr<RequestManager::HandlerInterface>(
378 new operations::ObserveDirectory( 411 new operations::ObserveDirectory(
379 event_router_, 412 event_router_,
380 file_system_info_, 413 file_system_info_,
381 directory_path, 414 directory_path,
382 recursive, 415 recursive,
383 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted, 416 base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted,
384 weak_ptr_factory_.GetWeakPtr(), 417 weak_ptr_factory_.GetWeakPtr(),
418 origin,
385 directory_path, 419 directory_path,
386 recursive, 420 recursive,
421 persistent,
387 callback)))); 422 callback))));
423
388 if (!request_id) { 424 if (!request_id) {
389 callback.Run(base::File::FILE_ERROR_SECURITY); 425 OnObserveDirectoryCompleted(origin,
426 directory_path,
427 recursive,
428 persistent,
429 callback,
430 base::File::FILE_ERROR_SECURITY);
390 return AbortCallback(); 431 return AbortCallback();
391 } 432 }
392 433
393 return base::Bind( 434 return base::Bind(
394 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id); 435 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
395 } 436 }
396 437
397 void ProvidedFileSystem::UnobserveEntry( 438 void ProvidedFileSystem::UnobserveEntry(
439 const GURL& origin,
398 const base::FilePath& entry_path, 440 const base::FilePath& entry_path,
399 const storage::AsyncFileUtil::StatusCallback& callback) { 441 const storage::AsyncFileUtil::StatusCallback& callback) {
400 const ObservedEntries::const_iterator it = observed_entries_.find(entry_path); 442 const ObservedEntries::iterator it = observed_entries_.find(entry_path);
401 if (it == observed_entries_.end()) { 443 if (it == observed_entries_.end() ||
444 it->second.subscribers.find(origin) == it->second.subscribers.end()) {
402 callback.Run(base::File::FILE_ERROR_NOT_FOUND); 445 callback.Run(base::File::FILE_ERROR_NOT_FOUND);
403 return; 446 return;
404 } 447 }
405 448
406 // Delete the watcher in advance since the list of observed entries is owned 449 // Delete the subscriber in advance, since the list of observed entries is
407 // by the C++ layer, not by the extension. 450 // owned by the C++ layer, not by the extension.
408 observed_entries_.erase(it); 451 it->second.subscribers.erase(origin);
409 452
410 FOR_EACH_OBSERVER( 453 FOR_EACH_OBSERVER(
411 ProvidedFileSystemObserver, 454 ProvidedFileSystemObserver,
412 observers_, 455 observers_,
413 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 456 OnObservedEntryListChanged(file_system_info_, observed_entries_));
414 457
415 // TODO(mtomasz): Consider returning always an OK error code, since for the 458 // If there are other subscribers, then do not remove the obsererver, but
416 // callers it's important that the entry is not watched anymore. The watcher 459 // simply return a success.
417 // is removed even if the extension returns an error. 460 if (it->second.subscribers.size()) {
461 callback.Run(base::File::FILE_OK);
462 return;
463 }
464
465 // Delete the watcher in advance.
466 observed_entries_.erase(it);
467
468 // Even if the extension returns an error, the callback is called with base::
469 // File::FILE_OK. The reason for that is that the observed is not watched
470 // anymore anyway, as it's removed in advance.
418 const int request_id = request_manager_->CreateRequest( 471 const int request_id = request_manager_->CreateRequest(
419 UNOBSERVE_ENTRY, 472 UNOBSERVE_ENTRY,
420 scoped_ptr<RequestManager::HandlerInterface>( 473 scoped_ptr<RequestManager::HandlerInterface>(
421 new operations::UnobserveEntry( 474 new operations::UnobserveEntry(
422 event_router_, file_system_info_, entry_path, callback))); 475 event_router_,
476 file_system_info_,
477 entry_path,
478 base::Bind(&AlwaysSuccessCallback, callback))));
479
423 if (!request_id) 480 if (!request_id)
424 callback.Run(base::File::FILE_ERROR_SECURITY); 481 callback.Run(base::File::FILE_OK);
425 } 482 }
426 483
427 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const { 484 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
428 return file_system_info_; 485 return file_system_info_;
429 } 486 }
430 487
431 RequestManager* ProvidedFileSystem::GetRequestManager() { 488 RequestManager* ProvidedFileSystem::GetRequestManager() {
432 return request_manager_.get(); 489 return request_manager_.get();
433 } 490 }
434 491
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 scoped_ptr<RequestManager::HandlerInterface>( 556 scoped_ptr<RequestManager::HandlerInterface>(
500 new operations::Abort(event_router_, 557 new operations::Abort(event_router_,
501 file_system_info_, 558 file_system_info_,
502 operation_request_id, 559 operation_request_id,
503 callback)))) { 560 callback)))) {
504 callback.Run(base::File::FILE_ERROR_SECURITY); 561 callback.Run(base::File::FILE_ERROR_SECURITY);
505 } 562 }
506 } 563 }
507 564
508 void ProvidedFileSystem::OnObserveDirectoryCompleted( 565 void ProvidedFileSystem::OnObserveDirectoryCompleted(
566 const GURL& origin,
509 const base::FilePath& directory_path, 567 const base::FilePath& directory_path,
510 bool recursive, 568 bool recursive,
569 bool persistent,
511 const storage::AsyncFileUtil::StatusCallback& callback, 570 const storage::AsyncFileUtil::StatusCallback& callback,
512 base::File::Error result) { 571 base::File::Error result) {
513 if (result != base::File::FILE_OK) { 572 if (result != base::File::FILE_OK) {
514 callback.Run(result); 573 callback.Run(result);
515 return; 574 return;
516 } 575 }
517 576
518 observed_entries_[directory_path].entry_path = directory_path; 577 ObservedEntry* const observed_entry = &observed_entries_[directory_path];
519 observed_entries_[directory_path].recursive |= recursive; 578 observed_entry->entry_path = directory_path;
579 observed_entry->recursive |= recursive;
580 observed_entry->subscribers[origin].origin = origin;
581 observed_entry->subscribers[origin].persistent |= persistent;
520 582
521 FOR_EACH_OBSERVER( 583 FOR_EACH_OBSERVER(
522 ProvidedFileSystemObserver, 584 ProvidedFileSystemObserver,
523 observers_, 585 observers_,
524 OnObservedEntryListChanged(file_system_info_, observed_entries_)); 586 OnObservedEntryListChanged(file_system_info_, observed_entries_));
525 587
526 callback.Run(result); 588 callback.Run(result);
527 } 589 }
528 590
529 void ProvidedFileSystem::OnNotifyCompleted( 591 void ProvidedFileSystem::OnNotifyCompleted(
(...skipping 17 matching lines...) Expand all
547 if (!tag.empty() && tag == it->second.last_tag) 609 if (!tag.empty() && tag == it->second.last_tag)
548 LOG(ERROR) << "Tag specified, but same as the previous one."; 610 LOG(ERROR) << "Tag specified, but same as the previous one.";
549 611
550 it->second.last_tag = tag; 612 it->second.last_tag = tag;
551 613
552 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, 614 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
553 observers_, 615 observers_,
554 OnObservedEntryTagUpdated(file_system_info_, it->second)); 616 OnObservedEntryTagUpdated(file_system_info_, it->second));
555 617
556 // If the observed entry is deleted, then unobserve it. 618 // If the observed entry is deleted, then unobserve it.
557 if (change_type == ProvidedFileSystemObserver::DELETED) 619 if (change_type == ProvidedFileSystemObserver::DELETED) {
558 UnobserveEntry(observed_path, base::Bind(&EmptyStatusCallback)); 620 // Make a copy, since the |it| iterator will get invalidated on the last
621 // subscriber.
622 Subscribers subscribers = it->second.subscribers;
623 for (const auto& subscriber_it : subscribers) {
624 UnobserveEntry(subscriber_it.second.origin,
625 observed_path,
626 base::Bind(&EmptyStatusCallback));
627 }
628 }
559 } 629 }
560 630
561 } // namespace file_system_provider 631 } // namespace file_system_provider
562 } // namespace chromeos 632 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698