Index: chrome/browser/chromeos/extensions/file_browser_event_router.cc |
diff --git a/chrome/browser/chromeos/extensions/file_browser_event_router.cc b/chrome/browser/chromeos/extensions/file_browser_event_router.cc |
index 40b4cf76e1f816676aeec19160a1c293f1283425..91f3992c9c54c55d4c4c1ae5ce64bb987dbd5e34 100644 |
--- a/chrome/browser/chromeos/extensions/file_browser_event_router.cc |
+++ b/chrome/browser/chromeos/extensions/file_browser_event_router.cc |
@@ -228,6 +228,23 @@ void DirectoryExistsOnUIThread(const base::FilePath& directory_path, |
failure_callback)); |
}; |
+// Creates a base::FilePathWatcher and starts watching at |watch_path| with |
+// |callback|. Returns NULL on failure. |
+base::FilePathWatcher* CreateAndStartFilePathWatcher( |
+ const base::FilePath& watch_path, |
+ const base::FilePathWatcher::Callback& callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ DCHECK(!callback.is_null()); |
+ |
+ base::FilePathWatcher* watcher(new base::FilePathWatcher); |
+ if (!watcher->Watch(watch_path, false /* recursive */, callback)) { |
+ delete watcher; |
+ return NULL; |
+ } |
+ |
+ return watcher; |
+} |
+ |
} // namespace |
FileBrowserEventRouter::FileBrowserEventRouter( |
@@ -240,12 +257,9 @@ FileBrowserEventRouter::FileBrowserEventRouter( |
shift_pressed_(false) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- // Bind a weak reference back to |this| to avoid memory errors in case we |
- // shut down while a callback is in flight. |
file_watcher_callback_ = |
- base::Bind(&RelayFileWatcherCallbackToUIThread, |
- base::Bind(&FileBrowserEventRouter::HandleFileWatchNotification, |
- weak_factory_.GetWeakPtr())); |
+ base::Bind(&FileBrowserEventRouter::HandleFileWatchNotification, |
+ weak_factory_.GetWeakPtr()); |
// Listen for the Shift modifier's state changes. |
chromeos::SystemKeyEventListener* key_event_listener = |
@@ -324,11 +338,11 @@ void FileBrowserEventRouter::ObserveFileSystemEvents() { |
pref_change_registrar_->Add( |
prefs::kExternalStorageDisabled, |
base::Bind(&FileBrowserEventRouter::OnExternalStorageDisabledChanged, |
- base::Unretained(this))); |
+ weak_factory_.GetWeakPtr())); |
base::Closure callback = |
base::Bind(&FileBrowserEventRouter::OnFileBrowserPrefsChanged, |
- base::Unretained(this)); |
+ weak_factory_.GetWeakPtr()); |
pref_change_registrar_->Add(prefs::kDisableDriveOverCellular, callback); |
pref_change_registrar_->Add(prefs::kDisableDriveHostedFiles, callback); |
pref_change_registrar_->Add(prefs::kDisableDrive, callback); |
@@ -336,13 +350,14 @@ void FileBrowserEventRouter::ObserveFileSystemEvents() { |
} |
// File watch setup routines. |
-bool FileBrowserEventRouter::AddFileWatch( |
+void FileBrowserEventRouter::AddFileWatch( |
const base::FilePath& local_path, |
const base::FilePath& virtual_path, |
- const std::string& extension_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ const std::string& extension_id, |
+ const BoolCallback& callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(!callback.is_null()); |
- base::AutoLock lock(lock_); |
base::FilePath watch_path = local_path; |
bool is_remote_watch = false; |
// Tweak watch path for remote sources - we need to drop leading /special |
@@ -351,10 +366,7 @@ bool FileBrowserEventRouter::AddFileWatch( |
if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { |
watch_path = drive::util::ExtractDrivePath(watch_path); |
is_remote_watch = true; |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&FileBrowserEventRouter::HandleRemoteUpdateRequestOnUIThread, |
- this, true)); |
+ HandleRemoteUpdateRequestOnUIThread(true /* start */); |
} |
WatcherMap::iterator iter = file_watchers_.find(watch_path); |
@@ -363,33 +375,29 @@ bool FileBrowserEventRouter::AddFileWatch( |
watch(new FileWatcherExtensions(virtual_path, |
extension_id, |
is_remote_watch)); |
- |
- if (watch->Watch(watch_path, file_watcher_callback_)) |
- file_watchers_[watch_path] = watch.release(); |
- else |
- return false; |
+ watch->Watch(watch_path, |
+ file_watcher_callback_, |
+ callback); |
+ file_watchers_[watch_path] = watch.release(); |
} else { |
iter->second->AddExtension(extension_id); |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
+ base::Bind(callback, true)); |
} |
- return true; |
} |
void FileBrowserEventRouter::RemoveFileWatch( |
const base::FilePath& local_path, |
const std::string& extension_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- base::AutoLock lock(lock_); |
base::FilePath watch_path = local_path; |
// Tweak watch path for remote sources - we need to drop leading /special |
// directory from there in order to be able to pair these events with |
// their change notifications. |
if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { |
watch_path = drive::util::ExtractDrivePath(watch_path); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&FileBrowserEventRouter::HandleRemoteUpdateRequestOnUIThread, |
- this, false)); |
+ HandleRemoteUpdateRequestOnUIThread(false /* start */); |
} |
WatcherMap::iterator iter = file_watchers_.find(watch_path); |
if (iter == file_watchers_.end()) |
@@ -655,7 +663,6 @@ void FileBrowserEventRouter::HandleFileWatchNotification( |
const base::FilePath& local_path, bool got_error) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- base::AutoLock lock(lock_); |
WatcherMap::const_iterator iter = file_watchers_.find(local_path); |
if (iter == file_watchers_.end()) { |
return; |
@@ -901,21 +908,29 @@ void FileBrowserEventRouter::OnFormatCompleted( |
} |
FileBrowserEventRouter::FileWatcherExtensions::FileWatcherExtensions( |
- const base::FilePath& path, const std::string& extension_id, |
+ const base::FilePath& virtual_path, |
+ const std::string& extension_id, |
bool is_remote_file_system) |
- : ref_count_(0), |
- is_remote_file_system_(is_remote_file_system) { |
- if (!is_remote_file_system_) |
- file_watcher_.reset(new base::FilePathWatcher()); |
+ : file_watcher_(NULL), |
+ virtual_path_(virtual_path), |
+ ref_count_(0), |
+ is_remote_file_system_(is_remote_file_system), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- virtual_path_ = path; |
AddExtension(extension_id); |
} |
-FileBrowserEventRouter::FileWatcherExtensions::~FileWatcherExtensions() {} |
+FileBrowserEventRouter::FileWatcherExtensions::~FileWatcherExtensions() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, file_watcher_); |
+} |
void FileBrowserEventRouter::FileWatcherExtensions::AddExtension( |
const std::string& extension_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); |
if (it != extensions_.end()) { |
it->second++; |
@@ -928,6 +943,8 @@ void FileBrowserEventRouter::FileWatcherExtensions::AddExtension( |
void FileBrowserEventRouter::FileWatcherExtensions::RemoveExtension( |
const std::string& extension_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); |
if (it != extensions_.end()) { |
@@ -949,16 +966,19 @@ void FileBrowserEventRouter::FileWatcherExtensions::RemoveExtension( |
const FileBrowserEventRouter::ExtensionUsageRegistry& |
FileBrowserEventRouter::FileWatcherExtensions::GetExtensions() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
return extensions_; |
} |
unsigned int |
FileBrowserEventRouter::FileWatcherExtensions::GetRefCount() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
return ref_count_; |
} |
const base::FilePath& |
FileBrowserEventRouter::FileWatcherExtensions::GetVirtualPath() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
return virtual_path_; |
} |
@@ -970,11 +990,44 @@ FileBrowserEventRouter::GetRemoteFileSystem() const { |
return (system_service ? system_service->file_system() : NULL); |
} |
-bool FileBrowserEventRouter::FileWatcherExtensions::Watch( |
- const base::FilePath& path, |
- const base::FilePathWatcher::Callback& callback) { |
- if (is_remote_file_system_) |
- return true; |
+void FileBrowserEventRouter::FileWatcherExtensions::Watch( |
+ const base::FilePath& local_path, |
+ const base::FilePathWatcher::Callback& file_watcher_callback, |
+ const BoolCallback& callback) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(!callback.is_null()); |
+ DCHECK(!file_watcher_); |
- return file_watcher_->Watch(path, false, callback); |
+ local_path_ = local_path; // For error message in RemoveExtension(). |
+ |
+ if (is_remote_file_system_) { |
+ base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
+ base::Bind(callback, true)); |
+ return; |
+ } |
+ |
+ BrowserThread::PostTaskAndReplyWithResult( |
+ BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&CreateAndStartFilePathWatcher, |
+ local_path, |
+ base::Bind(&RelayFileWatcherCallbackToUIThread, |
+ file_watcher_callback)), |
+ base::Bind( |
+ &FileBrowserEventRouter::FileWatcherExtensions::OnWatcherStarted, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ callback)); |
+} |
+ |
+void FileBrowserEventRouter::FileWatcherExtensions::OnWatcherStarted( |
+ const BoolCallback& callback, |
+ base::FilePathWatcher* file_watcher) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ if (file_watcher) { |
+ file_watcher_ = file_watcher; |
+ callback.Run(true); |
+ } else { |
+ callback.Run(false); |
+ } |
} |