OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/file_browser_event_router.h" | 5 #include "chrome/browser/chromeos/extensions/file_browser_event_router.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
222 | 222 |
223 content::BrowserThread::PostBlockingPoolTask( | 223 content::BrowserThread::PostBlockingPoolTask( |
224 FROM_HERE, | 224 FROM_HERE, |
225 base::Bind(&DirectoryExistsOnBlockingPool, | 225 base::Bind(&DirectoryExistsOnBlockingPool, |
226 directory_path, | 226 directory_path, |
227 success_callback, | 227 success_callback, |
228 failure_callback)); | 228 failure_callback)); |
229 }; | 229 }; |
230 | 230 |
| 231 // Creates a base::FilePathWatcher and starts watching at |watch_path| with |
| 232 // |callback|. Returns NULL on failure. |
| 233 base::FilePathWatcher* CreateAndStartFilePathWatcher( |
| 234 const base::FilePath& watch_path, |
| 235 const base::FilePathWatcher::Callback& callback) { |
| 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 237 DCHECK(!callback.is_null()); |
| 238 |
| 239 base::FilePathWatcher* watcher(new base::FilePathWatcher); |
| 240 if (!watcher->Watch(watch_path, false /* recursive */, callback)) { |
| 241 delete watcher; |
| 242 return NULL; |
| 243 } |
| 244 |
| 245 return watcher; |
| 246 } |
| 247 |
231 } // namespace | 248 } // namespace |
232 | 249 |
233 FileBrowserEventRouter::FileBrowserEventRouter( | 250 FileBrowserEventRouter::FileBrowserEventRouter( |
234 Profile* profile) | 251 Profile* profile) |
235 : weak_factory_(this), | 252 : weak_factory_(this), |
236 notifications_(new FileBrowserNotifications(profile)), | 253 notifications_(new FileBrowserNotifications(profile)), |
237 pref_change_registrar_(new PrefChangeRegistrar), | 254 pref_change_registrar_(new PrefChangeRegistrar), |
238 profile_(profile), | 255 profile_(profile), |
239 num_remote_update_requests_(0), | 256 num_remote_update_requests_(0), |
240 shift_pressed_(false) { | 257 shift_pressed_(false) { |
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
242 | 259 |
243 // Bind a weak reference back to |this| to avoid memory errors in case we | |
244 // shut down while a callback is in flight. | |
245 file_watcher_callback_ = | 260 file_watcher_callback_ = |
246 base::Bind(&RelayFileWatcherCallbackToUIThread, | 261 base::Bind(&FileBrowserEventRouter::HandleFileWatchNotification, |
247 base::Bind(&FileBrowserEventRouter::HandleFileWatchNotification, | 262 weak_factory_.GetWeakPtr()); |
248 weak_factory_.GetWeakPtr())); | |
249 | 263 |
250 // Listen for the Shift modifier's state changes. | 264 // Listen for the Shift modifier's state changes. |
251 chromeos::SystemKeyEventListener* key_event_listener = | 265 chromeos::SystemKeyEventListener* key_event_listener = |
252 chromeos::SystemKeyEventListener::GetInstance(); | 266 chromeos::SystemKeyEventListener::GetInstance(); |
253 if (key_event_listener) | 267 if (key_event_listener) |
254 key_event_listener->AddModifiersObserver(this); | 268 key_event_listener->AddModifiersObserver(this); |
255 } | 269 } |
256 | 270 |
257 FileBrowserEventRouter::~FileBrowserEventRouter() { | 271 FileBrowserEventRouter::~FileBrowserEventRouter() { |
258 } | 272 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 chromeos::ConnectivityStateHelper::Get()-> | 331 chromeos::ConnectivityStateHelper::Get()-> |
318 AddNetworkManagerObserver(this); | 332 AddNetworkManagerObserver(this); |
319 } | 333 } |
320 suspend_state_delegate_.reset(new SuspendStateDelegateImpl()); | 334 suspend_state_delegate_.reset(new SuspendStateDelegateImpl()); |
321 | 335 |
322 pref_change_registrar_->Init(profile_->GetPrefs()); | 336 pref_change_registrar_->Init(profile_->GetPrefs()); |
323 | 337 |
324 pref_change_registrar_->Add( | 338 pref_change_registrar_->Add( |
325 prefs::kExternalStorageDisabled, | 339 prefs::kExternalStorageDisabled, |
326 base::Bind(&FileBrowserEventRouter::OnExternalStorageDisabledChanged, | 340 base::Bind(&FileBrowserEventRouter::OnExternalStorageDisabledChanged, |
327 base::Unretained(this))); | 341 weak_factory_.GetWeakPtr())); |
328 | 342 |
329 base::Closure callback = | 343 base::Closure callback = |
330 base::Bind(&FileBrowserEventRouter::OnFileBrowserPrefsChanged, | 344 base::Bind(&FileBrowserEventRouter::OnFileBrowserPrefsChanged, |
331 base::Unretained(this)); | 345 weak_factory_.GetWeakPtr()); |
332 pref_change_registrar_->Add(prefs::kDisableDriveOverCellular, callback); | 346 pref_change_registrar_->Add(prefs::kDisableDriveOverCellular, callback); |
333 pref_change_registrar_->Add(prefs::kDisableDriveHostedFiles, callback); | 347 pref_change_registrar_->Add(prefs::kDisableDriveHostedFiles, callback); |
334 pref_change_registrar_->Add(prefs::kDisableDrive, callback); | 348 pref_change_registrar_->Add(prefs::kDisableDrive, callback); |
335 pref_change_registrar_->Add(prefs::kUse24HourClock, callback); | 349 pref_change_registrar_->Add(prefs::kUse24HourClock, callback); |
336 } | 350 } |
337 | 351 |
338 // File watch setup routines. | 352 // File watch setup routines. |
339 bool FileBrowserEventRouter::AddFileWatch( | 353 void FileBrowserEventRouter::AddFileWatch( |
340 const base::FilePath& local_path, | 354 const base::FilePath& local_path, |
341 const base::FilePath& virtual_path, | 355 const base::FilePath& virtual_path, |
342 const std::string& extension_id) { | 356 const std::string& extension_id, |
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 357 const BoolCallback& callback) { |
| 358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 359 DCHECK(!callback.is_null()); |
344 | 360 |
345 base::AutoLock lock(lock_); | |
346 base::FilePath watch_path = local_path; | 361 base::FilePath watch_path = local_path; |
347 bool is_remote_watch = false; | 362 bool is_remote_watch = false; |
348 // Tweak watch path for remote sources - we need to drop leading /special | 363 // Tweak watch path for remote sources - we need to drop leading /special |
349 // directory from there in order to be able to pair these events with | 364 // directory from there in order to be able to pair these events with |
350 // their change notifications. | 365 // their change notifications. |
351 if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { | 366 if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { |
352 watch_path = drive::util::ExtractDrivePath(watch_path); | 367 watch_path = drive::util::ExtractDrivePath(watch_path); |
353 is_remote_watch = true; | 368 is_remote_watch = true; |
354 BrowserThread::PostTask( | 369 HandleRemoteUpdateRequestOnUIThread(true /* start */); |
355 BrowserThread::UI, FROM_HERE, | |
356 base::Bind(&FileBrowserEventRouter::HandleRemoteUpdateRequestOnUIThread, | |
357 this, true)); | |
358 } | 370 } |
359 | 371 |
360 WatcherMap::iterator iter = file_watchers_.find(watch_path); | 372 WatcherMap::iterator iter = file_watchers_.find(watch_path); |
361 if (iter == file_watchers_.end()) { | 373 if (iter == file_watchers_.end()) { |
362 scoped_ptr<FileWatcherExtensions> | 374 scoped_ptr<FileWatcherExtensions> |
363 watch(new FileWatcherExtensions(virtual_path, | 375 watch(new FileWatcherExtensions(virtual_path, |
364 extension_id, | 376 extension_id, |
365 is_remote_watch)); | 377 is_remote_watch)); |
366 | 378 watch->Watch(watch_path, |
367 if (watch->Watch(watch_path, file_watcher_callback_)) | 379 file_watcher_callback_, |
368 file_watchers_[watch_path] = watch.release(); | 380 callback); |
369 else | 381 file_watchers_[watch_path] = watch.release(); |
370 return false; | |
371 } else { | 382 } else { |
372 iter->second->AddExtension(extension_id); | 383 iter->second->AddExtension(extension_id); |
| 384 base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
| 385 base::Bind(callback, true)); |
373 } | 386 } |
374 return true; | |
375 } | 387 } |
376 | 388 |
377 void FileBrowserEventRouter::RemoveFileWatch( | 389 void FileBrowserEventRouter::RemoveFileWatch( |
378 const base::FilePath& local_path, | 390 const base::FilePath& local_path, |
379 const std::string& extension_id) { | 391 const std::string& extension_id) { |
380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
381 | 393 |
382 base::AutoLock lock(lock_); | |
383 base::FilePath watch_path = local_path; | 394 base::FilePath watch_path = local_path; |
384 // Tweak watch path for remote sources - we need to drop leading /special | 395 // Tweak watch path for remote sources - we need to drop leading /special |
385 // directory from there in order to be able to pair these events with | 396 // directory from there in order to be able to pair these events with |
386 // their change notifications. | 397 // their change notifications. |
387 if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { | 398 if (drive::util::GetSpecialRemoteRootPath().IsParent(watch_path)) { |
388 watch_path = drive::util::ExtractDrivePath(watch_path); | 399 watch_path = drive::util::ExtractDrivePath(watch_path); |
389 BrowserThread::PostTask( | 400 HandleRemoteUpdateRequestOnUIThread(false /* start */); |
390 BrowserThread::UI, FROM_HERE, | |
391 base::Bind(&FileBrowserEventRouter::HandleRemoteUpdateRequestOnUIThread, | |
392 this, false)); | |
393 } | 401 } |
394 WatcherMap::iterator iter = file_watchers_.find(watch_path); | 402 WatcherMap::iterator iter = file_watchers_.find(watch_path); |
395 if (iter == file_watchers_.end()) | 403 if (iter == file_watchers_.end()) |
396 return; | 404 return; |
397 // Remove the renderer process for this watch. | 405 // Remove the renderer process for this watch. |
398 iter->second->RemoveExtension(extension_id); | 406 iter->second->RemoveExtension(extension_id); |
399 if (iter->second->GetRefCount() == 0) { | 407 if (iter->second->GetRefCount() == 0) { |
400 delete iter->second; | 408 delete iter->second; |
401 file_watchers_.erase(iter); | 409 file_watchers_.erase(iter); |
402 } | 410 } |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged, | 656 extensions::event_names::kOnFileBrowserDriveConnectionStatusChanged, |
649 scoped_ptr<ListValue>(new ListValue()))); | 657 scoped_ptr<ListValue>(new ListValue()))); |
650 extensions::ExtensionSystem::Get(profile_)->event_router()-> | 658 extensions::ExtensionSystem::Get(profile_)->event_router()-> |
651 BroadcastEvent(event.Pass()); | 659 BroadcastEvent(event.Pass()); |
652 } | 660 } |
653 | 661 |
654 void FileBrowserEventRouter::HandleFileWatchNotification( | 662 void FileBrowserEventRouter::HandleFileWatchNotification( |
655 const base::FilePath& local_path, bool got_error) { | 663 const base::FilePath& local_path, bool got_error) { |
656 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 664 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
657 | 665 |
658 base::AutoLock lock(lock_); | |
659 WatcherMap::const_iterator iter = file_watchers_.find(local_path); | 666 WatcherMap::const_iterator iter = file_watchers_.find(local_path); |
660 if (iter == file_watchers_.end()) { | 667 if (iter == file_watchers_.end()) { |
661 return; | 668 return; |
662 } | 669 } |
663 DispatchDirectoryChangeEvent(iter->second->GetVirtualPath(), got_error, | 670 DispatchDirectoryChangeEvent(iter->second->GetVirtualPath(), got_error, |
664 iter->second->GetExtensions()); | 671 iter->second->GetExtensions()); |
665 } | 672 } |
666 | 673 |
667 void FileBrowserEventRouter::DispatchDirectoryChangeEvent( | 674 void FileBrowserEventRouter::DispatchDirectoryChangeEvent( |
668 const base::FilePath& virtual_path, | 675 const base::FilePath& virtual_path, |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 chromeos::MOUNT_TYPE_DEVICE); | 901 chromeos::MOUNT_TYPE_DEVICE); |
895 } else { | 902 } else { |
896 notifications_->HideNotification(FileBrowserNotifications::FORMAT_START, | 903 notifications_->HideNotification(FileBrowserNotifications::FORMAT_START, |
897 device_path); | 904 device_path); |
898 notifications_->ShowNotification(FileBrowserNotifications::FORMAT_FAIL, | 905 notifications_->ShowNotification(FileBrowserNotifications::FORMAT_FAIL, |
899 device_path); | 906 device_path); |
900 } | 907 } |
901 } | 908 } |
902 | 909 |
903 FileBrowserEventRouter::FileWatcherExtensions::FileWatcherExtensions( | 910 FileBrowserEventRouter::FileWatcherExtensions::FileWatcherExtensions( |
904 const base::FilePath& path, const std::string& extension_id, | 911 const base::FilePath& virtual_path, |
| 912 const std::string& extension_id, |
905 bool is_remote_file_system) | 913 bool is_remote_file_system) |
906 : ref_count_(0), | 914 : file_watcher_(NULL), |
907 is_remote_file_system_(is_remote_file_system) { | 915 virtual_path_(virtual_path), |
908 if (!is_remote_file_system_) | 916 ref_count_(0), |
909 file_watcher_.reset(new base::FilePathWatcher()); | 917 is_remote_file_system_(is_remote_file_system), |
| 918 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 919 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
910 | 920 |
911 virtual_path_ = path; | |
912 AddExtension(extension_id); | 921 AddExtension(extension_id); |
913 } | 922 } |
914 | 923 |
915 FileBrowserEventRouter::FileWatcherExtensions::~FileWatcherExtensions() {} | 924 FileBrowserEventRouter::FileWatcherExtensions::~FileWatcherExtensions() { |
| 925 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 926 |
| 927 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, file_watcher_); |
| 928 } |
916 | 929 |
917 void FileBrowserEventRouter::FileWatcherExtensions::AddExtension( | 930 void FileBrowserEventRouter::FileWatcherExtensions::AddExtension( |
918 const std::string& extension_id) { | 931 const std::string& extension_id) { |
| 932 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 933 |
919 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); | 934 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); |
920 if (it != extensions_.end()) { | 935 if (it != extensions_.end()) { |
921 it->second++; | 936 it->second++; |
922 } else { | 937 } else { |
923 extensions_.insert(ExtensionUsageRegistry::value_type(extension_id, 1)); | 938 extensions_.insert(ExtensionUsageRegistry::value_type(extension_id, 1)); |
924 } | 939 } |
925 | 940 |
926 ref_count_++; | 941 ref_count_++; |
927 } | 942 } |
928 | 943 |
929 void FileBrowserEventRouter::FileWatcherExtensions::RemoveExtension( | 944 void FileBrowserEventRouter::FileWatcherExtensions::RemoveExtension( |
930 const std::string& extension_id) { | 945 const std::string& extension_id) { |
| 946 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 947 |
931 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); | 948 ExtensionUsageRegistry::iterator it = extensions_.find(extension_id); |
932 | 949 |
933 if (it != extensions_.end()) { | 950 if (it != extensions_.end()) { |
934 // If entry found - decrease it's count and remove if necessary | 951 // If entry found - decrease it's count and remove if necessary |
935 if (0 == it->second--) { | 952 if (0 == it->second--) { |
936 extensions_.erase(it); | 953 extensions_.erase(it); |
937 } | 954 } |
938 | 955 |
939 ref_count_--; | 956 ref_count_--; |
940 } else { | 957 } else { |
941 // Might be reference counting problem - e.g. if some component of | 958 // Might be reference counting problem - e.g. if some component of |
942 // extension subscribes/unsubscribes correctly, but other component | 959 // extension subscribes/unsubscribes correctly, but other component |
943 // only unsubscribes, developer of first one might receive this message | 960 // only unsubscribes, developer of first one might receive this message |
944 LOG(FATAL) << " Extension [" << extension_id | 961 LOG(FATAL) << " Extension [" << extension_id |
945 << "] tries to unsubscribe from folder [" << local_path_.value() | 962 << "] tries to unsubscribe from folder [" << local_path_.value() |
946 << "] it isn't subscribed"; | 963 << "] it isn't subscribed"; |
947 } | 964 } |
948 } | 965 } |
949 | 966 |
950 const FileBrowserEventRouter::ExtensionUsageRegistry& | 967 const FileBrowserEventRouter::ExtensionUsageRegistry& |
951 FileBrowserEventRouter::FileWatcherExtensions::GetExtensions() const { | 968 FileBrowserEventRouter::FileWatcherExtensions::GetExtensions() const { |
| 969 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
952 return extensions_; | 970 return extensions_; |
953 } | 971 } |
954 | 972 |
955 unsigned int | 973 unsigned int |
956 FileBrowserEventRouter::FileWatcherExtensions::GetRefCount() const { | 974 FileBrowserEventRouter::FileWatcherExtensions::GetRefCount() const { |
| 975 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
957 return ref_count_; | 976 return ref_count_; |
958 } | 977 } |
959 | 978 |
960 const base::FilePath& | 979 const base::FilePath& |
961 FileBrowserEventRouter::FileWatcherExtensions::GetVirtualPath() const { | 980 FileBrowserEventRouter::FileWatcherExtensions::GetVirtualPath() const { |
| 981 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
962 return virtual_path_; | 982 return virtual_path_; |
963 } | 983 } |
964 | 984 |
965 drive::DriveFileSystemInterface* | 985 drive::DriveFileSystemInterface* |
966 FileBrowserEventRouter::GetRemoteFileSystem() const { | 986 FileBrowserEventRouter::GetRemoteFileSystem() const { |
967 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 987 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
968 DriveSystemService* system_service = | 988 DriveSystemService* system_service = |
969 DriveSystemServiceFactory::GetForProfile(profile_); | 989 DriveSystemServiceFactory::GetForProfile(profile_); |
970 return (system_service ? system_service->file_system() : NULL); | 990 return (system_service ? system_service->file_system() : NULL); |
971 } | 991 } |
972 | 992 |
973 bool FileBrowserEventRouter::FileWatcherExtensions::Watch( | 993 void FileBrowserEventRouter::FileWatcherExtensions::Watch( |
974 const base::FilePath& path, | 994 const base::FilePath& local_path, |
975 const base::FilePathWatcher::Callback& callback) { | 995 const base::FilePathWatcher::Callback& file_watcher_callback, |
976 if (is_remote_file_system_) | 996 const BoolCallback& callback) { |
977 return true; | 997 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 998 DCHECK(!callback.is_null()); |
| 999 DCHECK(!file_watcher_); |
978 | 1000 |
979 return file_watcher_->Watch(path, false, callback); | 1001 local_path_ = local_path; // For error message in RemoveExtension(). |
| 1002 |
| 1003 if (is_remote_file_system_) { |
| 1004 base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
| 1005 base::Bind(callback, true)); |
| 1006 return; |
| 1007 } |
| 1008 |
| 1009 BrowserThread::PostTaskAndReplyWithResult( |
| 1010 BrowserThread::FILE, |
| 1011 FROM_HERE, |
| 1012 base::Bind(&CreateAndStartFilePathWatcher, |
| 1013 local_path, |
| 1014 base::Bind(&RelayFileWatcherCallbackToUIThread, |
| 1015 file_watcher_callback)), |
| 1016 base::Bind( |
| 1017 &FileBrowserEventRouter::FileWatcherExtensions::OnWatcherStarted, |
| 1018 weak_ptr_factory_.GetWeakPtr(), |
| 1019 callback)); |
980 } | 1020 } |
| 1021 |
| 1022 void FileBrowserEventRouter::FileWatcherExtensions::OnWatcherStarted( |
| 1023 const BoolCallback& callback, |
| 1024 base::FilePathWatcher* file_watcher) { |
| 1025 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1026 |
| 1027 if (file_watcher) { |
| 1028 file_watcher_ = file_watcher; |
| 1029 callback.Run(true); |
| 1030 } else { |
| 1031 callback.Run(false); |
| 1032 } |
| 1033 } |
OLD | NEW |