Add ICU message format support
[chromium-blink-merge.git] / content / browser / renderer_host / media / media_stream_ui_proxy.cc
blob6d79ab457272027e1bfaf0ee7b5f4e17c7b38132
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 "base/command_line.h"
8 #include "content/browser/frame_host/frame_tree_node.h"
9 #include "content/browser/frame_host/render_frame_host_delegate.h"
10 #include "content/browser/frame_host/render_frame_host_impl.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/common/content_switches.h"
13 #include "media/capture/video/fake_video_capture_device.h"
15 namespace content {
17 void SetAndCheckAncestorFlag(MediaStreamRequest* request) {
18 DCHECK_CURRENTLY_ON(BrowserThread::UI);
19 RenderFrameHostImpl* rfh =
20 RenderFrameHostImpl::FromID(request->render_process_id,
21 request->render_frame_id);
23 if (rfh == NULL) {
24 // RenderFrame destroyed before the request is handled?
25 return;
27 FrameTreeNode* node = rfh->frame_tree_node();
29 while (node->parent() != NULL) {
30 if (!node->HasSameOrigin(*node->parent())) {
31 request->all_ancestors_have_same_origin = false;
32 return;
34 node = node->parent();
36 request->all_ancestors_have_same_origin = true;
39 class MediaStreamUIProxy::Core {
40 public:
41 explicit Core(const base::WeakPtr<MediaStreamUIProxy>& proxy,
42 RenderFrameHostDelegate* test_render_delegate);
43 ~Core();
45 void RequestAccess(scoped_ptr<MediaStreamRequest> request);
46 bool CheckAccess(const GURL& security_origin,
47 MediaStreamType type,
48 int process_id,
49 int frame_id);
50 void OnStarted(gfx::NativeViewId* window_id);
52 private:
53 void ProcessAccessRequestResponse(const MediaStreamDevices& devices,
54 content::MediaStreamRequestResult result,
55 scoped_ptr<MediaStreamUI> stream_ui);
56 void ProcessStopRequestFromUI();
57 RenderFrameHostDelegate* GetRenderFrameHostDelegate(int render_process_id,
58 int render_frame_id);
60 base::WeakPtr<MediaStreamUIProxy> proxy_;
61 scoped_ptr<MediaStreamUI> ui_;
63 RenderFrameHostDelegate* const test_render_delegate_;
65 // WeakPtr<> is used to RequestMediaAccessPermission() because there is no way
66 // cancel media requests.
67 base::WeakPtrFactory<Core> weak_factory_;
69 DISALLOW_COPY_AND_ASSIGN(Core);
72 MediaStreamUIProxy::Core::Core(const base::WeakPtr<MediaStreamUIProxy>& proxy,
73 RenderFrameHostDelegate* test_render_delegate)
74 : proxy_(proxy),
75 test_render_delegate_(test_render_delegate),
76 weak_factory_(this) {
79 MediaStreamUIProxy::Core::~Core() {
80 DCHECK_CURRENTLY_ON(BrowserThread::UI);
83 void MediaStreamUIProxy::Core::RequestAccess(
84 scoped_ptr<MediaStreamRequest> request) {
85 DCHECK_CURRENTLY_ON(BrowserThread::UI);
87 RenderFrameHostDelegate* render_delegate = GetRenderFrameHostDelegate(
88 request->render_process_id, request->render_frame_id);
90 // Tab may have gone away, or has no delegate from which to request access.
91 if (!render_delegate) {
92 ProcessAccessRequestResponse(MediaStreamDevices(),
93 MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
94 scoped_ptr<MediaStreamUI>());
95 return;
97 SetAndCheckAncestorFlag(request.get());
99 render_delegate->RequestMediaAccessPermission(
100 *request, base::Bind(&Core::ProcessAccessRequestResponse,
101 weak_factory_.GetWeakPtr()));
104 bool MediaStreamUIProxy::Core::CheckAccess(const GURL& security_origin,
105 MediaStreamType type,
106 int render_process_id,
107 int render_frame_id) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI);
110 RenderFrameHostDelegate* render_delegate =
111 GetRenderFrameHostDelegate(render_process_id, render_frame_id);
112 if (!render_delegate)
113 return false;
115 return render_delegate->CheckMediaAccessPermission(security_origin, type);
118 void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
119 DCHECK_CURRENTLY_ON(BrowserThread::UI);
120 if (ui_) {
121 *window_id = ui_->OnStarted(
122 base::Bind(&Core::ProcessStopRequestFromUI, base::Unretained(this)));
126 void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
127 const MediaStreamDevices& devices,
128 content::MediaStreamRequestResult result,
129 scoped_ptr<MediaStreamUI> stream_ui) {
130 DCHECK_CURRENTLY_ON(BrowserThread::UI);
132 ui_ = stream_ui.Pass();
133 BrowserThread::PostTask(
134 BrowserThread::IO, FROM_HERE,
135 base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse,
136 proxy_, devices, result));
139 void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
140 DCHECK_CURRENTLY_ON(BrowserThread::UI);
142 BrowserThread::PostTask(
143 BrowserThread::IO, FROM_HERE,
144 base::Bind(&MediaStreamUIProxy::ProcessStopRequestFromUI, proxy_));
147 RenderFrameHostDelegate* MediaStreamUIProxy::Core::GetRenderFrameHostDelegate(
148 int render_process_id,
149 int render_frame_id) {
150 if (test_render_delegate_)
151 return test_render_delegate_;
152 RenderFrameHostImpl* host =
153 RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
154 return host ? host->delegate() : NULL;
157 // static
158 scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
159 return scoped_ptr<MediaStreamUIProxy>(new MediaStreamUIProxy(NULL));
162 // static
163 scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::CreateForTests(
164 RenderFrameHostDelegate* render_delegate) {
165 return scoped_ptr<MediaStreamUIProxy>(
166 new MediaStreamUIProxy(render_delegate));
169 MediaStreamUIProxy::MediaStreamUIProxy(
170 RenderFrameHostDelegate* test_render_delegate)
171 : weak_factory_(this) {
172 DCHECK_CURRENTLY_ON(BrowserThread::IO);
173 core_.reset(new Core(weak_factory_.GetWeakPtr(), test_render_delegate));
176 MediaStreamUIProxy::~MediaStreamUIProxy() {
177 DCHECK_CURRENTLY_ON(BrowserThread::IO);
180 void MediaStreamUIProxy::RequestAccess(
181 scoped_ptr<MediaStreamRequest> request,
182 const ResponseCallback& response_callback) {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO);
185 response_callback_ = response_callback;
186 BrowserThread::PostTask(
187 BrowserThread::UI, FROM_HERE,
188 base::Bind(&Core::RequestAccess, base::Unretained(core_.get()),
189 base::Passed(&request)));
192 void MediaStreamUIProxy::CheckAccess(
193 const GURL& security_origin,
194 MediaStreamType type,
195 int render_process_id,
196 int render_frame_id,
197 const base::Callback<void(bool)>& callback) {
198 DCHECK_CURRENTLY_ON(BrowserThread::IO);
200 BrowserThread::PostTaskAndReplyWithResult(
201 BrowserThread::UI,
202 FROM_HERE,
203 base::Bind(&Core::CheckAccess,
204 base::Unretained(core_.get()),
205 security_origin,
206 type,
207 render_process_id,
208 render_frame_id),
209 base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
210 weak_factory_.GetWeakPtr(),
211 callback));
214 void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
215 const WindowIdCallback& window_id_callback) {
216 DCHECK_CURRENTLY_ON(BrowserThread::IO);
218 stop_callback_ = stop_callback;
220 // Owned by the PostTaskAndReply callback.
221 gfx::NativeViewId* window_id = new gfx::NativeViewId(0);
223 BrowserThread::PostTaskAndReply(
224 BrowserThread::UI,
225 FROM_HERE,
226 base::Bind(&Core::OnStarted, base::Unretained(core_.get()), window_id),
227 base::Bind(&MediaStreamUIProxy::OnWindowId,
228 weak_factory_.GetWeakPtr(),
229 window_id_callback,
230 base::Owned(window_id)));
233 void MediaStreamUIProxy::ProcessAccessRequestResponse(
234 const MediaStreamDevices& devices,
235 content::MediaStreamRequestResult result) {
236 DCHECK_CURRENTLY_ON(BrowserThread::IO);
237 DCHECK(!response_callback_.is_null());
239 ResponseCallback cb = response_callback_;
240 response_callback_.Reset();
241 cb.Run(devices, result);
244 void MediaStreamUIProxy::ProcessStopRequestFromUI() {
245 DCHECK_CURRENTLY_ON(BrowserThread::IO);
246 DCHECK(!stop_callback_.is_null());
248 base::Closure cb = stop_callback_;
249 stop_callback_.Reset();
250 cb.Run();
253 void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
254 gfx::NativeViewId* window_id) {
255 DCHECK_CURRENTLY_ON(BrowserThread::IO);
256 if (!window_id_callback.is_null())
257 window_id_callback.Run(*window_id);
260 void MediaStreamUIProxy::OnCheckedAccess(
261 const base::Callback<void(bool)>& callback,
262 bool have_access) {
263 DCHECK_CURRENTLY_ON(BrowserThread::IO);
264 if (!callback.is_null())
265 callback.Run(have_access);
268 FakeMediaStreamUIProxy::FakeMediaStreamUIProxy()
269 : MediaStreamUIProxy(NULL),
270 mic_access_(true),
271 camera_access_(true) {
274 FakeMediaStreamUIProxy::~FakeMediaStreamUIProxy() {}
276 void FakeMediaStreamUIProxy::SetAvailableDevices(
277 const MediaStreamDevices& devices) {
278 devices_ = devices;
281 void FakeMediaStreamUIProxy::SetMicAccess(bool access) {
282 mic_access_ = access;
285 void FakeMediaStreamUIProxy::SetCameraAccess(bool access) {
286 camera_access_ = access;
289 void FakeMediaStreamUIProxy::RequestAccess(
290 scoped_ptr<MediaStreamRequest> request,
291 const ResponseCallback& response_callback) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO);
294 response_callback_ = response_callback;
296 if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
297 switches::kUseFakeUIForMediaStream) == "deny") {
298 // Immediately deny the request.
299 BrowserThread::PostTask(
300 BrowserThread::IO, FROM_HERE,
301 base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse,
302 weak_factory_.GetWeakPtr(),
303 MediaStreamDevices(),
304 MEDIA_DEVICE_PERMISSION_DENIED));
305 return;
308 MediaStreamDevices devices_to_use;
309 bool accepted_audio = false;
310 bool accepted_video = false;
312 // Use the first capture device of the same media type in the list for the
313 // fake UI.
314 for (MediaStreamDevices::const_iterator it = devices_.begin();
315 it != devices_.end(); ++it) {
316 if (!accepted_audio &&
317 IsAudioInputMediaType(request->audio_type) &&
318 IsAudioInputMediaType(it->type) &&
319 (request->requested_audio_device_id.empty() ||
320 request->requested_audio_device_id == it->id)) {
321 devices_to_use.push_back(*it);
322 accepted_audio = true;
323 } else if (!accepted_video &&
324 IsVideoMediaType(request->video_type) &&
325 IsVideoMediaType(it->type) &&
326 (request->requested_video_device_id.empty() ||
327 request->requested_video_device_id == it->id)) {
328 devices_to_use.push_back(*it);
329 accepted_video = true;
333 // Fail the request if a device doesn't exist for the requested type.
334 if ((request->audio_type != MEDIA_NO_SERVICE && !accepted_audio) ||
335 (request->video_type != MEDIA_NO_SERVICE && !accepted_video)) {
336 devices_to_use.clear();
339 BrowserThread::PostTask(
340 BrowserThread::IO, FROM_HERE,
341 base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse,
342 weak_factory_.GetWeakPtr(),
343 devices_to_use,
344 devices_to_use.empty() ?
345 MEDIA_DEVICE_NO_HARDWARE :
346 MEDIA_DEVICE_OK));
349 void FakeMediaStreamUIProxy::CheckAccess(
350 const GURL& security_origin,
351 MediaStreamType type,
352 int render_process_id,
353 int render_frame_id,
354 const base::Callback<void(bool)>& callback) {
355 DCHECK_CURRENTLY_ON(BrowserThread::IO);
356 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
357 type == MEDIA_DEVICE_VIDEO_CAPTURE);
359 bool have_access = false;
360 if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
361 switches::kUseFakeUIForMediaStream) != "deny") {
362 have_access =
363 type == MEDIA_DEVICE_AUDIO_CAPTURE ? mic_access_ : camera_access_;
366 BrowserThread::PostTask(
367 BrowserThread::IO,
368 FROM_HERE,
369 base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
370 weak_factory_.GetWeakPtr(),
371 callback,
372 have_access));
373 return;
376 void FakeMediaStreamUIProxy::OnStarted(
377 const base::Closure& stop_callback,
378 const WindowIdCallback& window_id_callback) {}
380 } // namespace content