Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / device_request_message_filter.cc
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/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"
12
13 // Clears the MediaStreamDevice.name from all devices in |device_list|.
14 static 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
22 namespace content {
23
24 DeviceRequestMessageFilter::DeviceRequestMessageFilter(
25     ResourceContext* resource_context,
26     MediaStreamManager* media_stream_manager,
27     int render_process_id)
28     : BrowserMessageFilter(MediaStreamMsgStart),
29       resource_context_(resource_context),
30       media_stream_manager_(media_stream_manager),
31       render_process_id_(render_process_id) {
32   DCHECK(resource_context);
33   DCHECK(media_stream_manager);
34 }
35
36 DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
37   // CHECK rather than DCHECK to make sure this never happens in the
38   // wild. We want to be sure due to http://crbug.com/341211
39   CHECK(requests_.empty());
40 }
41
42 struct DeviceRequestMessageFilter::DeviceRequest {
43   DeviceRequest(int request_id,
44                 const GURL& origin,
45                 const std::string& audio_devices_label,
46                 const std::string& video_devices_label)
47       : request_id(request_id),
48         origin(origin),
49         has_audio_returned(false),
50         has_video_returned(false),
51         audio_devices_label(audio_devices_label),
52         video_devices_label(video_devices_label) {}
53
54   int request_id;
55   GURL origin;
56   bool has_audio_returned;
57   bool has_video_returned;
58   std::string audio_devices_label;
59   std::string video_devices_label;
60   StreamDeviceInfoArray audio_devices;
61   StreamDeviceInfoArray video_devices;
62 };
63
64 void DeviceRequestMessageFilter::DevicesEnumerated(
65     int render_view_id,
66     int page_request_id,
67     const std::string& label,
68     const StreamDeviceInfoArray& new_devices) {
69   DCHECK_CURRENTLY_ON(BrowserThread::IO);
70
71   // Look up the DeviceRequest by id.
72   DeviceRequestList::iterator request_it = requests_.begin();
73   for (; request_it != requests_.end(); ++request_it) {
74     if (label == request_it->audio_devices_label ||
75         label == request_it->video_devices_label) {
76       break;
77     }
78   }
79   DCHECK(request_it != requests_.end());
80
81   StreamDeviceInfoArray* audio_devices = &request_it->audio_devices;
82   StreamDeviceInfoArray* video_devices = &request_it->video_devices;
83
84   // Store hmac'd device ids instead of raw device ids.
85   if (label == request_it->audio_devices_label) {
86     request_it->has_audio_returned = true;
87     DCHECK(audio_devices->empty());
88     *audio_devices = new_devices;
89   } else {
90     DCHECK(label == request_it->video_devices_label);
91     request_it->has_video_returned = true;
92     DCHECK(video_devices->empty());
93     *video_devices = new_devices;
94   }
95
96   if (!request_it->has_audio_returned || !request_it->has_video_returned) {
97     // Wait for the rest of the devices to complete.
98     return;
99   }
100
101   // Query for mic and camera permissions.
102   if (!resource_context_->AllowMicAccess(request_it->origin))
103     ClearDeviceLabels(audio_devices);
104   if (!resource_context_->AllowCameraAccess(request_it->origin))
105     ClearDeviceLabels(video_devices);
106
107   // Both audio and video devices are ready for copying.
108   StreamDeviceInfoArray all_devices = *audio_devices;
109   all_devices.insert(
110       all_devices.end(), video_devices->begin(), video_devices->end());
111
112   Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
113
114   media_stream_manager_->CancelRequest(request_it->audio_devices_label);
115   media_stream_manager_->CancelRequest(request_it->video_devices_label);
116   requests_.erase(request_it);
117 }
118
119 bool DeviceRequestMessageFilter::OnMessageReceived(const IPC::Message& message,
120                                                    bool* message_was_ok) {
121   bool handled = true;
122   IPC_BEGIN_MESSAGE_MAP_EX(DeviceRequestMessageFilter, message, *message_was_ok)
123     IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources)
124     IPC_MESSAGE_UNHANDLED(handled = false)
125   IPC_END_MESSAGE_MAP_EX()
126   return handled;
127 }
128
129 void DeviceRequestMessageFilter::OnChannelClosing() {
130   // Since the IPC channel is gone, cancel outstanding device requests.
131   for (DeviceRequestList::iterator request_it = requests_.begin();
132        request_it != requests_.end(); ++request_it) {
133     media_stream_manager_->CancelRequest(request_it->audio_devices_label);
134     media_stream_manager_->CancelRequest(request_it->video_devices_label);
135   }
136   requests_.clear();
137 }
138
139 void DeviceRequestMessageFilter::OnGetSources(int request_id,
140                                               const GURL& security_origin) {
141   if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
142           render_process_id_, security_origin)) {
143     LOG(ERROR) << "Disallowed URL in DRMF::OnGetSources: " << security_origin;
144     return;
145   }
146
147   // Make request to get audio devices.
148   const std::string& audio_label = media_stream_manager_->EnumerateDevices(
149       this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
150       MEDIA_DEVICE_AUDIO_CAPTURE, security_origin);
151   DCHECK(!audio_label.empty());
152
153   // Make request for video devices.
154   const std::string& video_label = media_stream_manager_->EnumerateDevices(
155       this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
156       MEDIA_DEVICE_VIDEO_CAPTURE, security_origin);
157   DCHECK(!video_label.empty());
158
159   requests_.push_back(DeviceRequest(
160       request_id, security_origin, audio_label, video_label));
161 }
162
163 }  // namespace content