OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/media/media_stream_manager.h" | 5 #include "content/browser/renderer_host/media/media_stream_manager.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "content/browser/renderer_host/media/media_stream_requester.h" | 24 #include "content/browser/renderer_host/media/media_stream_requester.h" |
25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
26 #include "content/browser/renderer_host/media/video_capture_manager.h" | 26 #include "content/browser/renderer_host/media/video_capture_manager.h" |
27 #include "content/browser/renderer_host/render_process_host_impl.h" | 27 #include "content/browser/renderer_host/render_process_host_impl.h" |
28 #include "content/public/browser/browser_thread.h" | 28 #include "content/public/browser/browser_thread.h" |
29 #include "content/public/browser/content_browser_client.h" | 29 #include "content/public/browser/content_browser_client.h" |
30 #include "content/public/browser/media_device_id.h" | 30 #include "content/public/browser/media_device_id.h" |
31 #include "content/public/browser/media_observer.h" | 31 #include "content/public/browser/media_observer.h" |
32 #include "content/public/browser/media_request_state.h" | 32 #include "content/public/browser/media_request_state.h" |
33 #include "content/public/browser/render_process_host.h" | 33 #include "content/public/browser/render_process_host.h" |
34 #include "content/public/common/content_client.h" | |
34 #include "content/public/common/content_switches.h" | 35 #include "content/public/common/content_switches.h" |
35 #include "content/public/common/media_stream_request.h" | 36 #include "content/public/common/media_stream_request.h" |
36 #include "media/audio/audio_manager_base.h" | 37 #include "media/audio/audio_manager_base.h" |
37 #include "media/audio/audio_parameters.h" | 38 #include "media/audio/audio_parameters.h" |
38 #include "media/base/channel_layout.h" | 39 #include "media/base/channel_layout.h" |
39 #include "media/base/media_switches.h" | 40 #include "media/base/media_switches.h" |
40 #include "media/video/capture/video_capture_device_factory.h" | 41 #include "media/video/capture/video_capture_device_factory.h" |
41 #include "url/gurl.h" | 42 #include "url/gurl.h" |
42 | 43 |
43 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 // several subclasses of DeviceRequest and move some of the responsibility of | 192 // several subclasses of DeviceRequest and move some of the responsibility of |
192 // the MediaStreamManager to the subclasses to get rid of the way too many if | 193 // the MediaStreamManager to the subclasses to get rid of the way too many if |
193 // statements in MediaStreamManager. | 194 // statements in MediaStreamManager. |
194 class MediaStreamManager::DeviceRequest { | 195 class MediaStreamManager::DeviceRequest { |
195 public: | 196 public: |
196 DeviceRequest(MediaStreamRequester* requester, | 197 DeviceRequest(MediaStreamRequester* requester, |
197 int requesting_process_id, | 198 int requesting_process_id, |
198 int requesting_frame_id, | 199 int requesting_frame_id, |
199 int page_request_id, | 200 int page_request_id, |
200 const GURL& security_origin, | 201 const GURL& security_origin, |
201 bool have_permission, | |
202 bool user_gesture, | 202 bool user_gesture, |
203 MediaStreamRequestType request_type, | 203 MediaStreamRequestType request_type, |
204 const StreamOptions& options, | 204 const StreamOptions& options, |
205 const ResourceContext::SaltCallback& salt_callback) | 205 const ResourceContext::SaltCallback& salt_callback) |
206 : requester(requester), | 206 : requester(requester), |
207 requesting_process_id(requesting_process_id), | 207 requesting_process_id(requesting_process_id), |
208 requesting_frame_id(requesting_frame_id), | 208 requesting_frame_id(requesting_frame_id), |
209 page_request_id(page_request_id), | 209 page_request_id(page_request_id), |
210 security_origin(security_origin), | 210 security_origin(security_origin), |
211 have_permission(have_permission), | |
212 user_gesture(user_gesture), | 211 user_gesture(user_gesture), |
213 request_type(request_type), | 212 request_type(request_type), |
214 options(options), | 213 options(options), |
215 salt_callback(salt_callback), | 214 salt_callback(salt_callback), |
216 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED), | 215 state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED), |
217 audio_type_(MEDIA_NO_SERVICE), | 216 audio_type_(MEDIA_NO_SERVICE), |
218 video_type_(MEDIA_NO_SERVICE) { | 217 video_type_(MEDIA_NO_SERVICE) { |
219 } | 218 } |
220 | 219 |
221 ~DeviceRequest() {} | 220 ~DeviceRequest() {} |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 // will receive a handle to the MediaStream. This may be different from | 317 // will receive a handle to the MediaStream. This may be different from |
319 // MediaStreamRequest::render_frame_id which in the tab capture case | 318 // MediaStreamRequest::render_frame_id which in the tab capture case |
320 // specifies the target renderer from which audio and video is captured. | 319 // specifies the target renderer from which audio and video is captured. |
321 const int requesting_frame_id; | 320 const int requesting_frame_id; |
322 | 321 |
323 // An ID the render frame provided to identify this request. | 322 // An ID the render frame provided to identify this request. |
324 const int page_request_id; | 323 const int page_request_id; |
325 | 324 |
326 const GURL security_origin; | 325 const GURL security_origin; |
327 | 326 |
328 // This is used when enumerating devices; if we don't have device access | |
329 // permission, we remove the device label. | |
330 bool have_permission; | |
331 | |
332 const bool user_gesture; | 327 const bool user_gesture; |
333 | 328 |
334 const MediaStreamRequestType request_type; | 329 const MediaStreamRequestType request_type; |
335 | 330 |
336 const StreamOptions options; | 331 const StreamOptions options; |
337 | 332 |
338 ResourceContext::SaltCallback salt_callback; | 333 ResourceContext::SaltCallback salt_callback; |
339 | 334 |
340 StreamDeviceInfoArray devices; | 335 StreamDeviceInfoArray devices; |
341 | 336 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 const MediaRequestResponseCallback& callback) { | 421 const MediaRequestResponseCallback& callback) { |
427 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 422 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
428 | 423 |
429 // TODO(perkj): The argument list with NULL parameters to DeviceRequest | 424 // TODO(perkj): The argument list with NULL parameters to DeviceRequest |
430 // suggests that this is the wrong design. Can this be refactored? | 425 // suggests that this is the wrong design. Can this be refactored? |
431 DeviceRequest* request = new DeviceRequest(NULL, | 426 DeviceRequest* request = new DeviceRequest(NULL, |
432 render_process_id, | 427 render_process_id, |
433 render_frame_id, | 428 render_frame_id, |
434 page_request_id, | 429 page_request_id, |
435 security_origin, | 430 security_origin, |
436 true, | |
437 false, // user gesture | 431 false, // user gesture |
438 MEDIA_DEVICE_ACCESS, | 432 MEDIA_DEVICE_ACCESS, |
439 options, | 433 options, |
440 base::Bind(&ReturnEmptySalt)); | 434 base::Bind(&ReturnEmptySalt)); |
441 | 435 |
442 const std::string& label = AddRequest(request); | 436 const std::string& label = AddRequest(request); |
443 | 437 |
444 request->callback = callback; | 438 request->callback = callback; |
445 // Post a task and handle the request asynchronously. The reason is that the | 439 // Post a task and handle the request asynchronously. The reason is that the |
446 // requester won't have a label for the request until this function returns | 440 // requester won't have a label for the request until this function returns |
(...skipping 20 matching lines...) Expand all Loading... | |
467 if (CommandLine::ForCurrentProcess()->HasSwitch( | 461 if (CommandLine::ForCurrentProcess()->HasSwitch( |
468 switches::kUseFakeUIForMediaStream)) { | 462 switches::kUseFakeUIForMediaStream)) { |
469 UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); | 463 UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); |
470 } | 464 } |
471 | 465 |
472 DeviceRequest* request = new DeviceRequest(requester, | 466 DeviceRequest* request = new DeviceRequest(requester, |
473 render_process_id, | 467 render_process_id, |
474 render_frame_id, | 468 render_frame_id, |
475 page_request_id, | 469 page_request_id, |
476 security_origin, | 470 security_origin, |
477 true, | |
478 user_gesture, | 471 user_gesture, |
479 MEDIA_GENERATE_STREAM, | 472 MEDIA_GENERATE_STREAM, |
480 options, | 473 options, |
481 sc); | 474 sc); |
482 | 475 |
483 const std::string& label = AddRequest(request); | 476 const std::string& label = AddRequest(request); |
484 | 477 |
485 // Post a task and handle the request asynchronously. The reason is that the | 478 // Post a task and handle the request asynchronously. The reason is that the |
486 // requester won't have a label for the request until this function returns | 479 // requester won't have a label for the request until this function returns |
487 // and thus can not handle a response. Using base::Unretained is safe since | 480 // and thus can not handle a response. Using base::Unretained is safe since |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 } | 643 } |
651 } | 644 } |
652 | 645 |
653 std::string MediaStreamManager::EnumerateDevices( | 646 std::string MediaStreamManager::EnumerateDevices( |
654 MediaStreamRequester* requester, | 647 MediaStreamRequester* requester, |
655 int render_process_id, | 648 int render_process_id, |
656 int render_frame_id, | 649 int render_frame_id, |
657 const ResourceContext::SaltCallback& sc, | 650 const ResourceContext::SaltCallback& sc, |
658 int page_request_id, | 651 int page_request_id, |
659 MediaStreamType type, | 652 MediaStreamType type, |
660 const GURL& security_origin, | 653 const GURL& security_origin) { |
661 bool have_permission) { | |
662 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 654 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
663 DCHECK(requester); | 655 DCHECK(requester); |
664 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || | 656 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || |
665 type == MEDIA_DEVICE_VIDEO_CAPTURE || | 657 type == MEDIA_DEVICE_VIDEO_CAPTURE || |
666 type == MEDIA_DEVICE_AUDIO_OUTPUT); | 658 type == MEDIA_DEVICE_AUDIO_OUTPUT); |
667 | 659 |
668 DeviceRequest* request = new DeviceRequest(requester, | 660 DeviceRequest* request = new DeviceRequest(requester, |
669 render_process_id, | 661 render_process_id, |
670 render_frame_id, | 662 render_frame_id, |
671 page_request_id, | 663 page_request_id, |
672 security_origin, | 664 security_origin, |
673 have_permission, | |
674 false, // user gesture | 665 false, // user gesture |
675 MEDIA_ENUMERATE_DEVICES, | 666 MEDIA_ENUMERATE_DEVICES, |
676 StreamOptions(), | 667 StreamOptions(), |
677 sc); | 668 sc); |
678 if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT) | 669 if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT) |
679 request->SetAudioType(type); | 670 request->SetAudioType(type); |
680 else if (IsVideoMediaType(type)) | 671 else if (IsVideoMediaType(type)) |
681 request->SetVideoType(type); | 672 request->SetVideoType(type); |
682 | 673 |
683 const std::string& label = AddRequest(request); | 674 const std::string& label = AddRequest(request); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
810 options.mandatory_video.push_back( | 801 options.mandatory_video.push_back( |
811 StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id)); | 802 StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id)); |
812 } else { | 803 } else { |
813 NOTREACHED(); | 804 NOTREACHED(); |
814 } | 805 } |
815 DeviceRequest* request = new DeviceRequest(requester, | 806 DeviceRequest* request = new DeviceRequest(requester, |
816 render_process_id, | 807 render_process_id, |
817 render_frame_id, | 808 render_frame_id, |
818 page_request_id, | 809 page_request_id, |
819 security_origin, | 810 security_origin, |
820 true, | |
821 false, // user gesture | 811 false, // user gesture |
822 MEDIA_OPEN_DEVICE, | 812 MEDIA_OPEN_DEVICE, |
823 options, | 813 options, |
824 sc); | 814 sc); |
825 | 815 |
826 const std::string& label = AddRequest(request); | 816 const std::string& label = AddRequest(request); |
827 // Post a task and handle the request asynchronously. The reason is that the | 817 // Post a task and handle the request asynchronously. The reason is that the |
828 // requester won't have a label for the request until this function returns | 818 // requester won't have a label for the request until this function returns |
829 // and thus can not handle a response. Using base::Unretained is safe since | 819 // and thus can not handle a response. Using base::Unretained is safe since |
830 // MediaStreamManager is deleted on the UI thread, after the IO thread has | 820 // MediaStreamManager is deleted on the UI thread, after the IO thread has |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1460 const StreamDeviceInfoArray& requested_devices = request->devices; | 1450 const StreamDeviceInfoArray& requested_devices = request->devices; |
1461 request->requester->DeviceOpened(request->requesting_frame_id, | 1451 request->requester->DeviceOpened(request->requesting_frame_id, |
1462 request->page_request_id, | 1452 request->page_request_id, |
1463 label, requested_devices.front()); | 1453 label, requested_devices.front()); |
1464 } | 1454 } |
1465 | 1455 |
1466 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, | 1456 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label, |
1467 DeviceRequest* request) { | 1457 DeviceRequest* request) { |
1468 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1458 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1469 DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES); | 1459 DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES); |
1460 DCHECK(((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || | |
1461 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) && | |
1462 request->video_type() == MEDIA_NO_SERVICE) || | |
1463 (request->audio_type() == MEDIA_NO_SERVICE && | |
1464 request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE)); | |
1470 | 1465 |
1471 if (request->security_origin.is_valid()) { | 1466 if (request->security_origin.is_valid()) { |
1472 for (StreamDeviceInfoArray::iterator it = request->devices.begin(); | 1467 for (StreamDeviceInfoArray::iterator it = request->devices.begin(); |
1473 it != request->devices.end(); ++it) { | 1468 it != request->devices.end(); ++it) { |
1474 TranslateDeviceIdToSourceId(request, &it->device); | 1469 TranslateDeviceIdToSourceId(request, &it->device); |
1475 } | 1470 } |
1476 } else { | 1471 } else { |
1477 request->devices.clear(); | 1472 request->devices.clear(); |
1478 } | 1473 } |
1479 | 1474 |
1480 if (!request->have_permission) | 1475 // Output label permissions are based on input permission. |
1476 MediaStreamType type = | |
1477 request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || | |
1478 request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT | |
1479 ? MEDIA_DEVICE_AUDIO_CAPTURE | |
1480 : MEDIA_DEVICE_VIDEO_CAPTURE; | |
1481 | |
1482 BrowserThread::PostTaskAndReplyWithResult( | |
1483 BrowserThread::UI, | |
1484 FROM_HERE, | |
1485 base::Bind(&MediaStreamManager::CheckMediaAccessOnUI, | |
1486 base::Unretained(this), | |
1487 request->requesting_process_id, | |
1488 request->security_origin, | |
1489 type), | |
1490 base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse, | |
1491 base::Unretained(this), | |
1492 label)); | |
1493 } | |
1494 | |
1495 bool MediaStreamManager::CheckMediaAccessOnUI(int render_process_id, | |
perkj_chrome
2014/08/29 09:38:10
CheckMediaAccessPermissionsOnUi?
Henrik Grunell
2014/08/29 11:20:08
Yes, that's good. Even ...OnUIThread() so that it'
| |
1496 const GURL& security_origin, | |
1497 MediaStreamType type) { | |
1498 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
1499 | |
1500 RenderProcessHost* host = | |
1501 RenderProcessHost::FromID(render_process_id); | |
1502 if (!host) { | |
1503 // This can happen if the renderer goes away during the lifetime of a | |
1504 // request. | |
1505 return false; | |
1506 } | |
1507 content::BrowserContext* context = host->GetBrowserContext(); | |
1508 DCHECK(context); | |
1509 return GetContentClient()->browser()->CheckMediaAccessPermission( | |
1510 context, | |
1511 security_origin, | |
1512 type); | |
1513 } | |
1514 | |
1515 void MediaStreamManager::HandleCheckMediaAccessResponse( | |
1516 const std::string& label, | |
1517 bool have_access) { | |
1518 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
1519 | |
1520 DeviceRequest* request = FindRequest(label); | |
1521 if (!request) { | |
1522 // This can happen if the request was cancelled. | |
1523 DVLOG(1) << "The request with label " << label << " does not exist."; | |
1524 return; | |
1525 } | |
1526 | |
1527 if (!have_access) | |
1481 ClearDeviceLabels(&request->devices); | 1528 ClearDeviceLabels(&request->devices); |
1482 | 1529 |
1483 request->requester->DevicesEnumerated( | 1530 request->requester->DevicesEnumerated( |
1484 request->requesting_frame_id, | 1531 request->requesting_frame_id, |
1485 request->page_request_id, | 1532 request->page_request_id, |
1486 label, | 1533 label, |
1487 request->devices); | 1534 request->devices); |
1488 | 1535 |
1489 // TODO(tommi): | 1536 // TODO(tommi): |
perkj_chrome
2014/08/29 09:38:10
Not this cl maybe, but is this todo still relevant
Henrik Grunell
2014/08/29 11:20:08
I think we still should separate the notification
| |
1490 // Ideally enumeration requests should be deleted once they have been served | 1537 // Ideally enumeration requests should be deleted once they have been served |
1491 // (as any request). However, this implementation mixes requests and | 1538 // (as any request). However, this implementation mixes requests and |
1492 // notifications together so enumeration requests are kept open by some | 1539 // notifications together so enumeration requests are kept open by some |
1493 // implementations (only Pepper?) and enumerations are done again when | 1540 // implementations (only Pepper?) and enumerations are done again when |
1494 // device notifications are fired. | 1541 // device notifications are fired. |
1495 // Implementations that just want to request the device list and be done | 1542 // Implementations that just want to request the device list and be done |
1496 // (e.g. DeviceRequestMessageFilter), they must (confusingly) call | 1543 // (e.g. DeviceRequestMessageFilter), they must (confusingly) call |
1497 // CancelRequest() after the request has been fulfilled. This is not | 1544 // CancelRequest() after the request has been fulfilled. This is not |
1498 // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest) | 1545 // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest) |
1499 // and can lead to subtle bugs (requests not deleted at all deleted too | 1546 // and can lead to subtle bugs (requests not deleted at all deleted too |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2039 if (it->device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { | 2086 if (it->device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) { |
2040 video_capture_manager_->SetDesktopCaptureWindowId(it->session_id, | 2087 video_capture_manager_->SetDesktopCaptureWindowId(it->session_id, |
2041 window_id); | 2088 window_id); |
2042 break; | 2089 break; |
2043 } | 2090 } |
2044 } | 2091 } |
2045 } | 2092 } |
2046 } | 2093 } |
2047 | 2094 |
2048 } // namespace content | 2095 } // namespace content |
OLD | NEW |