| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/media/device_request_message_filter.h" |
| |
| #include "content/browser/browser_main_loop.h" |
| #include "content/browser/renderer_host/media/media_stream_manager.h" |
| #include "content/common/media/media_stream_messages.h" |
| #include "content/public/browser/media_device_id.h" |
| #include "content/public/browser/resource_context.h" |
| |
| // Clears the MediaStreamDevice.name from all devices in |device_list|. |
| static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) { |
| for (content::StreamDeviceInfoArray::iterator device_itr = devices->begin(); |
| device_itr != devices->end(); |
| ++device_itr) { |
| device_itr->device.name.clear(); |
| } |
| } |
| |
| namespace content { |
| |
| DeviceRequestMessageFilter::DeviceRequestMessageFilter( |
| ResourceContext* resource_context, |
| MediaStreamManager* media_stream_manager) |
| : resource_context_(resource_context), |
| media_stream_manager_(media_stream_manager) { |
| DCHECK(resource_context); |
| DCHECK(media_stream_manager); |
| } |
| |
| DeviceRequestMessageFilter::~DeviceRequestMessageFilter() { |
| DCHECK(requests_.empty()); |
| } |
| |
| struct DeviceRequestMessageFilter::DeviceRequest { |
| DeviceRequest(int request_id, |
| const GURL& origin, |
| const std::string& audio_devices_label, |
| const std::string& video_devices_label) |
| : request_id(request_id), |
| origin(origin), |
| has_audio_returned(false), |
| has_video_returned(false), |
| audio_devices_label(audio_devices_label), |
| video_devices_label(video_devices_label) {} |
| |
| int request_id; |
| GURL origin; |
| bool has_audio_returned; |
| bool has_video_returned; |
| std::string audio_devices_label; |
| std::string video_devices_label; |
| StreamDeviceInfoArray audio_devices; |
| StreamDeviceInfoArray video_devices; |
| }; |
| |
| void DeviceRequestMessageFilter::StreamGenerated( |
| const std::string& label, |
| const StreamDeviceInfoArray& audio_devices, |
| const StreamDeviceInfoArray& video_devices) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void DeviceRequestMessageFilter::StreamGenerationFailed( |
| const std::string& label) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void DeviceRequestMessageFilter::StopGeneratedStream( |
| int render_view_id, |
| const std::string& label) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void DeviceRequestMessageFilter::DevicesEnumerated( |
| const std::string& label, |
| const StreamDeviceInfoArray& new_devices) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| // Look up the DeviceRequest by id. |
| DeviceRequestList::iterator request_it = requests_.begin(); |
| for (; request_it != requests_.end(); ++request_it) { |
| if (label == request_it->audio_devices_label || |
| label == request_it->video_devices_label) { |
| break; |
| } |
| } |
| DCHECK(request_it != requests_.end()); |
| |
| StreamDeviceInfoArray* audio_devices = &request_it->audio_devices; |
| StreamDeviceInfoArray* video_devices = &request_it->video_devices; |
| |
| // Store hmac'd device ids instead of raw device ids. |
| if (label == request_it->audio_devices_label) { |
| request_it->has_audio_returned = true; |
| DCHECK(audio_devices->empty()); |
| HmacDeviceIds(request_it->origin, new_devices, audio_devices); |
| } else { |
| DCHECK(label == request_it->video_devices_label); |
| request_it->has_video_returned = true; |
| DCHECK(video_devices->empty()); |
| HmacDeviceIds(request_it->origin, new_devices, video_devices); |
| } |
| |
| if (!request_it->has_audio_returned || !request_it->has_video_returned) { |
| // Wait for the rest of the devices to complete. |
| return; |
| } |
| |
| // Query for mic and camera permissions. |
| if (!resource_context_->AllowMicAccess(request_it->origin)) |
| ClearDeviceLabels(audio_devices); |
| if (!resource_context_->AllowCameraAccess(request_it->origin)) |
| ClearDeviceLabels(video_devices); |
| |
| // Both audio and video devices are ready for copying. |
| StreamDeviceInfoArray all_devices = *audio_devices; |
| all_devices.insert( |
| all_devices.end(), video_devices->begin(), video_devices->end()); |
| |
| Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices)); |
| |
| media_stream_manager_->CancelRequest(request_it->audio_devices_label); |
| media_stream_manager_->CancelRequest(request_it->video_devices_label); |
| requests_.erase(request_it); |
| } |
| |
| void DeviceRequestMessageFilter::DeviceOpened( |
| const std::string& label, |
| const StreamDeviceInfo& video_device) { |
| NOTIMPLEMENTED(); |
| } |
| |
| bool DeviceRequestMessageFilter::OnMessageReceived(const IPC::Message& message, |
| bool* message_was_ok) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP_EX(DeviceRequestMessageFilter, message, *message_was_ok) |
| IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP_EX() |
| return handled; |
| } |
| |
| void DeviceRequestMessageFilter::OnChannelClosing() { |
| // Since the IPC channel is gone, cancel outstanding device requests. |
| media_stream_manager_->CancelAllRequests(peer_pid()); |
| |
| requests_.clear(); |
| } |
| |
| void DeviceRequestMessageFilter::HmacDeviceIds( |
| const GURL& origin, |
| const StreamDeviceInfoArray& raw_devices, |
| StreamDeviceInfoArray* devices_with_guids) { |
| DCHECK(devices_with_guids); |
| |
| // Replace raw ids with hmac'd ids before returning to renderer process. |
| for (StreamDeviceInfoArray::const_iterator device_itr = raw_devices.begin(); |
| device_itr != raw_devices.end(); |
| ++device_itr) { |
| StreamDeviceInfo current_device_info = *device_itr; |
| current_device_info.device.id = |
| content::GetHMACForMediaDeviceID(origin, device_itr->device.id); |
| devices_with_guids->push_back(current_device_info); |
| } |
| } |
| |
| void DeviceRequestMessageFilter::OnGetSources(int request_id, |
| const GURL& security_origin) { |
| // Make request to get audio devices. |
| const std::string& audio_label = media_stream_manager_->EnumerateDevices( |
| this, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin); |
| DCHECK(!audio_label.empty()); |
| |
| // Make request for video devices. |
| const std::string& video_label = media_stream_manager_->EnumerateDevices( |
| this, -1, -1, -1, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin); |
| DCHECK(!video_label.empty()); |
| |
| requests_.push_back(DeviceRequest( |
| request_id, security_origin, audio_label, video_label)); |
| } |
| |
| } // namespace content |