Index: content/browser/system_message_window_win.cc |
diff --git a/content/browser/system_message_window_win.cc b/content/browser/system_message_window_win.cc |
index ca31feb21f7a1358d25b51e42f5f052a9e844db6..918037d216843f3266fe5ae5b2e5500ac07865cf 100644 |
--- a/content/browser/system_message_window_win.cc |
+++ b/content/browser/system_message_window_win.cc |
@@ -4,14 +4,68 @@ |
#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 WindowClassName[] = 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 }, |
+}; |
+} |
+ |
+// 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); |
+ PLOG_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() { |
@@ -28,6 +82,7 @@ SystemMessageWindowWin::SystemMessageWindowWin() { |
window_ = CreateWindow(WindowClassName, |
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() { |
@@ -37,13 +92,53 @@ SystemMessageWindowWin::~SystemMessageWindowWin() { |
} |
} |
-LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) { |
+LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, |
+ DWORD_PTR 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; |
+ DVLOG(1) |
+ << "Received a notification for " |
+ << (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE ? |
+ "an audio device." : "a video device"); |
wjia(left Chromium)
2012/07/31 06:12:26
When more device types are added, this code has to
tommi (sloooow) - chröme
2012/07/31 09:56:15
Agree. There already is a LOG() statement inside
|
+ break; |
+ } |
+ } |
+ |
+ if (device_type == base::SystemMonitor::DEVTYPE_UNKNOWN) { |
+ DVLOG(1) << "Ignoring device of unknown type arrival/removal."; |
+ return TRUE; |
+ } |
break; |
+ } |
+ |
+ default: |
+ DVLOG(1) << "Ignoring device notification " << event_type; |
+ return TRUE; |
} |
+ |
+ monitor->ProcessDevicesChanged(device_type); |
+ |
return TRUE; |
} |
@@ -52,7 +147,7 @@ LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message, |
switch (message) { |
case WM_DEVICECHANGE: |
return OnDeviceChange(static_cast<UINT>(wparam), |
- static_cast<DWORD>(lparam)); |
+ static_cast<DWORD_PTR>(lparam)); |
default: |
break; |
} |