Chromium Code Reviews| 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 |