Skip to content

Commit

Permalink
Add notification for media changed, and notify volume mount watcher w…
Browse files Browse the repository at this point in the history
…hen 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
  • Loading branch information
krb@chromium.org committed Apr 29, 2014
1 parent 237ce82 commit 19e01a9
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
31 changes: 31 additions & 0 deletions components/storage_monitor/storage_monitor_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
#include <windows.h>
#include <dbt.h>
#include <fileapi.h>
#include <shlobj.h>

#include "base/win/wrapped_window_proc.h"
#include "components/storage_monitor/portable_device_watcher_win.h"
#include "components/storage_monitor/removable_device_constants.h"
#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 {
Expand All @@ -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_);
Expand All @@ -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);

Expand All @@ -59,6 +65,7 @@ void StorageMonitorWin::Init() {
SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
volume_mount_watcher_->Init();
portable_device_watcher_->Init(window_);
MediaChangeNotificationRegister();
}

bool StorageMonitorWin::GetStorageInfoForPath(const base::FilePath& path,
Expand Down Expand Up @@ -138,13 +145,32 @@ LRESULT CALLBACK StorageMonitorWin::WndProc(HWND hwnd, UINT message,
case WM_DEVICECHANGE:
OnDeviceChange(static_cast<UINT>(wparam), lparam);
return TRUE;
case WM_USER_MEDIACHANGED:
OnMediaChange(wparam, lparam);
return TRUE;
default:
break;
}

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, &notify_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);
Expand All @@ -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());
Expand Down
6 changes: 6 additions & 0 deletions components/storage_monitor/storage_monitor_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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_;
Expand All @@ -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<VolumeMountWatcherWin> volume_mount_watcher_;

Expand Down
25 changes: 25 additions & 0 deletions components/storage_monitor/volume_mount_watcher_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <dbt.h>
#include <fileapi.h>
#include <shlobj.h>
#include <winioctl.h>

#include "base/bind_helpers.h"
Expand Down Expand Up @@ -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<struct _ITEMIDLIST**>(
wparam);
wchar_t sPath[MAX_PATH];
if (!SHGetPathFromIDList(pidl, sPath)) {
DVLOG(1) << "MediaInserted: SHGetPathFromIDList failed";
return;
}
switch (lparam) {
case SHCNE_MEDIAINSERTED: {
std::vector<base::FilePath> paths;
paths.push_back(base::FilePath(sPath));
AddDevicesOnUIThread(paths);
break;
}
case SHCNE_MEDIAREMOVED: {
HandleDeviceDetachEventOnUIThread(sPath);
break;
}
}
}
}

void VolumeMountWatcherWin::SetNotifications(
StorageMonitor::Receiver* notifications) {
notifications_ = notifications;
Expand Down
3 changes: 3 additions & 0 deletions components/storage_monitor/volume_mount_watcher_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 19e01a9

Please sign in to comment.