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 3 // found in the LICENSE file. 4 5 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" 6 7 #include "content/browser/browser_main_loop.h" 8 #include "content/browser/child_process_security_policy_impl.h" 9 #include "content/common/media/media_stream_messages.h" 10 #include "content/common/media/media_stream_options.h" 11 #include "content/public/browser/render_process_host.h" 12 #include "url/gurl.h" 13 14 namespace content { 15 16 MediaStreamDispatcherHost::MediaStreamDispatcherHost( 17 int render_process_id, 18 const ResourceContext::SaltCallback& salt_callback, 19 MediaStreamManager* media_stream_manager, 20 ResourceContext* resource_context) 21 : BrowserMessageFilter(MediaStreamMsgStart), 22 render_process_id_(render_process_id), 23 salt_callback_(salt_callback), 24 media_stream_manager_(media_stream_manager), 25 resource_context_(resource_context) { 26 } 27 28 void MediaStreamDispatcherHost::StreamGenerated( 29 int render_view_id, 30 int page_request_id, 31 const std::string& label, 32 const StreamDeviceInfoArray& audio_devices, 33 const StreamDeviceInfoArray& video_devices) { 34 DCHECK_CURRENTLY_ON(BrowserThread::IO); 35 DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerated(" 36 << ", {label = " << label << "})"; 37 38 Send(new MediaStreamMsg_StreamGenerated( 39 render_view_id, page_request_id, label, audio_devices, 40 video_devices)); 41 } 42 43 void MediaStreamDispatcherHost::StreamGenerationFailed( 44 int render_view_id, 45 int page_request_id, 46 content::MediaStreamRequestResult result) { 47 DCHECK_CURRENTLY_ON(BrowserThread::IO); 48 DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerationFailed(" 49 << ", {page_request_id = " << page_request_id << "}" 50 << ", { result= " << result << "})"; 51 52 53 Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id, 54 page_request_id, 55 result)); 56 } 57 58 void MediaStreamDispatcherHost::DeviceStopped(int render_view_id, 59 const std::string& label, 60 const StreamDeviceInfo& device) { 61 DCHECK_CURRENTLY_ON(BrowserThread::IO); 62 DVLOG(1) << "MediaStreamDispatcherHost::DeviceStopped(" 63 << "{label = " << label << "}, " 64 << "{type = " << device.device.type << "}, " 65 << "{device_id = " << device.device.id << "})"; 66 67 Send(new MediaStreamMsg_DeviceStopped(render_view_id, label, device)); 68 } 69 70 void MediaStreamDispatcherHost::DevicesEnumerated( 71 int render_view_id, 72 int page_request_id, 73 const std::string& label, 74 const StreamDeviceInfoArray& devices) { 75 DCHECK_CURRENTLY_ON(BrowserThread::IO); 76 DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated(" 77 << ", {page_request_id = " << page_request_id << "})"; 78 79 Send(new MediaStreamMsg_DevicesEnumerated(render_view_id, page_request_id, 80 devices)); 81 } 82 83 void MediaStreamDispatcherHost::DeviceOpened( 84 int render_view_id, 85 int page_request_id, 86 const std::string& label, 87 const StreamDeviceInfo& video_device) { 88 DCHECK_CURRENTLY_ON(BrowserThread::IO); 89 DVLOG(1) << "MediaStreamDispatcherHost::DeviceOpened(" 90 << ", {page_request_id = " << page_request_id << "})"; 91 92 Send(new MediaStreamMsg_DeviceOpened( 93 render_view_id, page_request_id, label, video_device)); 94 } 95 96 bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) { 97 bool handled = true; 98 IPC_BEGIN_MESSAGE_MAP(MediaStreamDispatcherHost, message) 99 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GenerateStream, OnGenerateStream) 100 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelGenerateStream, 101 OnCancelGenerateStream) 102 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_StopStreamDevice, 103 OnStopStreamDevice) 104 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_EnumerateDevices, 105 OnEnumerateDevices) 106 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CancelEnumerateDevices, 107 OnCancelEnumerateDevices) 108 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_OpenDevice, 109 OnOpenDevice) 110 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_CloseDevice, 111 OnCloseDevice) 112 IPC_MESSAGE_UNHANDLED(handled = false) 113 IPC_END_MESSAGE_MAP() 114 return handled; 115 } 116 117 void MediaStreamDispatcherHost::OnChannelClosing() { 118 DVLOG(1) << "MediaStreamDispatcherHost::OnChannelClosing"; 119 120 // Since the IPC sender is gone, close all requesting/requested streams. 121 media_stream_manager_->CancelAllRequests(render_process_id_); 122 } 123 124 MediaStreamDispatcherHost::~MediaStreamDispatcherHost() { 125 } 126 127 void MediaStreamDispatcherHost::OnGenerateStream( 128 int render_view_id, 129 int page_request_id, 130 const StreamOptions& components, 131 const GURL& security_origin, 132 bool user_gesture) { 133 DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream(" 134 << render_view_id << ", " 135 << page_request_id << ", [" 136 << " audio:" << components.audio_requested 137 << " video:" << components.video_requested 138 << " ], " 139 << security_origin.spec() 140 << ", " << user_gesture << ")"; 141 142 if (!IsURLAllowed(security_origin)) 143 return; 144 145 media_stream_manager_->GenerateStream( 146 this, render_process_id_, render_view_id, salt_callback_, 147 page_request_id, components, security_origin, user_gesture); 148 } 149 150 void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id, 151 int page_request_id) { 152 DVLOG(1) << "MediaStreamDispatcherHost::OnCancelGenerateStream(" 153 << render_view_id << ", " 154 << page_request_id << ")"; 155 media_stream_manager_->CancelRequest(render_process_id_, render_view_id, 156 page_request_id); 157 } 158 159 void MediaStreamDispatcherHost::OnStopStreamDevice( 160 int render_view_id, 161 const std::string& device_id) { 162 DVLOG(1) << "MediaStreamDispatcherHost::OnStopStreamDevice(" 163 << render_view_id << ", " 164 << device_id << ")"; 165 media_stream_manager_->StopStreamDevice(render_process_id_, render_view_id, 166 device_id); 167 } 168 169 void MediaStreamDispatcherHost::OnEnumerateDevices( 170 int render_view_id, 171 int page_request_id, 172 MediaStreamType type, 173 const GURL& security_origin, 174 bool hide_labels_if_no_access) { 175 DVLOG(1) << "MediaStreamDispatcherHost::OnEnumerateDevices(" 176 << render_view_id << ", " 177 << page_request_id << ", " 178 << type << ", " 179 << security_origin.spec() << ")"; 180 181 if (!IsURLAllowed(security_origin)) 182 return; 183 184 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || 185 type == MEDIA_DEVICE_VIDEO_CAPTURE || 186 type == MEDIA_DEVICE_AUDIO_OUTPUT); 187 bool have_permission = true; 188 if (hide_labels_if_no_access) { 189 bool audio_type = type == MEDIA_DEVICE_AUDIO_CAPTURE || 190 type == MEDIA_DEVICE_AUDIO_OUTPUT; 191 have_permission = audio_type ? 192 resource_context_->AllowMicAccess(security_origin) : 193 resource_context_->AllowCameraAccess(security_origin); 194 } 195 196 media_stream_manager_->EnumerateDevices( 197 this, render_process_id_, render_view_id, salt_callback_, 198 page_request_id, type, security_origin, have_permission); 199 } 200 201 void MediaStreamDispatcherHost::OnCancelEnumerateDevices( 202 int render_view_id, 203 int page_request_id) { 204 DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices(" 205 << render_view_id << ", " 206 << page_request_id << ")"; 207 media_stream_manager_->CancelRequest(render_process_id_, render_view_id, 208 page_request_id); 209 } 210 211 void MediaStreamDispatcherHost::OnOpenDevice( 212 int render_view_id, 213 int page_request_id, 214 const std::string& device_id, 215 MediaStreamType type, 216 const GURL& security_origin) { 217 DVLOG(1) << "MediaStreamDispatcherHost::OnOpenDevice(" 218 << render_view_id << ", " 219 << page_request_id << ", device_id: " 220 << device_id.c_str() << ", type: " 221 << type << ", " 222 << security_origin.spec() << ")"; 223 224 if (!IsURLAllowed(security_origin)) 225 return; 226 227 media_stream_manager_->OpenDevice( 228 this, render_process_id_, render_view_id, salt_callback_, 229 page_request_id, device_id, type, security_origin); 230 } 231 232 void MediaStreamDispatcherHost::OnCloseDevice( 233 int render_view_id, 234 const std::string& label) { 235 DVLOG(1) << "MediaStreamDispatcherHost::OnCloseDevice(" 236 << render_view_id << ", " 237 << label << ")"; 238 239 media_stream_manager_->CancelRequest(label); 240 } 241 242 bool MediaStreamDispatcherHost::IsURLAllowed(const GURL& url) { 243 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( 244 render_process_id_, url)) { 245 LOG(ERROR) << "MSDH: Renderer requested a URL it's not allowed to use."; 246 return false; 247 } 248 249 return true; 250 } 251 252 } // namespace content 253