device_request_message_filter.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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.
4
5#include "content/browser/renderer_host/media/device_request_message_filter.h"
6
7#include "content/browser/browser_main_loop.h"
8#include "content/browser/renderer_host/media/media_stream_manager.h"
9#include "content/common/media/media_stream_messages.h"
10#include "content/public/browser/media_device_id.h"
11#include "content/public/browser/resource_context.h"
12
13// Clears the MediaStreamDevice.name from all devices in |device_list|.
14static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
15  for (content::StreamDeviceInfoArray::iterator device_itr = devices->begin();
16       device_itr != devices->end();
17       ++device_itr) {
18    device_itr->device.name.clear();
19  }
20}
21
22namespace content {
23
24DeviceRequestMessageFilter::DeviceRequestMessageFilter(
25    ResourceContext* resource_context,
26    MediaStreamManager* media_stream_manager)
27    : resource_context_(resource_context),
28      media_stream_manager_(media_stream_manager) {
29  DCHECK(resource_context);
30  DCHECK(media_stream_manager);
31}
32
33DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
34  DCHECK(requests_.empty());
35}
36
37struct DeviceRequestMessageFilter::DeviceRequest {
38  DeviceRequest(int request_id,
39                const GURL& origin,
40                const std::string& audio_devices_label,
41                const std::string& video_devices_label)
42      : request_id(request_id),
43        origin(origin),
44        has_audio_returned(false),
45        has_video_returned(false),
46        audio_devices_label(audio_devices_label),
47        video_devices_label(video_devices_label) {}
48
49  int request_id;
50  GURL origin;
51  bool has_audio_returned;
52  bool has_video_returned;
53  std::string audio_devices_label;
54  std::string video_devices_label;
55  StreamDeviceInfoArray audio_devices;
56  StreamDeviceInfoArray video_devices;
57};
58
59void DeviceRequestMessageFilter::StreamGenerated(
60    const std::string& label,
61    const StreamDeviceInfoArray& audio_devices,
62    const StreamDeviceInfoArray& video_devices) {
63  NOTIMPLEMENTED();
64}
65
66void DeviceRequestMessageFilter::StreamGenerationFailed(
67    const std::string& label) {
68  NOTIMPLEMENTED();
69}
70
71void DeviceRequestMessageFilter::StopGeneratedStream(
72    int render_view_id,
73    const std::string& label) {
74  NOTIMPLEMENTED();
75}
76
77void DeviceRequestMessageFilter::DevicesEnumerated(
78    const std::string& label,
79    const StreamDeviceInfoArray& new_devices) {
80  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
81
82  // Look up the DeviceRequest by id.
83  DeviceRequestList::iterator request_it = requests_.begin();
84  for (; request_it != requests_.end(); ++request_it) {
85    if (label == request_it->audio_devices_label ||
86        label == request_it->video_devices_label) {
87      break;
88    }
89  }
90  DCHECK(request_it != requests_.end());
91
92  StreamDeviceInfoArray* audio_devices = &request_it->audio_devices;
93  StreamDeviceInfoArray* video_devices = &request_it->video_devices;
94
95  // Store hmac'd device ids instead of raw device ids.
96  if (label == request_it->audio_devices_label) {
97    request_it->has_audio_returned = true;
98    DCHECK(audio_devices->empty());
99    HmacDeviceIds(request_it->origin, new_devices, audio_devices);
100  } else {
101    DCHECK(label == request_it->video_devices_label);
102    request_it->has_video_returned = true;
103    DCHECK(video_devices->empty());
104    HmacDeviceIds(request_it->origin, new_devices, video_devices);
105  }
106
107  if (!request_it->has_audio_returned || !request_it->has_video_returned) {
108    // Wait for the rest of the devices to complete.
109    return;
110  }
111
112  // Query for mic and camera permissions.
113  if (!resource_context_->AllowMicAccess(request_it->origin))
114    ClearDeviceLabels(audio_devices);
115  if (!resource_context_->AllowCameraAccess(request_it->origin))
116    ClearDeviceLabels(video_devices);
117
118  // Both audio and video devices are ready for copying.
119  StreamDeviceInfoArray all_devices = *audio_devices;
120  all_devices.insert(
121      all_devices.end(), video_devices->begin(), video_devices->end());
122
123  Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
124
125  media_stream_manager_->CancelRequest(request_it->audio_devices_label);
126  media_stream_manager_->CancelRequest(request_it->video_devices_label);
127  requests_.erase(request_it);
128}
129
130void DeviceRequestMessageFilter::DeviceOpened(
131    const std::string& label,
132    const StreamDeviceInfo& video_device) {
133  NOTIMPLEMENTED();
134}
135
136bool DeviceRequestMessageFilter::OnMessageReceived(const IPC::Message& message,
137                                                   bool* message_was_ok) {
138  bool handled = true;
139  IPC_BEGIN_MESSAGE_MAP_EX(DeviceRequestMessageFilter, message, *message_was_ok)
140    IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources)
141    IPC_MESSAGE_UNHANDLED(handled = false)
142  IPC_END_MESSAGE_MAP_EX()
143  return handled;
144}
145
146void DeviceRequestMessageFilter::OnChannelClosing() {
147  // Since the IPC channel is gone, cancel outstanding device requests.
148  media_stream_manager_->CancelAllRequests(peer_pid());
149
150  requests_.clear();
151}
152
153void DeviceRequestMessageFilter::HmacDeviceIds(
154    const GURL& origin,
155    const StreamDeviceInfoArray& raw_devices,
156    StreamDeviceInfoArray* devices_with_guids) {
157  DCHECK(devices_with_guids);
158
159  // Replace raw ids with hmac'd ids before returning to renderer process.
160  for (StreamDeviceInfoArray::const_iterator device_itr = raw_devices.begin();
161       device_itr != raw_devices.end();
162       ++device_itr) {
163    StreamDeviceInfo current_device_info = *device_itr;
164    current_device_info.device.id =
165        content::GetHMACForMediaDeviceID(origin, device_itr->device.id);
166    devices_with_guids->push_back(current_device_info);
167  }
168}
169
170void DeviceRequestMessageFilter::OnGetSources(int request_id,
171                                              const GURL& security_origin) {
172  // Make request to get audio devices.
173  const std::string& audio_label = media_stream_manager_->EnumerateDevices(
174      this, -1, -1, -1, MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
175  DCHECK(!audio_label.empty());
176
177  // Make request for video devices.
178  const std::string& video_label = media_stream_manager_->EnumerateDevices(
179      this, -1, -1, -1, MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
180  DCHECK(!video_label.empty());
181
182  requests_.push_back(DeviceRequest(
183      request_id, security_origin, audio_label, video_label));
184}
185
186}  // namespace content
187