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