Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / file_system_provider / provided_file_system.cc
blobaef7e5842a94cb0501941e85f0ecc32fca574723
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
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
7 #include <vector>
9 #include "base/files/file.h"
10 #include "base/trace_event/trace_event.h"
11 #include "chrome/browser/chromeos/file_system_provider/notification_manager.h"
12 #include "chrome/browser/chromeos/file_system_provider/operations/abort.h"
13 #include "chrome/browser/chromeos/file_system_provider/operations/add_watcher.h"
14 #include "chrome/browser/chromeos/file_system_provider/operations/close_file.h"
15 #include "chrome/browser/chromeos/file_system_provider/operations/copy_entry.h"
16 #include "chrome/browser/chromeos/file_system_provider/operations/create_directory.h"
17 #include "chrome/browser/chromeos/file_system_provider/operations/create_file.h"
18 #include "chrome/browser/chromeos/file_system_provider/operations/delete_entry.h"
19 #include "chrome/browser/chromeos/file_system_provider/operations/get_metadata.h"
20 #include "chrome/browser/chromeos/file_system_provider/operations/move_entry.h"
21 #include "chrome/browser/chromeos/file_system_provider/operations/open_file.h"
22 #include "chrome/browser/chromeos/file_system_provider/operations/read_directory.h"
23 #include "chrome/browser/chromeos/file_system_provider/operations/read_file.h"
24 #include "chrome/browser/chromeos/file_system_provider/operations/remove_watcher.h"
25 #include "chrome/browser/chromeos/file_system_provider/operations/truncate.h"
26 #include "chrome/browser/chromeos/file_system_provider/operations/unmount.h"
27 #include "chrome/browser/chromeos/file_system_provider/operations/write_file.h"
28 #include "chrome/browser/chromeos/file_system_provider/request_manager.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/common/extensions/api/file_system_provider.h"
31 #include "extensions/browser/event_router.h"
33 namespace net {
34 class IOBuffer;
35 } // namespace net
37 namespace chromeos {
38 namespace file_system_provider {
39 namespace {
41 // Discards the result of Abort() when called from the destructor.
42 void EmptyStatusCallback(base::File::Error /* result */) {
45 } // namespace
47 AutoUpdater::AutoUpdater(const base::Closure& update_callback)
48 : update_callback_(update_callback),
49 created_callbacks_(0),
50 pending_callbacks_(0) {
53 base::Closure AutoUpdater::CreateCallback() {
54 ++created_callbacks_;
55 ++pending_callbacks_;
56 return base::Bind(&AutoUpdater::OnPendingCallback, this);
59 void AutoUpdater::OnPendingCallback() {
60 DCHECK_LT(0, pending_callbacks_);
61 if (--pending_callbacks_ == 0)
62 update_callback_.Run();
65 AutoUpdater::~AutoUpdater() {
66 // If no callbacks are created, then we need to invoke updating in the
67 // destructor.
68 if (!created_callbacks_)
69 update_callback_.Run();
70 else if (pending_callbacks_)
71 LOG(ERROR) << "Not all callbacks called. This may happen on shutdown.";
74 struct ProvidedFileSystem::AddWatcherInQueueArgs {
75 AddWatcherInQueueArgs(size_t token,
76 const GURL& origin,
77 const base::FilePath& entry_path,
78 bool recursive,
79 bool persistent,
80 const storage::AsyncFileUtil::StatusCallback& callback,
81 const storage::WatcherManager::NotificationCallback&
82 notification_callback)
83 : token(token),
84 origin(origin),
85 entry_path(entry_path),
86 recursive(recursive),
87 persistent(persistent),
88 callback(callback),
89 notification_callback(notification_callback) {}
90 ~AddWatcherInQueueArgs() {}
92 const size_t token;
93 const GURL origin;
94 const base::FilePath entry_path;
95 const bool recursive;
96 const bool persistent;
97 const storage::AsyncFileUtil::StatusCallback callback;
98 const storage::WatcherManager::NotificationCallback notification_callback;
101 struct ProvidedFileSystem::NotifyInQueueArgs {
102 NotifyInQueueArgs(size_t token,
103 const base::FilePath& entry_path,
104 bool recursive,
105 storage::WatcherManager::ChangeType change_type,
106 scoped_ptr<ProvidedFileSystemObserver::Changes> changes,
107 const std::string& tag,
108 const storage::AsyncFileUtil::StatusCallback& callback)
109 : token(token),
110 entry_path(entry_path),
111 recursive(recursive),
112 change_type(change_type),
113 changes(changes.Pass()),
114 tag(tag),
115 callback(callback) {}
116 ~NotifyInQueueArgs() {}
118 const size_t token;
119 const base::FilePath entry_path;
120 const bool recursive;
121 const storage::WatcherManager::ChangeType change_type;
122 const scoped_ptr<ProvidedFileSystemObserver::Changes> changes;
123 const std::string tag;
124 const storage::AsyncFileUtil::StatusCallback callback;
126 private:
127 DISALLOW_COPY_AND_ASSIGN(NotifyInQueueArgs);
130 ProvidedFileSystem::ProvidedFileSystem(
131 Profile* profile,
132 const ProvidedFileSystemInfo& file_system_info)
133 : profile_(profile),
134 event_router_(extensions::EventRouter::Get(profile)), // May be NULL.
135 file_system_info_(file_system_info),
136 notification_manager_(
137 new NotificationManager(profile_, file_system_info_)),
138 request_manager_(new RequestManager(notification_manager_.get())),
139 watcher_queue_(1),
140 weak_ptr_factory_(this) {
143 ProvidedFileSystem::~ProvidedFileSystem() {
144 const std::vector<int> request_ids = request_manager_->GetActiveRequestIds();
145 for (size_t i = 0; i < request_ids.size(); ++i) {
146 Abort(request_ids[i]);
150 void ProvidedFileSystem::SetEventRouterForTesting(
151 extensions::EventRouter* event_router) {
152 event_router_ = event_router;
155 void ProvidedFileSystem::SetNotificationManagerForTesting(
156 scoped_ptr<NotificationManagerInterface> notification_manager) {
157 notification_manager_ = notification_manager.Pass();
158 request_manager_.reset(new RequestManager(notification_manager_.get()));
161 AbortCallback ProvidedFileSystem::RequestUnmount(
162 const storage::AsyncFileUtil::StatusCallback& callback) {
163 const int request_id = request_manager_->CreateRequest(
164 REQUEST_UNMOUNT,
165 scoped_ptr<RequestManager::HandlerInterface>(
166 new operations::Unmount(event_router_, file_system_info_, callback)));
167 if (!request_id) {
168 callback.Run(base::File::FILE_ERROR_SECURITY);
169 return AbortCallback();
172 return base::Bind(
173 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
176 AbortCallback ProvidedFileSystem::GetMetadata(
177 const base::FilePath& entry_path,
178 MetadataFieldMask fields,
179 const GetMetadataCallback& callback) {
180 const int request_id = request_manager_->CreateRequest(
181 GET_METADATA,
182 scoped_ptr<RequestManager::HandlerInterface>(new operations::GetMetadata(
183 event_router_, file_system_info_, entry_path, fields, callback)));
184 if (!request_id) {
185 callback.Run(make_scoped_ptr<EntryMetadata>(NULL),
186 base::File::FILE_ERROR_SECURITY);
187 return AbortCallback();
190 return base::Bind(
191 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
194 AbortCallback ProvidedFileSystem::ReadDirectory(
195 const base::FilePath& directory_path,
196 const storage::AsyncFileUtil::ReadDirectoryCallback& callback) {
197 const int request_id = request_manager_->CreateRequest(
198 READ_DIRECTORY,
199 scoped_ptr<RequestManager::HandlerInterface>(
200 new operations::ReadDirectory(
201 event_router_, file_system_info_, directory_path, callback)));
202 if (!request_id) {
203 callback.Run(base::File::FILE_ERROR_SECURITY,
204 storage::AsyncFileUtil::EntryList(),
205 false /* has_more */);
206 return AbortCallback();
209 return base::Bind(
210 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
213 AbortCallback ProvidedFileSystem::ReadFile(
214 int file_handle,
215 net::IOBuffer* buffer,
216 int64 offset,
217 int length,
218 const ReadChunkReceivedCallback& callback) {
219 TRACE_EVENT1(
220 "file_system_provider", "ProvidedFileSystem::ReadFile", "length", length);
221 const int request_id = request_manager_->CreateRequest(
222 READ_FILE,
223 make_scoped_ptr<RequestManager::HandlerInterface>(
224 new operations::ReadFile(event_router_,
225 file_system_info_,
226 file_handle,
227 buffer,
228 offset,
229 length,
230 callback)));
231 if (!request_id) {
232 callback.Run(0 /* chunk_length */,
233 false /* has_more */,
234 base::File::FILE_ERROR_SECURITY);
235 return AbortCallback();
238 return base::Bind(
239 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
242 AbortCallback ProvidedFileSystem::OpenFile(const base::FilePath& file_path,
243 OpenFileMode mode,
244 const OpenFileCallback& callback) {
245 const int request_id = request_manager_->CreateRequest(
246 OPEN_FILE,
247 scoped_ptr<RequestManager::HandlerInterface>(new operations::OpenFile(
248 event_router_, file_system_info_, file_path, mode,
249 base::Bind(&ProvidedFileSystem::OnOpenFileCompleted,
250 weak_ptr_factory_.GetWeakPtr(), file_path, mode,
251 callback))));
252 if (!request_id) {
253 callback.Run(0 /* file_handle */, base::File::FILE_ERROR_SECURITY);
254 return AbortCallback();
257 return base::Bind(
258 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
261 AbortCallback ProvidedFileSystem::CloseFile(
262 int file_handle,
263 const storage::AsyncFileUtil::StatusCallback& callback) {
264 const int request_id = request_manager_->CreateRequest(
265 CLOSE_FILE,
266 scoped_ptr<RequestManager::HandlerInterface>(new operations::CloseFile(
267 event_router_, file_system_info_, file_handle,
268 base::Bind(&ProvidedFileSystem::OnCloseFileCompleted,
269 weak_ptr_factory_.GetWeakPtr(), file_handle, callback))));
270 if (!request_id) {
271 callback.Run(base::File::FILE_ERROR_SECURITY);
272 return AbortCallback();
275 return base::Bind(
276 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
279 AbortCallback ProvidedFileSystem::CreateDirectory(
280 const base::FilePath& directory_path,
281 bool recursive,
282 const storage::AsyncFileUtil::StatusCallback& callback) {
283 const int request_id = request_manager_->CreateRequest(
284 CREATE_DIRECTORY,
285 scoped_ptr<RequestManager::HandlerInterface>(
286 new operations::CreateDirectory(event_router_,
287 file_system_info_,
288 directory_path,
289 recursive,
290 callback)));
291 if (!request_id) {
292 callback.Run(base::File::FILE_ERROR_SECURITY);
293 return AbortCallback();
296 return base::Bind(
297 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
300 AbortCallback ProvidedFileSystem::DeleteEntry(
301 const base::FilePath& entry_path,
302 bool recursive,
303 const storage::AsyncFileUtil::StatusCallback& callback) {
304 const int request_id = request_manager_->CreateRequest(
305 DELETE_ENTRY,
306 scoped_ptr<RequestManager::HandlerInterface>(new operations::DeleteEntry(
307 event_router_, file_system_info_, entry_path, recursive, callback)));
308 if (!request_id) {
309 callback.Run(base::File::FILE_ERROR_SECURITY);
310 return AbortCallback();
313 return base::Bind(
314 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
317 AbortCallback ProvidedFileSystem::CreateFile(
318 const base::FilePath& file_path,
319 const storage::AsyncFileUtil::StatusCallback& callback) {
320 const int request_id = request_manager_->CreateRequest(
321 CREATE_FILE,
322 scoped_ptr<RequestManager::HandlerInterface>(new operations::CreateFile(
323 event_router_, file_system_info_, file_path, callback)));
324 if (!request_id) {
325 callback.Run(base::File::FILE_ERROR_SECURITY);
326 return AbortCallback();
329 return base::Bind(
330 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
333 AbortCallback ProvidedFileSystem::CopyEntry(
334 const base::FilePath& source_path,
335 const base::FilePath& target_path,
336 const storage::AsyncFileUtil::StatusCallback& callback) {
337 const int request_id = request_manager_->CreateRequest(
338 COPY_ENTRY,
339 scoped_ptr<RequestManager::HandlerInterface>(
340 new operations::CopyEntry(event_router_,
341 file_system_info_,
342 source_path,
343 target_path,
344 callback)));
345 if (!request_id) {
346 callback.Run(base::File::FILE_ERROR_SECURITY);
347 return AbortCallback();
350 return base::Bind(
351 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
354 AbortCallback ProvidedFileSystem::WriteFile(
355 int file_handle,
356 net::IOBuffer* buffer,
357 int64 offset,
358 int length,
359 const storage::AsyncFileUtil::StatusCallback& callback) {
360 TRACE_EVENT1("file_system_provider",
361 "ProvidedFileSystem::WriteFile",
362 "length",
363 length);
364 const int request_id = request_manager_->CreateRequest(
365 WRITE_FILE,
366 make_scoped_ptr<RequestManager::HandlerInterface>(
367 new operations::WriteFile(event_router_,
368 file_system_info_,
369 file_handle,
370 make_scoped_refptr(buffer),
371 offset,
372 length,
373 callback)));
374 if (!request_id) {
375 callback.Run(base::File::FILE_ERROR_SECURITY);
376 return AbortCallback();
379 return base::Bind(
380 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
383 AbortCallback ProvidedFileSystem::MoveEntry(
384 const base::FilePath& source_path,
385 const base::FilePath& target_path,
386 const storage::AsyncFileUtil::StatusCallback& callback) {
387 const int request_id = request_manager_->CreateRequest(
388 MOVE_ENTRY,
389 scoped_ptr<RequestManager::HandlerInterface>(
390 new operations::MoveEntry(event_router_,
391 file_system_info_,
392 source_path,
393 target_path,
394 callback)));
395 if (!request_id) {
396 callback.Run(base::File::FILE_ERROR_SECURITY);
397 return AbortCallback();
400 return base::Bind(
401 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
404 AbortCallback ProvidedFileSystem::Truncate(
405 const base::FilePath& file_path,
406 int64 length,
407 const storage::AsyncFileUtil::StatusCallback& callback) {
408 const int request_id = request_manager_->CreateRequest(
409 TRUNCATE,
410 scoped_ptr<RequestManager::HandlerInterface>(new operations::Truncate(
411 event_router_, file_system_info_, file_path, length, callback)));
412 if (!request_id) {
413 callback.Run(base::File::FILE_ERROR_SECURITY);
414 return AbortCallback();
417 return base::Bind(
418 &ProvidedFileSystem::Abort, weak_ptr_factory_.GetWeakPtr(), request_id);
421 AbortCallback ProvidedFileSystem::AddWatcher(
422 const GURL& origin,
423 const base::FilePath& entry_path,
424 bool recursive,
425 bool persistent,
426 const storage::AsyncFileUtil::StatusCallback& callback,
427 const storage::WatcherManager::NotificationCallback&
428 notification_callback) {
429 const size_t token = watcher_queue_.NewToken();
430 watcher_queue_.Enqueue(
431 token, base::Bind(&ProvidedFileSystem::AddWatcherInQueue,
432 base::Unretained(this), // Outlived by the queue.
433 AddWatcherInQueueArgs(token, origin, entry_path,
434 recursive, persistent, callback,
435 notification_callback)));
436 return AbortCallback();
439 void ProvidedFileSystem::RemoveWatcher(
440 const GURL& origin,
441 const base::FilePath& entry_path,
442 bool recursive,
443 const storage::AsyncFileUtil::StatusCallback& callback) {
444 const size_t token = watcher_queue_.NewToken();
445 watcher_queue_.Enqueue(
446 token, base::Bind(&ProvidedFileSystem::RemoveWatcherInQueue,
447 base::Unretained(this), // Outlived by the queue.
448 token, origin, entry_path, recursive, callback));
451 const ProvidedFileSystemInfo& ProvidedFileSystem::GetFileSystemInfo() const {
452 return file_system_info_;
455 RequestManager* ProvidedFileSystem::GetRequestManager() {
456 return request_manager_.get();
459 Watchers* ProvidedFileSystem::GetWatchers() {
460 return &watchers_;
463 const OpenedFiles& ProvidedFileSystem::GetOpenedFiles() const {
464 return opened_files_;
467 void ProvidedFileSystem::AddObserver(ProvidedFileSystemObserver* observer) {
468 DCHECK(observer);
469 observers_.AddObserver(observer);
472 void ProvidedFileSystem::RemoveObserver(ProvidedFileSystemObserver* observer) {
473 DCHECK(observer);
474 observers_.RemoveObserver(observer);
477 void ProvidedFileSystem::Notify(
478 const base::FilePath& entry_path,
479 bool recursive,
480 storage::WatcherManager::ChangeType change_type,
481 scoped_ptr<ProvidedFileSystemObserver::Changes> changes,
482 const std::string& tag,
483 const storage::AsyncFileUtil::StatusCallback& callback) {
484 const size_t token = watcher_queue_.NewToken();
485 watcher_queue_.Enqueue(
486 token, base::Bind(&ProvidedFileSystem::NotifyInQueue,
487 base::Unretained(this), // Outlived by the queue.
488 base::Passed(make_scoped_ptr(new NotifyInQueueArgs(
489 token, entry_path, recursive, change_type,
490 changes.Pass(), tag, callback)))));
493 void ProvidedFileSystem::Abort(int operation_request_id) {
494 request_manager_->RejectRequest(operation_request_id,
495 make_scoped_ptr(new RequestValue()),
496 base::File::FILE_ERROR_ABORT);
497 if (!request_manager_->CreateRequest(
498 ABORT,
499 scoped_ptr<RequestManager::HandlerInterface>(new operations::Abort(
500 event_router_, file_system_info_, operation_request_id,
501 base::Bind(&EmptyStatusCallback))))) {
502 LOG(ERROR) << "Failed to create an abort request.";
506 AbortCallback ProvidedFileSystem::AddWatcherInQueue(
507 const AddWatcherInQueueArgs& args) {
508 if (args.persistent && (!file_system_info_.supports_notify_tag() ||
509 !args.notification_callback.is_null())) {
510 OnAddWatcherInQueueCompleted(args.token, args.entry_path, args.recursive,
511 Subscriber(), args.callback,
512 base::File::FILE_ERROR_INVALID_OPERATION);
513 return AbortCallback();
516 // Create a candidate subscriber. This could be done in OnAddWatcherCompleted,
517 // but base::Bind supports only up to 7 arguments.
518 Subscriber subscriber;
519 subscriber.origin = args.origin;
520 subscriber.persistent = args.persistent;
521 subscriber.notification_callback = args.notification_callback;
523 const WatcherKey key(args.entry_path, args.recursive);
524 const Watchers::const_iterator it = watchers_.find(key);
525 if (it != watchers_.end()) {
526 const bool exists = it->second.subscribers.find(args.origin) !=
527 it->second.subscribers.end();
528 OnAddWatcherInQueueCompleted(
529 args.token, args.entry_path, args.recursive, subscriber, args.callback,
530 exists ? base::File::FILE_ERROR_EXISTS : base::File::FILE_OK);
531 return AbortCallback();
534 const int request_id = request_manager_->CreateRequest(
535 ADD_WATCHER,
536 scoped_ptr<RequestManager::HandlerInterface>(new operations::AddWatcher(
537 event_router_, file_system_info_, args.entry_path, args.recursive,
538 base::Bind(&ProvidedFileSystem::OnAddWatcherInQueueCompleted,
539 weak_ptr_factory_.GetWeakPtr(), args.token,
540 args.entry_path, args.recursive, subscriber,
541 args.callback))));
543 if (!request_id) {
544 OnAddWatcherInQueueCompleted(args.token, args.entry_path, args.recursive,
545 subscriber, args.callback,
546 base::File::FILE_ERROR_SECURITY);
549 return AbortCallback();
552 AbortCallback ProvidedFileSystem::RemoveWatcherInQueue(
553 size_t token,
554 const GURL& origin,
555 const base::FilePath& entry_path,
556 bool recursive,
557 const storage::AsyncFileUtil::StatusCallback& callback) {
558 const WatcherKey key(entry_path, recursive);
559 const Watchers::iterator it = watchers_.find(key);
560 if (it == watchers_.end() ||
561 it->second.subscribers.find(origin) == it->second.subscribers.end()) {
562 OnRemoveWatcherInQueueCompleted(token, origin, key, callback,
563 false /* extension_response */,
564 base::File::FILE_ERROR_NOT_FOUND);
565 return AbortCallback();
568 // If there are other subscribers, then do not remove the observer, but simply
569 // return a success.
570 if (it->second.subscribers.size() > 1) {
571 OnRemoveWatcherInQueueCompleted(token, origin, key, callback,
572 false /* extension_response */,
573 base::File::FILE_OK);
574 return AbortCallback();
577 // Otherwise, emit an event, and remove the watcher.
578 request_manager_->CreateRequest(
579 REMOVE_WATCHER,
580 scoped_ptr<RequestManager::HandlerInterface>(
581 new operations::RemoveWatcher(
582 event_router_, file_system_info_, entry_path, recursive,
583 base::Bind(&ProvidedFileSystem::OnRemoveWatcherInQueueCompleted,
584 weak_ptr_factory_.GetWeakPtr(), token, origin, key,
585 callback, true /* extension_response */))));
587 return AbortCallback();
590 AbortCallback ProvidedFileSystem::NotifyInQueue(
591 scoped_ptr<NotifyInQueueArgs> args) {
592 const WatcherKey key(args->entry_path, args->recursive);
593 const auto& watcher_it = watchers_.find(key);
594 if (watcher_it == watchers_.end()) {
595 OnNotifyInQueueCompleted(args.Pass(), base::File::FILE_ERROR_NOT_FOUND);
596 return AbortCallback();
599 // The tag must be provided if and only if it's explicitly supported.
600 if (file_system_info_.supports_notify_tag() == args->tag.empty()) {
601 OnNotifyInQueueCompleted(args.Pass(),
602 base::File::FILE_ERROR_INVALID_OPERATION);
603 return AbortCallback();
606 // It's illegal to provide a tag which is not unique.
607 if (!args->tag.empty() && args->tag == watcher_it->second.last_tag) {
608 OnNotifyInQueueCompleted(args.Pass(),
609 base::File::FILE_ERROR_INVALID_OPERATION);
610 return AbortCallback();
613 // The object is owned by AutoUpdated, so the reference is valid as long as
614 // callbacks created with AutoUpdater::CreateCallback().
615 const ProvidedFileSystemObserver::Changes& changes_ref = *args->changes.get();
616 const storage::WatcherManager::ChangeType change_type = args->change_type;
618 scoped_refptr<AutoUpdater> auto_updater(
619 new AutoUpdater(base::Bind(&ProvidedFileSystem::OnNotifyInQueueCompleted,
620 weak_ptr_factory_.GetWeakPtr(),
621 base::Passed(&args), base::File::FILE_OK)));
623 // Call all notification callbacks (if any).
624 for (const auto& subscriber_it : watcher_it->second.subscribers) {
625 const storage::WatcherManager::NotificationCallback& notification_callback =
626 subscriber_it.second.notification_callback;
627 if (!notification_callback.is_null())
628 notification_callback.Run(change_type);
631 // Notify all observers.
632 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
633 observers_,
634 OnWatcherChanged(file_system_info_,
635 watcher_it->second,
636 change_type,
637 changes_ref,
638 auto_updater->CreateCallback()));
640 return AbortCallback();
643 base::WeakPtr<ProvidedFileSystemInterface> ProvidedFileSystem::GetWeakPtr() {
644 return weak_ptr_factory_.GetWeakPtr();
647 void ProvidedFileSystem::OnAddWatcherInQueueCompleted(
648 size_t token,
649 const base::FilePath& entry_path,
650 bool recursive,
651 const Subscriber& subscriber,
652 const storage::AsyncFileUtil::StatusCallback& callback,
653 base::File::Error result) {
654 if (result != base::File::FILE_OK) {
655 callback.Run(result);
656 watcher_queue_.Complete(token);
657 return;
660 const WatcherKey key(entry_path, recursive);
661 const Watchers::iterator it = watchers_.find(key);
662 if (it != watchers_.end()) {
663 callback.Run(base::File::FILE_OK);
664 watcher_queue_.Complete(token);
665 return;
668 Watcher* const watcher = &watchers_[key];
669 watcher->entry_path = entry_path;
670 watcher->recursive = recursive;
671 watcher->subscribers[subscriber.origin] = subscriber;
673 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
674 observers_,
675 OnWatcherListChanged(file_system_info_, watchers_));
677 callback.Run(base::File::FILE_OK);
678 watcher_queue_.Complete(token);
681 void ProvidedFileSystem::OnRemoveWatcherInQueueCompleted(
682 size_t token,
683 const GURL& origin,
684 const WatcherKey& key,
685 const storage::AsyncFileUtil::StatusCallback& callback,
686 bool extension_response,
687 base::File::Error result) {
688 if (!extension_response && result != base::File::FILE_OK) {
689 watcher_queue_.Complete(token);
690 callback.Run(result);
691 return;
694 // Even if the extension returns an error, the callback is called with base::
695 // File::FILE_OK.
696 const auto it = watchers_.find(key);
697 DCHECK(it != watchers_.end());
698 DCHECK(it->second.subscribers.find(origin) != it->second.subscribers.end());
700 it->second.subscribers.erase(origin);
702 FOR_EACH_OBSERVER(ProvidedFileSystemObserver, observers_,
703 OnWatcherListChanged(file_system_info_, watchers_));
705 // If there are no more subscribers, then remove the watcher.
706 if (!it->second.subscribers.size())
707 watchers_.erase(it);
709 callback.Run(base::File::FILE_OK);
710 watcher_queue_.Complete(token);
713 void ProvidedFileSystem::OnNotifyInQueueCompleted(
714 scoped_ptr<NotifyInQueueArgs> args,
715 base::File::Error result) {
716 if (result != base::File::FILE_OK) {
717 args->callback.Run(result);
718 watcher_queue_.Complete(args->token);
719 return;
722 // Check if the entry is still watched.
723 const WatcherKey key(args->entry_path, args->recursive);
724 const Watchers::iterator it = watchers_.find(key);
725 if (it == watchers_.end()) {
726 args->callback.Run(base::File::FILE_ERROR_NOT_FOUND);
727 watcher_queue_.Complete(args->token);
728 return;
731 it->second.last_tag = args->tag;
733 FOR_EACH_OBSERVER(ProvidedFileSystemObserver,
734 observers_,
735 OnWatcherTagUpdated(file_system_info_, it->second));
737 // If the watched entry is deleted, then remove the watcher.
738 if (args->change_type == storage::WatcherManager::DELETED) {
739 // Make a copy, since the |it| iterator will get invalidated on the last
740 // subscriber.
741 Subscribers subscribers = it->second.subscribers;
742 for (const auto& subscriber_it : subscribers) {
743 RemoveWatcher(subscriber_it.second.origin, args->entry_path,
744 args->recursive, base::Bind(&EmptyStatusCallback));
748 args->callback.Run(base::File::FILE_OK);
749 watcher_queue_.Complete(args->token);
752 void ProvidedFileSystem::OnOpenFileCompleted(const base::FilePath& file_path,
753 OpenFileMode mode,
754 const OpenFileCallback& callback,
755 int file_handle,
756 base::File::Error result) {
757 if (result != base::File::FILE_OK) {
758 callback.Run(file_handle, result);
759 return;
762 opened_files_[file_handle] = OpenedFile(file_path, mode);
763 callback.Run(file_handle, base::File::FILE_OK);
766 void ProvidedFileSystem::OnCloseFileCompleted(
767 int file_handle,
768 const storage::AsyncFileUtil::StatusCallback& callback,
769 base::File::Error result) {
770 // Closing files is final. Even if an error happened, we remove it from the
771 // list of opened files.
772 opened_files_.erase(file_handle);
773 callback.Run(result);
776 } // namespace file_system_provider
777 } // namespace chromeos