diff options
author | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-31 21:28:52 +0000 |
---|---|---|
committer | tommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-31 21:28:52 +0000 |
commit | 043e4899a81297f3b88db2984a6eacb87ffa5be6 (patch) | |
tree | 6d5ae79b749ef3199eb300721340ece9dc22fa6f | |
parent | 5db03dd4f3d795d037bfbb50bb9bc52de3b89f17 (diff) | |
download | chromium_src-043e4899a81297f3b88db2984a6eacb87ffa5be6.zip chromium_src-043e4899a81297f3b88db2984a6eacb87ffa5be6.tar.gz chromium_src-043e4899a81297f3b88db2984a6eacb87ffa5be6.tar.bz2 |
Add support for device removal/arrival detection with device type. For now this allows us to detect when audio and video capture devices are connected/disconnected.
TEST=Try connecting and disconnecting USB audio/video devices. You should see notifications in the log about those operations being detected.
BUG=137799
Review URL: https://chromiumcodereview.appspot.com/10824086
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149279 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/system_message_window_win.cc | 108 | ||||
-rw-r--r-- | content/browser/system_message_window_win.h | 5 |
2 files changed, 103 insertions, 10 deletions
diff --git a/content/browser/system_message_window_win.cc b/content/browser/system_message_window_win.cc index ca31feb..211e728 100644 --- a/content/browser/system_message_window_win.cc +++ b/content/browser/system_message_window_win.cc @@ -4,20 +4,75 @@ #include "content/browser/system_message_window_win.h" -#include <windows.h> #include <dbt.h> +#include <ks.h> +#include <ksmedia.h> #include "base/logging.h" #include "base/system_monitor/system_monitor.h" #include "base/win/wrapped_window_proc.h" -static const wchar_t* const WindowClassName = L"Chrome_SystemMessageWindow"; +namespace { +const wchar_t kWindowClassName[] = L"Chrome_SystemMessageWindow"; + +// A static map from a device category guid to base::SystemMonitor::DeviceType. +struct { + const GUID device_category; + const base::SystemMonitor::DeviceType device_type; +} const kDeviceCategoryMap[] = { + { KSCATEGORY_AUDIO, base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE }, + { KSCATEGORY_VIDEO, base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE }, +}; +} // namespace + +// Manages the device notification handles for SystemMessageWindowWin. +class SystemMessageWindowWin::DeviceNotifications { + public: + explicit DeviceNotifications(HWND hwnd) : notifications_() { + Register(hwnd); + } + + ~DeviceNotifications() { + Unregister(); + } + + void Register(HWND hwnd) { + // Request to receive device notifications. All applications receive basic + // notifications via WM_DEVICECHANGE but in order to receive detailed device + // arrival and removal messages, we need to register. + DEV_BROADCAST_DEVICEINTERFACE filter = {0}; + filter.dbcc_size = sizeof(filter); + filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + for (int i = 0; i < arraysize(kDeviceCategoryMap); ++i) { + filter.dbcc_classguid = kDeviceCategoryMap[i].device_category; + DCHECK_EQ(notifications_[i], static_cast<HDEVNOTIFY>(NULL)); + notifications_[i] = RegisterDeviceNotification( + hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE); + DPLOG_IF(ERROR, !notifications_[i]) + << "RegisterDeviceNotification failed"; + } + } + + void Unregister() { + for (int i = 0; i < arraysize(notifications_); ++i) { + if (notifications_[i]) { + UnregisterDeviceNotification(notifications_[i]); + notifications_[i] = NULL; + } + } + } + + private: + HDEVNOTIFY notifications_[arraysize(kDeviceCategoryMap)]; + + DISALLOW_IMPLICIT_CONSTRUCTORS(DeviceNotifications); +}; SystemMessageWindowWin::SystemMessageWindowWin() { WNDCLASSEX window_class; base::win::InitializeWindowClass( - WindowClassName, + kWindowClassName, &base::win::WrappedWindowProc<SystemMessageWindowWin::WndProcThunk>, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, &window_class); @@ -25,25 +80,61 @@ SystemMessageWindowWin::SystemMessageWindowWin() { ATOM clazz = RegisterClassEx(&window_class); DCHECK(clazz); - window_ = CreateWindow(WindowClassName, + window_ = CreateWindow(kWindowClassName, 0, 0, 0, 0, 0, 0, 0, 0, instance_, 0); SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); + device_notifications_.reset(new DeviceNotifications(window_)); } SystemMessageWindowWin::~SystemMessageWindowWin() { if (window_) { DestroyWindow(window_); - UnregisterClass(WindowClassName, instance_); + UnregisterClass(kWindowClassName, instance_); } } -LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) { +LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, LPARAM data) { base::SystemMonitor* monitor = base::SystemMonitor::Get(); + base::SystemMonitor::DeviceType device_type = + base::SystemMonitor::DEVTYPE_UNKNOWN; switch (event_type) { case DBT_DEVNODES_CHANGED: - monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_UNKNOWN); + // For this notification, we're happy with the default DEVTYPE_UNKNOWN. + break; + + case DBT_DEVICEREMOVECOMPLETE: + case DBT_DEVICEARRIVAL: { + // This notification has more details about the specific device that + // was added or removed. See if this is a category we're interested + // in monitoring and if so report the specific device type. If we don't + // find the category in our map, ignore the notification and do not + // notify the system monitor. + DEV_BROADCAST_DEVICEINTERFACE* device_interface = + reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data); + DCHECK_EQ(device_interface->dbcc_devicetype, + static_cast<DWORD>(DBT_DEVTYP_DEVICEINTERFACE)); + for (int i = 0; i < arraysize(kDeviceCategoryMap); ++i) { + if (kDeviceCategoryMap[i].device_category == + device_interface->dbcc_classguid) { + device_type = kDeviceCategoryMap[i].device_type; + break; + } + } + + // Devices that we do not have a DEVTYPE_ for, get detected via + // DBT_DEVNODES_CHANGED, so we avoid sending additional notifications + // for those here. + if (device_type == base::SystemMonitor::DEVTYPE_UNKNOWN) + return TRUE; break; + } + + default: + return TRUE; } + + monitor->ProcessDevicesChanged(device_type); + return TRUE; } @@ -51,8 +142,7 @@ LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { switch (message) { case WM_DEVICECHANGE: - return OnDeviceChange(static_cast<UINT>(wparam), - static_cast<DWORD>(lparam)); + return OnDeviceChange(static_cast<UINT>(wparam), lparam); default: break; } diff --git a/content/browser/system_message_window_win.h b/content/browser/system_message_window_win.h index fefb4ce..d4120c9 100644 --- a/content/browser/system_message_window_win.h +++ b/content/browser/system_message_window_win.h @@ -8,6 +8,7 @@ #include <windows.h> #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" class CONTENT_EXPORT SystemMessageWindowWin { @@ -16,7 +17,7 @@ class CONTENT_EXPORT SystemMessageWindowWin { virtual ~SystemMessageWindowWin(); - virtual LRESULT OnDeviceChange(UINT event_type, DWORD data); + virtual LRESULT OnDeviceChange(UINT event_type, LPARAM data); private: void Init(); @@ -37,6 +38,8 @@ class CONTENT_EXPORT SystemMessageWindowWin { HMODULE instance_; HWND window_; + class DeviceNotifications; + scoped_ptr<DeviceNotifications> device_notifications_; DISALLOW_COPY_AND_ASSIGN(SystemMessageWindowWin); }; |