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

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

Powered by Google App Engine
This is Rietveld 408576698