Chromium Code Reviews| 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 |