OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/renderer_host/media/media_devices_dispatcher_host.h" | |
6 | |
7 #include <utility> | |
8 #include <vector> | |
9 | |
10 #include "base/bind_helpers.h" | |
11 #include "base/memory/ptr_util.h" | |
12 #include "content/browser/bad_message.h" | |
13 #include "content/browser/renderer_host/media/media_stream_manager.h" | |
14 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | |
15 #include "content/common/media/media_devices.h" | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "content/public/browser/media_device_id.h" | |
18 #include "content/public/browser/render_frame_host.h" | |
19 #include "content/public/browser/resource_context.h" | |
20 #include "content/public/common/media_stream_request.h" | |
21 #include "mojo/public/cpp/bindings/strong_binding.h" | |
22 #include "services/shell/public/cpp/interface_provider.h" | |
23 #include "url/origin.h" | |
24 | |
25 namespace content { | |
26 | |
27 namespace { | |
28 | |
29 MediaDeviceInfo TranslateDeviceInfo(bool has_permission, | |
30 const std::string& device_id_salt, | |
31 const std::string& group_id_salt, | |
32 const url::Origin& security_origin, | |
33 const MediaDeviceInfo& device_info) { | |
34 return MediaDeviceInfo( | |
35 GetHMACForMediaDeviceID(device_id_salt, security_origin, | |
36 device_info.device_id), | |
37 has_permission ? device_info.label : std::string(), | |
38 device_info.group_id.empty() | |
39 ? std::string() | |
40 : GetHMACForMediaDeviceID(group_id_salt, security_origin, | |
41 device_info.group_id)); | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 // static | |
47 void MediaDevicesDispatcherHost::Create( | |
48 int render_process_id, | |
49 int routing_id, | |
50 const std::string& device_id_salt, | |
51 MediaStreamManager* media_stream_manager, | |
52 bool use_fake_ui, | |
53 ::mojom::MediaDevicesDispatcherHostRequest request) { | |
54 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
55 mojo::MakeStrongBinding(base::MakeUnique<MediaDevicesDispatcherHost>( | |
56 render_process_id, routing_id, device_id_salt, | |
57 media_stream_manager, use_fake_ui), | |
58 std::move(request)); | |
59 } | |
60 | |
61 MediaDevicesDispatcherHost::MediaDevicesDispatcherHost( | |
62 int render_process_id, | |
63 int routing_id, | |
64 const std::string& device_id_salt, | |
65 MediaStreamManager* media_stream_manager, | |
66 bool use_fake_ui) | |
67 : render_process_id_(render_process_id), | |
68 routing_id_(routing_id), | |
69 device_id_salt_(device_id_salt), | |
70 group_id_salt_(ResourceContext::CreateRandomMediaDeviceIDSalt()), | |
71 media_stream_manager_(media_stream_manager), | |
72 use_fake_ui_(use_fake_ui), | |
73 weak_factory_(this) { | |
74 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
75 } | |
76 | |
77 MediaDevicesDispatcherHost::~MediaDevicesDispatcherHost() { | |
78 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
79 } | |
80 | |
81 void MediaDevicesDispatcherHost::EnumerateDevices( | |
82 bool request_audio_input, | |
83 bool request_video_input, | |
84 bool request_audio_output, | |
85 const url::Origin& security_origin, | |
86 const EnumerateDevicesCallback& client_callback) { | |
87 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
88 | |
89 if (!request_audio_input && !request_video_input && !request_audio_output) { | |
90 bad_message::ReceivedBadMessage(render_process_id_, | |
91 bad_message::MDDH_INVALID_DEVICE_TYPE); | |
hta - Chromium
2016/09/30 08:38:12
Given that this is what the error means, should it
Guido Urdaneta
2016/10/07 17:07:13
Done.
| |
92 return; | |
93 } | |
94 | |
95 if (!MediaStreamManager::IsOriginAllowed(render_process_id_, | |
96 security_origin)) { | |
97 bad_message::ReceivedBadMessage(render_process_id_, | |
98 bad_message::MDDH_UNAUTHORIZED_ORIGIN); | |
99 return; | |
100 } | |
101 | |
102 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate; | |
103 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = request_audio_input; | |
104 devices_to_enumerate[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = request_video_input; | |
105 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = request_audio_output; | |
106 | |
107 // This callback is run after permissions are checked. | |
108 AccessCheckedCallback access_checked_callback = | |
109 base::Bind(&MediaDevicesDispatcherHost::DoEnumerateDevices, | |
110 weak_factory_.GetWeakPtr(), devices_to_enumerate, | |
111 security_origin, client_callback); | |
112 | |
113 std::unique_ptr<MediaStreamUIProxy> ui_proxy = GetUIProxy(); | |
114 | |
115 // The permission type MEDIA_DEVICE_AUDIO_CAPTURE is currently used for both | |
116 // audio input and output. TODO(guidou): use specific permission for audio | |
hta - Chromium
2016/09/30 08:38:12
New line for TODO?
Guido Urdaneta
2016/10/07 17:07:13
Done.
| |
117 // output when it becomes available. See http://crbug.com/556542. | |
118 bool request_audio = request_audio_input || request_audio_output; | |
119 if (request_audio) { | |
120 ui_proxy->CheckAccess( | |
121 security_origin, MEDIA_DEVICE_AUDIO_CAPTURE, render_process_id_, | |
122 routing_id_, base::Bind(&MediaDevicesDispatcherHost::AudioAccessChecked, | |
123 weak_factory_.GetWeakPtr(), | |
124 base::Passed(&ui_proxy), request_video_input, | |
125 security_origin, access_checked_callback)); | |
126 return; | |
127 } | |
128 | |
129 DCHECK(request_video_input); | |
130 ui_proxy->CheckAccess( | |
131 security_origin, MEDIA_DEVICE_VIDEO_CAPTURE, render_process_id_, | |
132 routing_id_, | |
133 base::Bind(&MediaDevicesDispatcherHost::VideoAccessChecked, | |
134 weak_factory_.GetWeakPtr(), base::Passed(&ui_proxy), | |
135 false /* has_audio_permission */, access_checked_callback)); | |
136 } | |
137 | |
138 void MediaDevicesDispatcherHost::AudioAccessChecked( | |
139 std::unique_ptr<MediaStreamUIProxy> ui_proxy, | |
140 bool check_video_permission, | |
141 const url::Origin& security_origin, | |
142 AccessCheckedCallback callback, | |
143 bool has_audio_permission) { | |
144 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
145 if (check_video_permission) { | |
146 ui_proxy->CheckAccess( | |
147 security_origin, MEDIA_DEVICE_VIDEO_CAPTURE, render_process_id_, | |
148 routing_id_, | |
149 base::Bind(&MediaDevicesDispatcherHost::VideoAccessChecked, | |
150 weak_factory_.GetWeakPtr(), base::Passed(&ui_proxy), | |
151 has_audio_permission, callback)); | |
152 return; | |
153 } | |
154 | |
155 MediaDevicesManager::BoolDeviceTypes permissions; | |
156 permissions[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = has_audio_permission; | |
157 permissions[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = has_audio_permission; | |
158 callback.Run(permissions); | |
159 } | |
160 | |
161 void MediaDevicesDispatcherHost::VideoAccessChecked( | |
162 std::unique_ptr<MediaStreamUIProxy> ui_proxy, | |
163 bool has_audio_permission, | |
164 AccessCheckedCallback callback, | |
165 bool has_video_permission) { | |
166 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
167 MediaDevicesManager::BoolDeviceTypes permissions; | |
168 permissions[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = has_audio_permission; | |
169 permissions[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = has_audio_permission; | |
170 permissions[MEDIA_DEVICE_TYPE_VIDEO_INPUT] = has_video_permission; | |
171 callback.Run(permissions); | |
172 } | |
173 | |
174 void MediaDevicesDispatcherHost::DoEnumerateDevices( | |
175 const MediaDevicesManager::BoolDeviceTypes& requested_types, | |
176 const url::Origin& security_origin, | |
177 const EnumerateDevicesCallback& client_callback, | |
178 const MediaDevicesManager::BoolDeviceTypes& has_permissions) { | |
179 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
180 media_stream_manager_->media_devices_manager()->EnumerateDevices( | |
181 requested_types, | |
182 base::Bind(&MediaDevicesDispatcherHost::DevicesEnumerated, | |
183 weak_factory_.GetWeakPtr(), requested_types, security_origin, | |
184 client_callback, has_permissions)); | |
185 } | |
186 | |
187 void MediaDevicesDispatcherHost::DevicesEnumerated( | |
188 const MediaDevicesManager::BoolDeviceTypes& requested_types, | |
189 const url::Origin& security_origin, | |
190 const EnumerateDevicesCallback& client_callback, | |
191 const MediaDevicesManager::BoolDeviceTypes& has_permissions, | |
192 const MediaDeviceEnumeration& enumeration) { | |
193 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
194 std::vector<std::vector<MediaDeviceInfo>> result(NUM_MEDIA_DEVICE_TYPES); | |
195 for (size_t i = 0; i < NUM_MEDIA_DEVICE_TYPES; ++i) { | |
196 if (!requested_types[i]) | |
197 continue; | |
198 | |
199 for (const auto& device_info : enumeration[i]) { | |
200 result[i].push_back(TranslateDeviceInfo(has_permissions[i], | |
201 device_id_salt_, group_id_salt_, | |
202 security_origin, device_info)); | |
203 } | |
204 } | |
205 client_callback.Run(result); | |
206 } | |
207 | |
208 std::unique_ptr<MediaStreamUIProxy> MediaDevicesDispatcherHost::GetUIProxy() { | |
209 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
210 if (use_fake_ui_) { | |
211 return fake_ui_proxy_ ? std::move(fake_ui_proxy_) | |
212 : base::MakeUnique<FakeMediaStreamUIProxy>(); | |
213 } | |
214 return MediaStreamUIProxy::Create(); | |
215 } | |
216 | |
217 void MediaDevicesDispatcherHost::SetFakeUIProxy( | |
218 std::unique_ptr<MediaStreamUIProxy> fake_ui_proxy) { | |
219 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
220 fake_ui_proxy_ = std::move(fake_ui_proxy); | |
221 } | |
222 | |
223 } // namespace content | |
OLD | NEW |