1 // Copyright 2013 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.
5 #include "content/browser/renderer_host/media/device_request_message_filter.h"
7 #include "content/browser/browser_main_loop.h"
8 #include "content/browser/child_process_security_policy_impl.h"
9 #include "content/browser/renderer_host/media/media_stream_manager.h"
10 #include "content/common/media/media_stream_messages.h"
11 #include "content/public/browser/resource_context.h"
15 DeviceRequestMessageFilter::DeviceRequestMessageFilter(
16 ResourceContext* resource_context,
17 MediaStreamManager* media_stream_manager,
18 int render_process_id)
19 : BrowserMessageFilter(MediaStreamMsgStart),
20 resource_context_(resource_context),
21 media_stream_manager_(media_stream_manager),
22 render_process_id_(render_process_id) {
23 DCHECK(resource_context);
24 DCHECK(media_stream_manager);
27 DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
28 // CHECK rather than DCHECK to make sure this never happens in the
29 // wild. We want to be sure due to http://crbug.com/341211
30 CHECK(requests_.empty());
33 struct DeviceRequestMessageFilter::DeviceRequest {
34 DeviceRequest(int request_id,
36 const std::string& audio_devices_label,
37 const std::string& video_devices_label)
38 : request_id(request_id),
40 has_audio_returned(false),
41 has_video_returned(false),
42 audio_devices_label(audio_devices_label),
43 video_devices_label(video_devices_label) {}
47 bool has_audio_returned;
48 bool has_video_returned;
49 std::string audio_devices_label;
50 std::string video_devices_label;
51 StreamDeviceInfoArray audio_devices;
52 StreamDeviceInfoArray video_devices;
55 void DeviceRequestMessageFilter::DevicesEnumerated(
58 const std::string& label,
59 const StreamDeviceInfoArray& new_devices) {
60 DCHECK_CURRENTLY_ON(BrowserThread::IO);
62 // Look up the DeviceRequest by id.
63 DeviceRequestList::iterator request_it = requests_.begin();
64 for (; request_it != requests_.end(); ++request_it) {
65 if (label == request_it->audio_devices_label ||
66 label == request_it->video_devices_label) {
70 DCHECK(request_it != requests_.end());
72 StreamDeviceInfoArray* audio_devices = &request_it->audio_devices;
73 StreamDeviceInfoArray* video_devices = &request_it->video_devices;
75 // Store hmac'd device ids instead of raw device ids.
76 if (label == request_it->audio_devices_label) {
77 request_it->has_audio_returned = true;
78 DCHECK(audio_devices->empty());
79 *audio_devices = new_devices;
81 DCHECK(label == request_it->video_devices_label);
82 request_it->has_video_returned = true;
83 DCHECK(video_devices->empty());
84 *video_devices = new_devices;
87 if (!request_it->has_audio_returned || !request_it->has_video_returned) {
88 // Wait for the rest of the devices to complete.
92 // Both audio and video devices are ready for copying.
93 StreamDeviceInfoArray all_devices = *audio_devices;
95 all_devices.end(), video_devices->begin(), video_devices->end());
97 Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
99 media_stream_manager_->CancelRequest(request_it->audio_devices_label);
100 media_stream_manager_->CancelRequest(request_it->video_devices_label);
101 requests_.erase(request_it);
104 bool DeviceRequestMessageFilter::OnMessageReceived(
105 const IPC::Message& message) {
107 IPC_BEGIN_MESSAGE_MAP(DeviceRequestMessageFilter, message)
108 IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources)
109 IPC_MESSAGE_UNHANDLED(handled = false)
110 IPC_END_MESSAGE_MAP()
114 void DeviceRequestMessageFilter::OnChannelClosing() {
115 // Since the IPC channel is gone, cancel outstanding device requests.
116 for (DeviceRequestList::iterator request_it = requests_.begin();
117 request_it != requests_.end(); ++request_it) {
118 media_stream_manager_->CancelRequest(request_it->audio_devices_label);
119 media_stream_manager_->CancelRequest(request_it->video_devices_label);
124 void DeviceRequestMessageFilter::OnGetSources(int request_id,
125 const GURL& security_origin) {
126 if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
127 render_process_id_, security_origin)) {
128 LOG(ERROR) << "Disallowed URL in DRMF::OnGetSources: " << security_origin;
132 // Make request to get audio devices.
133 const std::string& audio_label = media_stream_manager_->EnumerateDevices(
134 this, render_process_id_, -1, resource_context_->GetMediaDeviceIDSalt(),
135 -1, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
136 DCHECK(!audio_label.empty());
138 // Make request for video devices.
139 const std::string& video_label = media_stream_manager_->EnumerateDevices(
140 this, render_process_id_, -1, resource_context_->GetMediaDeviceIDSalt(),
141 -1, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
142 DCHECK(!video_label.empty());
144 requests_.push_back(DeviceRequest(
145 request_id, security_origin, audio_label, video_label));
148 } // namespace content