From 19e01a995f9e487e45f580b27f064835b4669673 Mon Sep 17 00:00:00 2001 From: "krb@chromium.org" Date: Tue, 29 Apr 2014 17:42:58 +0000 Subject: [PATCH] Add notification for media changed, and notify volume mount watcher when it occurs. BUG=154632 Review URL: https://codereview.chromium.org/231063002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266914 0039d316-1c4b-4281-b951-d872f2087c98 --- .../storage_monitor/storage_monitor_win.cc | 31 +++++++++++++++++++ .../storage_monitor/storage_monitor_win.h | 6 ++++ .../volume_mount_watcher_win.cc | 25 +++++++++++++++ .../volume_mount_watcher_win.h | 3 ++ 4 files changed, 65 insertions(+) diff --git a/components/storage_monitor/storage_monitor_win.cc b/components/storage_monitor/storage_monitor_win.cc index fb721bb3284826..95a6911552d83a 100644 --- a/components/storage_monitor/storage_monitor_win.cc +++ b/components/storage_monitor/storage_monitor_win.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "base/win/wrapped_window_proc.h" #include "components/storage_monitor/portable_device_watcher_win.h" @@ -14,6 +15,8 @@ #include "components/storage_monitor/storage_info.h" #include "components/storage_monitor/volume_mount_watcher_win.h" +#define WM_USER_MEDIACHANGED (WM_USER + 5) + // StorageMonitorWin ------------------------------------------------------- namespace storage_monitor { @@ -24,6 +27,7 @@ StorageMonitorWin::StorageMonitorWin( : window_class_(0), instance_(NULL), window_(NULL), + shell_change_notify_id_(0), volume_mount_watcher_(volume_mount_watcher), portable_device_watcher_(portable_device_watcher) { DCHECK(volume_mount_watcher_); @@ -33,6 +37,8 @@ StorageMonitorWin::StorageMonitorWin( } StorageMonitorWin::~StorageMonitorWin() { + if (shell_change_notify_id_) + SHChangeNotifyDeregister(shell_change_notify_id_); volume_mount_watcher_->SetNotifications(NULL); portable_device_watcher_->SetNotifications(NULL); @@ -59,6 +65,7 @@ void StorageMonitorWin::Init() { SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast(this)); volume_mount_watcher_->Init(); portable_device_watcher_->Init(window_); + MediaChangeNotificationRegister(); } bool StorageMonitorWin::GetStorageInfoForPath(const base::FilePath& path, @@ -138,6 +145,9 @@ LRESULT CALLBACK StorageMonitorWin::WndProc(HWND hwnd, UINT message, case WM_DEVICECHANGE: OnDeviceChange(static_cast(wparam), lparam); return TRUE; + case WM_USER_MEDIACHANGED: + OnMediaChange(wparam, lparam); + return TRUE; default: break; } @@ -145,6 +155,22 @@ LRESULT CALLBACK StorageMonitorWin::WndProc(HWND hwnd, UINT message, return ::DefWindowProc(hwnd, message, wparam, lparam); } +void StorageMonitorWin::MediaChangeNotificationRegister() { + LPITEMIDLIST id_list; + if (SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &id_list) == NOERROR) { + SHChangeNotifyEntry notify_entry; + notify_entry.pidl = id_list; + notify_entry.fRecursive = TRUE; + shell_change_notify_id_ = SHChangeNotifyRegister( + window_, SHCNRF_ShellLevel, SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED, + WM_USER_MEDIACHANGED, 1, ¬ify_entry); + if (!shell_change_notify_id_) + DVLOG(1) << "SHChangeNotifyRegister FAILED"; + } else { + DVLOG(1) << "SHGetSpecialFolderLocation FAILED"; + } +} + bool StorageMonitorWin::GetDeviceInfo(const base::FilePath& device_path, StorageInfo* info) const { DCHECK(info); @@ -156,10 +182,15 @@ bool StorageMonitorWin::GetDeviceInfo(const base::FilePath& device_path, } void StorageMonitorWin::OnDeviceChange(UINT event_type, LPARAM data) { + DVLOG(1) << "OnDeviceChange " << event_type << " " << data; volume_mount_watcher_->OnWindowMessage(event_type, data); portable_device_watcher_->OnWindowMessage(event_type, data); } +void StorageMonitorWin::OnMediaChange(WPARAM wparam, LPARAM lparam) { + volume_mount_watcher_->OnMediaChange(wparam, lparam); +} + StorageMonitor* StorageMonitor::CreateInternal() { return new StorageMonitorWin(new VolumeMountWatcherWin(), new PortableDeviceWatcherWin()); diff --git a/components/storage_monitor/storage_monitor_win.h b/components/storage_monitor/storage_monitor_win.h index f59b3c3a9f1647..65681b4dbf514d 100644 --- a/components/storage_monitor/storage_monitor_win.h +++ b/components/storage_monitor/storage_monitor_win.h @@ -50,6 +50,8 @@ class StorageMonitorWin : public StorageMonitor { class PortableDeviceNotifications; friend class TestStorageMonitorWin; + void MediaChangeNotificationRegister(); + // Gets the removable storage information given a |device_path|. On success, // returns true and fills in |info|. bool GetDeviceInfo(const base::FilePath& device_path, @@ -62,6 +64,7 @@ class StorageMonitorWin : public StorageMonitor { LPARAM lparam); void OnDeviceChange(UINT event_type, LPARAM data); + void OnMediaChange(WPARAM wparam, LPARAM lparam); // The window class of |window_|. ATOM window_class_; @@ -70,6 +73,9 @@ class StorageMonitorWin : public StorageMonitor { HMODULE instance_; HWND window_; + // The handle of a registration for shell notifications. + ULONG shell_change_notify_id_; + // The volume mount point watcher, used to manage the mounted devices. scoped_ptr volume_mount_watcher_; diff --git a/components/storage_monitor/volume_mount_watcher_win.cc b/components/storage_monitor/volume_mount_watcher_win.cc index 5dc2013782e9b4..e38070e37871e5 100644 --- a/components/storage_monitor/volume_mount_watcher_win.cc +++ b/components/storage_monitor/volume_mount_watcher_win.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include "base/bind_helpers.h" @@ -471,6 +472,30 @@ void VolumeMountWatcherWin::OnWindowMessage(UINT event_type, LPARAM data) { } } +void VolumeMountWatcherWin::OnMediaChange(WPARAM wparam, LPARAM lparam) { + if (lparam == SHCNE_MEDIAINSERTED || lparam == SHCNE_MEDIAREMOVED) { + struct _ITEMIDLIST* pidl = *reinterpret_cast( + wparam); + wchar_t sPath[MAX_PATH]; + if (!SHGetPathFromIDList(pidl, sPath)) { + DVLOG(1) << "MediaInserted: SHGetPathFromIDList failed"; + return; + } + switch (lparam) { + case SHCNE_MEDIAINSERTED: { + std::vector paths; + paths.push_back(base::FilePath(sPath)); + AddDevicesOnUIThread(paths); + break; + } + case SHCNE_MEDIAREMOVED: { + HandleDeviceDetachEventOnUIThread(sPath); + break; + } + } + } +} + void VolumeMountWatcherWin::SetNotifications( StorageMonitor::Receiver* notifications) { notifications_ = notifications; diff --git a/components/storage_monitor/volume_mount_watcher_win.h b/components/storage_monitor/volume_mount_watcher_win.h index 0940d5c01117de..5e5f05a5e94ce1 100644 --- a/components/storage_monitor/volume_mount_watcher_win.h +++ b/components/storage_monitor/volume_mount_watcher_win.h @@ -49,6 +49,9 @@ class VolumeMountWatcherWin { // notification if appropriate. void OnWindowMessage(UINT event_type, LPARAM data); + // Processes SHCNE_MEDIAINSERTED (and REMOVED). + void OnMediaChange(WPARAM wparam, LPARAM lparam); + // Set the volume notifications object to be used when new // removable volumes are found. void SetNotifications(StorageMonitor::Receiver* notifications);