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 "content/browser/system_message_window_win.h" | 5 #include "content/browser/system_message_window_win.h" |
6 | 6 |
7 #include <windows.h> | |
8 #include <dbt.h> | 7 #include <dbt.h> |
8 #include <ks.h> | |
9 #include <ksmedia.h> | |
9 | 10 |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 #include "base/system_monitor/system_monitor.h" | 12 #include "base/system_monitor/system_monitor.h" |
12 #include "base/win/wrapped_window_proc.h" | 13 #include "base/win/wrapped_window_proc.h" |
13 | 14 |
14 static const wchar_t* const WindowClassName = L"Chrome_SystemMessageWindow"; | 15 namespace { |
16 const wchar_t WindowClassName[] = L"Chrome_SystemMessageWindow"; | |
17 | |
18 // A static map from a device category guid to base::SystemMonitor::DeviceType. | |
19 struct { | |
20 const GUID device_category; | |
21 const base::SystemMonitor::DeviceType device_type; | |
22 } const kDeviceCategoryMap[] = { | |
23 { KSCATEGORY_AUDIO, base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE }, | |
24 { KSCATEGORY_VIDEO, base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE }, | |
25 }; | |
26 } | |
27 | |
28 // Manages the device notification handles for SystemMessageWindowWin. | |
29 class SystemMessageWindowWin::DeviceNotifications { | |
30 public: | |
31 explicit DeviceNotifications(HWND hwnd) : notifications_() { | |
32 Register(hwnd); | |
33 } | |
34 | |
35 ~DeviceNotifications() { | |
36 Unregister(); | |
37 } | |
38 | |
39 void Register(HWND hwnd) { | |
40 // Request to receive device notifications. All applications receive basic | |
41 // notifications via WM_DEVICECHANGE but in order to receive detailed device | |
42 // arrival and removal messages, we need to register. | |
43 DEV_BROADCAST_DEVICEINTERFACE filter = {0}; | |
44 filter.dbcc_size = sizeof(filter); | |
45 filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; | |
46 for (int i = 0; i < arraysize(kDeviceCategoryMap); ++i) { | |
47 filter.dbcc_classguid = kDeviceCategoryMap[i].device_category; | |
48 DCHECK_EQ(notifications_[i], static_cast<HDEVNOTIFY>(NULL)); | |
49 notifications_[i] = RegisterDeviceNotification(hwnd, &filter, | |
50 DEVICE_NOTIFY_WINDOW_HANDLE); | |
51 PLOG_IF(ERROR, !notifications_[i]) << "RegisterDeviceNotification failed"; | |
52 } | |
53 } | |
54 | |
55 void Unregister() { | |
56 for (int i = 0; i < arraysize(notifications_); ++i) { | |
57 if (notifications_[i]) { | |
58 UnregisterDeviceNotification(notifications_[i]); | |
59 notifications_[i] = NULL; | |
60 } | |
61 } | |
62 } | |
63 | |
64 private: | |
65 HDEVNOTIFY notifications_[arraysize(kDeviceCategoryMap)]; | |
66 | |
67 DISALLOW_IMPLICIT_CONSTRUCTORS(DeviceNotifications); | |
68 }; | |
15 | 69 |
16 | 70 |
17 SystemMessageWindowWin::SystemMessageWindowWin() { | 71 SystemMessageWindowWin::SystemMessageWindowWin() { |
18 WNDCLASSEX window_class; | 72 WNDCLASSEX window_class; |
19 base::win::InitializeWindowClass( | 73 base::win::InitializeWindowClass( |
20 WindowClassName, | 74 WindowClassName, |
21 &base::win::WrappedWindowProc<SystemMessageWindowWin::WndProcThunk>, | 75 &base::win::WrappedWindowProc<SystemMessageWindowWin::WndProcThunk>, |
22 0, 0, 0, NULL, NULL, NULL, NULL, NULL, | 76 0, 0, 0, NULL, NULL, NULL, NULL, NULL, |
23 &window_class); | 77 &window_class); |
24 instance_ = window_class.hInstance; | 78 instance_ = window_class.hInstance; |
25 ATOM clazz = RegisterClassEx(&window_class); | 79 ATOM clazz = RegisterClassEx(&window_class); |
26 DCHECK(clazz); | 80 DCHECK(clazz); |
27 | 81 |
28 window_ = CreateWindow(WindowClassName, | 82 window_ = CreateWindow(WindowClassName, |
29 0, 0, 0, 0, 0, 0, 0, 0, instance_, 0); | 83 0, 0, 0, 0, 0, 0, 0, 0, instance_, 0); |
30 SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); | 84 SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this)); |
85 device_notifications_.reset(new DeviceNotifications(window_)); | |
31 } | 86 } |
32 | 87 |
33 SystemMessageWindowWin::~SystemMessageWindowWin() { | 88 SystemMessageWindowWin::~SystemMessageWindowWin() { |
34 if (window_) { | 89 if (window_) { |
35 DestroyWindow(window_); | 90 DestroyWindow(window_); |
36 UnregisterClass(WindowClassName, instance_); | 91 UnregisterClass(WindowClassName, instance_); |
37 } | 92 } |
38 } | 93 } |
39 | 94 |
40 LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) { | 95 LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, |
96 DWORD_PTR data) { | |
41 base::SystemMonitor* monitor = base::SystemMonitor::Get(); | 97 base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
98 base::SystemMonitor::DeviceType device_type = | |
99 base::SystemMonitor::DEVTYPE_UNKNOWN; | |
42 switch (event_type) { | 100 switch (event_type) { |
43 case DBT_DEVNODES_CHANGED: | 101 case DBT_DEVNODES_CHANGED: |
44 monitor->ProcessDevicesChanged(base::SystemMonitor::DEVTYPE_UNKNOWN); | 102 // For this notification, we're happy with the default DEVTYPE_UNKNOWN. |
45 break; | 103 break; |
104 | |
105 case DBT_DEVICEREMOVECOMPLETE: | |
106 case DBT_DEVICEARRIVAL: { | |
107 // This notification has more details about the specific device that | |
108 // was added or removed. See if this is a category we're interested | |
109 // in monitoring and if so report the specific device type. If we don't | |
110 // find the category in our map, ignore the notification and do not | |
111 // notify the system monitor. | |
112 DEV_BROADCAST_DEVICEINTERFACE* device_interface = | |
113 reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data); | |
114 DCHECK_EQ(device_interface->dbcc_devicetype, | |
115 static_cast<DWORD>(DBT_DEVTYP_DEVICEINTERFACE)); | |
116 for (int i = 0; i < arraysize(kDeviceCategoryMap); ++i) { | |
117 if (kDeviceCategoryMap[i].device_category == | |
118 device_interface->dbcc_classguid) { | |
119 device_type = kDeviceCategoryMap[i].device_type; | |
120 DVLOG(1) | |
121 << "Received a notification for " | |
122 << (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE ? | |
123 "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
| |
124 break; | |
125 } | |
126 } | |
127 | |
128 if (device_type == base::SystemMonitor::DEVTYPE_UNKNOWN) { | |
129 DVLOG(1) << "Ignoring device of unknown type arrival/removal."; | |
130 return TRUE; | |
131 } | |
132 break; | |
133 } | |
134 | |
135 default: | |
136 DVLOG(1) << "Ignoring device notification " << event_type; | |
137 return TRUE; | |
46 } | 138 } |
139 | |
140 monitor->ProcessDevicesChanged(device_type); | |
141 | |
47 return TRUE; | 142 return TRUE; |
48 } | 143 } |
49 | 144 |
50 LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message, | 145 LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message, |
51 WPARAM wparam, LPARAM lparam) { | 146 WPARAM wparam, LPARAM lparam) { |
52 switch (message) { | 147 switch (message) { |
53 case WM_DEVICECHANGE: | 148 case WM_DEVICECHANGE: |
54 return OnDeviceChange(static_cast<UINT>(wparam), | 149 return OnDeviceChange(static_cast<UINT>(wparam), |
55 static_cast<DWORD>(lparam)); | 150 static_cast<DWORD_PTR>(lparam)); |
56 default: | 151 default: |
57 break; | 152 break; |
58 } | 153 } |
59 | 154 |
60 return ::DefWindowProc(hwnd, message, wparam, lparam); | 155 return ::DefWindowProc(hwnd, message, wparam, lparam); |
61 } | 156 } |
OLD | NEW |