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/media_stream_ui_proxy.h"
7 #include "content/browser/renderer_host/render_view_host_delegate.h"
8 #include "content/browser/renderer_host/render_view_host_impl.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "media/video/capture/fake_video_capture_device.h"
14 class MediaStreamUIProxy::Core
{
16 explicit Core(const base::WeakPtr
<MediaStreamUIProxy
>& proxy
,
17 RenderViewHostDelegate
* test_render_delegate
);
20 void RequestAccess(const MediaStreamRequest
& request
);
21 void OnStarted(gfx::NativeViewId
* window_id
);
24 void ProcessAccessRequestResponse(const MediaStreamDevices
& devices
,
25 content::MediaStreamRequestResult result
,
26 scoped_ptr
<MediaStreamUI
> stream_ui
);
27 void ProcessStopRequestFromUI();
29 base::WeakPtr
<MediaStreamUIProxy
> proxy_
;
30 scoped_ptr
<MediaStreamUI
> ui_
;
32 RenderViewHostDelegate
* const test_render_delegate_
;
34 // WeakPtr<> is used to RequestMediaAccessPermission() because there is no way
35 // cancel media requests.
36 base::WeakPtrFactory
<Core
> weak_factory_
;
38 DISALLOW_COPY_AND_ASSIGN(Core
);
41 MediaStreamUIProxy::Core::Core(const base::WeakPtr
<MediaStreamUIProxy
>& proxy
,
42 RenderViewHostDelegate
* test_render_delegate
)
44 test_render_delegate_(test_render_delegate
),
48 MediaStreamUIProxy::Core::~Core() {
49 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
52 void MediaStreamUIProxy::Core::RequestAccess(
53 const MediaStreamRequest
& request
) {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
56 RenderViewHostDelegate
* render_delegate
;
58 if (test_render_delegate_
) {
59 render_delegate
= test_render_delegate_
;
61 RenderViewHostImpl
* host
= RenderViewHostImpl::FromID(
62 request
.render_process_id
, request
.render_view_id
);
64 // Tab may have gone away.
65 if (!host
|| !host
->GetDelegate()) {
66 ProcessAccessRequestResponse(
68 MEDIA_DEVICE_INVALID_STATE
,
69 scoped_ptr
<MediaStreamUI
>());
73 render_delegate
= host
->GetDelegate();
76 render_delegate
->RequestMediaAccessPermission(
77 request
, base::Bind(&Core::ProcessAccessRequestResponse
,
78 weak_factory_
.GetWeakPtr()));
81 void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId
* window_id
) {
82 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
84 *window_id
= ui_
->OnStarted(
85 base::Bind(&Core::ProcessStopRequestFromUI
, base::Unretained(this)));
89 void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
90 const MediaStreamDevices
& devices
,
91 content::MediaStreamRequestResult result
,
92 scoped_ptr
<MediaStreamUI
> stream_ui
) {
93 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
95 ui_
= stream_ui
.Pass();
96 BrowserThread::PostTask(
97 BrowserThread::IO
, FROM_HERE
,
98 base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse
,
99 proxy_
, devices
, result
));
102 void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
103 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
105 BrowserThread::PostTask(
106 BrowserThread::IO
, FROM_HERE
,
107 base::Bind(&MediaStreamUIProxy::ProcessStopRequestFromUI
, proxy_
));
111 scoped_ptr
<MediaStreamUIProxy
> MediaStreamUIProxy::Create() {
112 return scoped_ptr
<MediaStreamUIProxy
>(new MediaStreamUIProxy(NULL
));
116 scoped_ptr
<MediaStreamUIProxy
> MediaStreamUIProxy::CreateForTests(
117 RenderViewHostDelegate
* render_delegate
) {
118 return scoped_ptr
<MediaStreamUIProxy
>(
119 new MediaStreamUIProxy(render_delegate
));
122 MediaStreamUIProxy::MediaStreamUIProxy(
123 RenderViewHostDelegate
* test_render_delegate
)
124 : weak_factory_(this) {
125 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
126 core_
.reset(new Core(weak_factory_
.GetWeakPtr(), test_render_delegate
));
129 MediaStreamUIProxy::~MediaStreamUIProxy() {
130 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
131 BrowserThread::DeleteSoon(BrowserThread::UI
, FROM_HERE
, core_
.release());
134 void MediaStreamUIProxy::RequestAccess(
135 const MediaStreamRequest
& request
,
136 const ResponseCallback
& response_callback
) {
137 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
139 response_callback_
= response_callback
;
140 BrowserThread::PostTask(
141 BrowserThread::UI
, FROM_HERE
,
142 base::Bind(&Core::RequestAccess
, base::Unretained(core_
.get()), request
));
145 void MediaStreamUIProxy::OnStarted(const base::Closure
& stop_callback
,
146 const WindowIdCallback
& window_id_callback
) {
147 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
149 stop_callback_
= stop_callback
;
151 // Owned by the PostTaskAndReply callback.
152 gfx::NativeViewId
* window_id
= new gfx::NativeViewId(0);
154 BrowserThread::PostTaskAndReply(
157 base::Bind(&Core::OnStarted
, base::Unretained(core_
.get()), window_id
),
158 base::Bind(&MediaStreamUIProxy::OnWindowId
,
159 weak_factory_
.GetWeakPtr(),
161 base::Owned(window_id
)));
164 void MediaStreamUIProxy::OnWindowId(const WindowIdCallback
& window_id_callback
,
165 gfx::NativeViewId
* window_id
) {
166 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
167 if (!window_id_callback
.is_null())
168 window_id_callback
.Run(*window_id
);
171 void MediaStreamUIProxy::ProcessAccessRequestResponse(
172 const MediaStreamDevices
& devices
,
173 content::MediaStreamRequestResult result
) {
174 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
175 DCHECK(!response_callback_
.is_null());
177 ResponseCallback cb
= response_callback_
;
178 response_callback_
.Reset();
179 cb
.Run(devices
, result
);
182 void MediaStreamUIProxy::ProcessStopRequestFromUI() {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
184 DCHECK(!stop_callback_
.is_null());
186 base::Closure cb
= stop_callback_
;
187 stop_callback_
.Reset();
191 FakeMediaStreamUIProxy::FakeMediaStreamUIProxy()
192 : MediaStreamUIProxy(NULL
) {
195 FakeMediaStreamUIProxy::~FakeMediaStreamUIProxy() {}
197 void FakeMediaStreamUIProxy::SetAvailableDevices(
198 const MediaStreamDevices
& devices
) {
202 void FakeMediaStreamUIProxy::RequestAccess(
203 const MediaStreamRequest
& request
,
204 const ResponseCallback
& response_callback
) {
205 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
207 response_callback_
= response_callback
;
209 MediaStreamDevices devices_to_use
;
210 bool accepted_audio
= false;
211 bool accepted_video
= false;
213 // Use the first capture device of the same media type in the list for the
215 for (MediaStreamDevices::const_iterator it
= devices_
.begin();
216 it
!= devices_
.end(); ++it
) {
217 if (!accepted_audio
&&
218 IsAudioMediaType(request
.audio_type
) &&
219 IsAudioMediaType(it
->type
) &&
220 (request
.requested_audio_device_id
.empty() ||
221 request
.requested_audio_device_id
== it
->id
)) {
222 devices_to_use
.push_back(*it
);
223 accepted_audio
= true;
224 } else if (!accepted_video
&&
225 IsVideoMediaType(request
.video_type
) &&
226 IsVideoMediaType(it
->type
) &&
227 (request
.requested_video_device_id
.empty() ||
228 request
.requested_video_device_id
== it
->id
)) {
229 devices_to_use
.push_back(*it
);
230 accepted_video
= true;
234 // Fail the request if a device exist for the requested type.
235 if ((request
.audio_type
!= MEDIA_NO_SERVICE
&& !accepted_audio
) ||
236 (request
.video_type
!= MEDIA_NO_SERVICE
&& !accepted_video
)) {
237 devices_to_use
.clear();
240 BrowserThread::PostTask(
241 BrowserThread::IO
, FROM_HERE
,
242 base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse
,
243 weak_factory_
.GetWeakPtr(),
245 devices_to_use
.empty() ?
246 MEDIA_DEVICE_NO_HARDWARE
:
250 void FakeMediaStreamUIProxy::OnStarted(
251 const base::Closure
& stop_callback
,
252 const WindowIdCallback
& window_id_callback
) {}
254 } // namespace content