11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/api/file_system/entry_watcher_service.h" 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/thread_task_runner_handle.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/extensions/extension_util.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/profiles/profile.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/extensions/api/file_system.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/keyed_service/content/browser_context_dependency_manager.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_context.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_thread.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/storage_partition.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/event_router.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_context.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace extensions { 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Default implementation for dispatching an event. Can be replaced for unit 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// tests by EntryWatcherService::SetDispatchEventImplForTesting(). 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DispatchEventImpl(EventRouter* event_router, 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<Event> event) { 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event_router->DispatchEventToExtension(extension_id, event.Pass()); 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Default implementation for acquiring a file system context for a specific 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |extension_id| and |context|. 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistorage::FileSystemContext* GetFileSystemContextImpl( 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::BrowserContext* context) { 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL site = util::GetSiteForExtensionId(extension_id, context); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return content::BrowserContext::GetStoragePartitionForSite(context, site) 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ->GetFileSystemContext(); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryWatcherService::EntryWatcherService(content::BrowserContext* context) 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : context_(context), 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dispatch_event_impl_( 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&DispatchEventImpl, EventRouter::Get(context))), 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci get_file_system_context_impl_(base::Bind(&GetFileSystemContextImpl)), 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci observing_(this), 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_(this) { 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mtomasz): Restore persistent watchers. 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryWatcherService::~EntryWatcherService() { 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::SetDispatchEventImplForTesting( 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const DispatchEventImplCallback& callback) { 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dispatch_event_impl_ = callback; 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::SetGetFileSystemContextImplForTesting( 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GetFileSystemContextImplCallback& callback) { 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci get_file_system_context_impl_ = callback; 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::WatchDirectory( 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::FileSystemURL& url, 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool recursive, 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::WatcherManager::StatusCallback& callback) { 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mtomasz): Add support for recursive watchers. 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (recursive) { 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadTaskRunnerHandle::Get()->PostTask( 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION)); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::FileSystemContext* const context = 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci get_file_system_context_impl_.Run(extension_id, context_); 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(context); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::WatcherManager* const watcher_manager = 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context->GetWatcherManager(url.type()); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!watcher_manager) { 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Post a task instead of calling the callback directly, since the caller 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // may expect the callback to be called asynchronously. 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadTaskRunnerHandle::Get()->PostTask( 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION)); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Passing a pointer to WatcherManager is safe, since the pointer is required 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to be valid until shutdown. 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context->default_file_task_runner()->PostNonNestableTask( 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&storage::WatcherManager::WatchDirectory, 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(watcher_manager), // Outlives the service. 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci recursive, 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&EntryWatcherService::OnWatchDirectoryCompleted, 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr(), 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watcher_manager, // Outlives the service. 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_id, 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci recursive, 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback))); 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::UnwatchEntry( 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::FileSystemURL& url, 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::WatcherManager::StatusCallback& callback) { 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::FileSystemContext* const context = 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci get_file_system_context_impl_.Run(extension_id, context_); 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(context); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::WatcherManager* const watcher_manager = 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context->GetWatcherManager(url.type()); 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!watcher_manager) { 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadTaskRunnerHandle::Get()->PostTask( 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION)); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Passing a pointer to WatcherManager is safe, since the pointer is required 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to be valid until shutdown. 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context->default_file_task_runner()->PostNonNestableTask( 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&storage::WatcherManager::UnwatchEntry, 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Unretained(watcher_manager), // Outlives the service. 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&EntryWatcherService::OnUnwatchEntryCompleted, 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_ptr_factory_.GetWeakPtr(), 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_id, 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci url, 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback))); 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::vector<storage::FileSystemURL> EntryWatcherService::GetWatchedEntries( 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id) { 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<storage::FileSystemURL> result; 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (WatcherMap::const_iterator it = watchers_.begin(); it != watchers_.end(); 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it) { 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::map<std::string, EntryWatcher>::const_iterator watcher_it = 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->second.find(extension_id); 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (watcher_it != it->second.end()) 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result.push_back(watcher_it->second.url); 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return result; 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::OnEntryChanged(const storage::FileSystemURL& url) { 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const WatcherMap::const_iterator it = watchers_.find(url); 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(it != watchers_.end()); 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::map<std::string, EntryWatcher>::const_iterator watcher_it = 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->second.begin(); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watcher_it != it->second.end(); 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++watcher_it) { 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id = watcher_it->first; 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api::file_system::EntryChangedEvent event; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dispatch_event_impl_.Run( 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_id, 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci make_scoped_ptr( 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new Event(api::file_system::OnEntryChanged::kEventName, 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api::file_system::OnEntryChanged::Create(event)))); 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::OnEntryRemoved(const storage::FileSystemURL& url) { 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci WatcherMap::const_iterator it = watchers_.find(url); 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(it != watchers_.end()); 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (std::map<std::string, EntryWatcher>::const_iterator watcher_it = 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it->second.begin(); 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watcher_it != it->second.end(); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++watcher_it) { 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id = watcher_it->first; 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api::file_system::EntryRemovedEvent event; 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dispatch_event_impl_.Run( 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_id, 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci make_scoped_ptr( 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new Event(api::file_system::OnEntryRemoved::kEventName, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci api::file_system::OnEntryRemoved::Create(event)))); 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::OnWatchDirectoryCompleted( 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::WatcherManager* watcher_manager, 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::FileSystemURL& url, 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool recursive, 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::WatcherManager::StatusCallback& callback, 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::File::Error result) { 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != base::File::FILE_OK) { 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(result); 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci storage::FileSystemContext* const context = 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci get_file_system_context_impl_.Run(extension_id, context_); 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(context); 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Observe the manager if not observed yet. 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!observing_.IsObserving(watcher_manager)) 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci observing_.Add(watcher_manager); 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watchers_[url][extension_id] = 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryWatcher(url, true /* directory */, recursive); 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mtomasz): Save in preferences. 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(base::File::FILE_OK); 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid EntryWatcherService::OnUnwatchEntryCompleted( 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string& extension_id, 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::FileSystemURL& url, 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::WatcherManager::StatusCallback& callback, 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::File::Error result) { 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != base::File::FILE_OK) { 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(result); 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (watchers_[url].erase(extension_id) == 0) { 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(base::File::FILE_ERROR_NOT_FOUND); 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (watchers_[url].empty()) 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci watchers_.erase(url); 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(mtomasz): Save in preferences. 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(base::File::FILE_OK); 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryWatcherService::EntryWatcher::EntryWatcher() 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : directory(false), recursive(false) { 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryWatcherService::EntryWatcher::EntryWatcher( 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const storage::FileSystemURL& url, 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool directory, 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool recursive) 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : url(url), directory(directory), recursive(recursive) { 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryWatcherService::EntryWatcher::~EntryWatcher() { 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace extensions 254