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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/file_system_provider/provided_file_system.cc
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
index 06dd39af0ab780db0b3a58112c4ce30a1f0045cc..853da613b931504afa5fc878bc11712017aed93f 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
@@ -42,6 +42,13 @@ namespace {
void EmptyStatusCallback(base::File::Error /* result */) {
}
+// Discards the error code and always calls the callback with a success.
+void AlwaysSuccessCallback(
+ const storage::AsyncFileUtil::StatusCallback& callback,
+ base::File::Error /* result */) {
+ callback.Run(base::File::FILE_OK);
+}
+
} // namespace
AutoUpdater::AutoUpdater(const base::Closure& update_callback)
@@ -358,16 +365,42 @@ ProvidedFileSystem::AbortCallback ProvidedFileSystem::Truncate(
}
ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory(
+ const GURL& origin,
const base::FilePath& directory_path,
bool recursive,
+ bool persistent,
const storage::AsyncFileUtil::StatusCallback& callback) {
// TODO(mtomasz): Wrap the entire method body with an asynchronous queue to
// avoid races.
- const ObservedEntries::const_iterator it =
- observed_entries_.find(directory_path);
+
+ if (persistent && !file_system_info_.supports_notify_tag()) {
+ OnObserveDirectoryCompleted(origin,
+ directory_path,
+ recursive,
+ persistent,
+ callback,
+ base::File::FILE_ERROR_INVALID_OPERATION);
+ return AbortCallback();
+ }
+
+ const ObservedEntries::iterator it = observed_entries_.find(directory_path);
if (it != observed_entries_.end()) {
+ if (it->second.subscribers.find(origin) != it->second.subscribers.end()) {
+ OnObserveDirectoryCompleted(origin,
+ directory_path,
+ recursive,
+ persistent,
+ callback,
+ base::File::FILE_ERROR_EXISTS);
+ return AbortCallback();
+ }
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
- callback.Run(base::File::FILE_ERROR_EXISTS);
+ OnObserveDirectoryCompleted(origin,
+ directory_path,
+ recursive,
+ persistent,
+ callback,
+ base::File::FILE_OK);
return AbortCallback();
}
}
@@ -382,11 +415,19 @@ ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory(
recursive,
base::Bind(&ProvidedFileSystem::OnObserveDirectoryCompleted,
weak_ptr_factory_.GetWeakPtr(),
+ origin,
directory_path,
recursive,
+ persistent,
callback))));
+
if (!request_id) {
- callback.Run(base::File::FILE_ERROR_SECURITY);
+ OnObserveDirectoryCompleted(origin,
+ directory_path,
+ recursive,
+ persistent,
+ callback,
+ base::File::FILE_ERROR_SECURITY);
return AbortCallback();
}
@@ -395,33 +436,49 @@ ProvidedFileSystem::AbortCallback ProvidedFileSystem::ObserveDirectory(
}
void ProvidedFileSystem::UnobserveEntry(
+ const GURL& origin,
const base::FilePath& entry_path,
const storage::AsyncFileUtil::StatusCallback& callback) {
- const ObservedEntries::const_iterator it = observed_entries_.find(entry_path);
- if (it == observed_entries_.end()) {
+ const ObservedEntries::iterator it = observed_entries_.find(entry_path);
+ if (it == observed_entries_.end() ||
+ it->second.subscribers.find(origin) == it->second.subscribers.end()) {
callback.Run(base::File::FILE_ERROR_NOT_FOUND);
return;
}
- // Delete the watcher in advance since the list of observed entries is owned
- // by the C++ layer, not by the extension.
- observed_entries_.erase(it);
+ // Delete the subscriber in advance, since the list of observed entries is
+ // owned by the C++ layer, not by the extension.
+ it->second.subscribers.erase(origin);
FOR_EACH_OBSERVER(
ProvidedFileSystemObserver,
observers_,
OnObservedEntryListChanged(file_system_info_, observed_entries_));
- // TODO(mtomasz): Consider returning always an OK error code, since for the
- // callers it's important that the entry is not watched anymore. The watcher
- // is removed even if the extension returns an error.
+ // If there are other subscribers, then do not remove the obsererver, but
+ // simply return a success.
+ if (it->second.subscribers.size()) {
+ callback.Run(base::File::FILE_OK);
+ return;
+ }
+
+ // Delete the watcher in advance.
+ observed_entries_.erase(it);
+
+ // Even if the extension returns an error, the callback is called with base::
+ // File::FILE_OK. The reason for that is that the observed is not watched
+ // anymore anyway, as it's removed in advance.
const int request_id = request_manager_->CreateRequest(
UNOBSERVE_ENTRY,
scoped_ptr<RequestManager::HandlerInterface>(
new operations::UnobserveEntry(
- event_router_, file_system_info_, entry_path, callback)));
+ event_router_,
+ file_system_info_,
+ entry_path,
+ base::Bind(&AlwaysSuccessCallback, callback))));
+
if (!request_id)
- callback.Run(base::File::FILE_ERROR_SECURITY);
+ callback.Run(base::File::FILE_OK);
}
const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
@@ -506,8 +563,10 @@ void ProvidedFileSystem::Abort(
}
void ProvidedFileSystem::OnObserveDirectoryCompleted(
+ const GURL& origin,
const base::FilePath& directory_path,
bool recursive,
+ bool persistent,
const storage::AsyncFileUtil::StatusCallback& callback,
base::File::Error result) {
if (result != base::File::FILE_OK) {
@@ -515,8 +574,11 @@ void ProvidedFileSystem::OnObserveDirectoryCompleted(
return;
}
- observed_entries_[directory_path].entry_path = directory_path;
- observed_entries_[directory_path].recursive |= recursive;
+ ObservedEntry* const observed_entry = &observed_entries_[directory_path];
+ observed_entry->entry_path = directory_path;
+ observed_entry->recursive |= recursive;
+ observed_entry->subscribers[origin].origin = origin;
+ observed_entry->subscribers[origin].persistent |= persistent;
FOR_EACH_OBSERVER(
ProvidedFileSystemObserver,
@@ -554,8 +616,16 @@ void ProvidedFileSystem::OnNotifyCompleted(
OnObservedEntryTagUpdated(file_system_info_, it->second));
// If the observed entry is deleted, then unobserve it.
- if (change_type == ProvidedFileSystemObserver::DELETED)
- UnobserveEntry(observed_path, base::Bind(&EmptyStatusCallback));
+ if (change_type == ProvidedFileSystemObserver::DELETED) {
+ // Make a copy, since the |it| iterator will get invalidated on the last
+ // subscriber.
+ Subscribers subscribers = it->second.subscribers;
+ for (const auto& subscriber_it : subscribers) {
+ UnobserveEntry(subscriber_it.second.origin,
+ observed_path,
+ base::Bind(&EmptyStatusCallback));
+ }
+ }
}
} // namespace file_system_provider

Powered by Google App Engine
This is Rietveld 408576698