| 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/audio_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_renderer_host.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/shared_memory.h" | 14 #include "base/memory/shared_memory.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/process/process.h" | 16 #include "base/process/process.h" |
| 17 #include "content/browser/bad_message.h" | 17 #include "content/browser/bad_message.h" |
| 18 #include "content/browser/browser_main_loop.h" | 18 #include "content/browser/browser_main_loop.h" |
| 19 #include "content/browser/child_process_security_policy_impl.h" | |
| 20 #include "content/browser/media/audio_stream_monitor.h" | 19 #include "content/browser/media/audio_stream_monitor.h" |
| 21 #include "content/browser/media/capture/audio_mirroring_manager.h" | 20 #include "content/browser/media/capture/audio_mirroring_manager.h" |
| 22 #include "content/browser/media/media_internals.h" | 21 #include "content/browser/media/media_internals.h" |
| 23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 22 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 24 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 23 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 25 #include "content/browser/renderer_host/media/media_stream_manager.h" | 24 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 26 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
| 27 #include "content/browser/renderer_host/render_widget_host_impl.h" | 26 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 28 #include "content/common/media/audio_messages.h" | 27 #include "content/common/media/audio_messages.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 28 #include "content/public/browser/content_browser_client.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 49 LAZY_INSTANCE_INITIALIZER; | 48 LAZY_INSTANCE_INITIALIZER; |
| 50 | 49 |
| 51 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( | 50 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( |
| 52 int stream_id, | 51 int stream_id, |
| 53 bool authorized, | 52 bool authorized, |
| 54 const std::string& device_unique_id) { | 53 const std::string& device_unique_id) { |
| 55 return std::make_pair(stream_id, | 54 return std::make_pair(stream_id, |
| 56 std::make_pair(authorized, device_unique_id)); | 55 std::make_pair(authorized, device_unique_id)); |
| 57 } | 56 } |
| 58 | 57 |
| 59 GURL ConvertToGURL(const url::Origin& origin) { | |
| 60 return origin.unique() ? GURL() : GURL(origin.Serialize()); | |
| 61 } | |
| 62 | |
| 63 bool IsValidDeviceId(const std::string& device_id) { | 58 bool IsValidDeviceId(const std::string& device_id) { |
| 64 static const std::string::size_type kValidLength = 64; | 59 static const std::string::size_type kValidLength = 64; |
| 65 | 60 |
| 66 if (device_id.empty() || | 61 if (device_id.empty() || |
| 67 device_id == media::AudioDeviceDescription::kDefaultDeviceId || | 62 device_id == media::AudioDeviceDescription::kDefaultDeviceId || |
| 68 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { | 63 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { |
| 69 return true; | 64 return true; |
| 70 } | 65 } |
| 71 | 66 |
| 72 if (device_id.length() != kValidLength) | 67 if (device_id.length() != kValidLength) |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, | 426 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 432 static_cast<media::ChannelLayout>( | 427 static_cast<media::ChannelLayout>( |
| 433 info->device.matched_output.channel_layout), | 428 info->device.matched_output.channel_layout), |
| 434 info->device.matched_output.sample_rate, 16, | 429 info->device.matched_output.sample_rate, 16, |
| 435 info->device.matched_output.frames_per_buffer); | 430 info->device.matched_output.frames_per_buffer); |
| 436 output_params.set_effects(info->device.matched_output.effects); | 431 output_params.set_effects(info->device.matched_output.effects); |
| 437 authorizations_.insert(MakeAuthorizationData( | 432 authorizations_.insert(MakeAuthorizationData( |
| 438 stream_id, true, info->device.matched_output_device_id)); | 433 stream_id, true, info->device.matched_output_device_id)); |
| 439 MaybeFixAudioParameters(&output_params); | 434 MaybeFixAudioParameters(&output_params); |
| 440 // Hash matched device id and pass it to the renderer | 435 // Hash matched device id and pass it to the renderer |
| 441 GURL gurl_security_origin = ConvertToGURL(security_origin); | |
| 442 Send(new AudioMsg_NotifyDeviceAuthorized( | 436 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 443 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, | 437 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, |
| 444 GetHMACForMediaDeviceID(salt_callback_, gurl_security_origin, | 438 GetHMACForMediaDeviceID(salt_callback_, security_origin, |
| 445 info->device.matched_output_device_id))); | 439 info->device.matched_output_device_id))); |
| 446 return; | 440 return; |
| 447 } | 441 } |
| 448 } | 442 } |
| 449 | 443 |
| 450 authorizations_.insert( | 444 authorizations_.insert( |
| 451 MakeAuthorizationData(stream_id, false, std::string())); | 445 MakeAuthorizationData(stream_id, false, std::string())); |
| 452 GURL gurl_security_origin = ConvertToGURL(security_origin); | |
| 453 CheckOutputDeviceAccess( | 446 CheckOutputDeviceAccess( |
| 454 render_frame_id, device_id, gurl_security_origin, | 447 render_frame_id, device_id, security_origin, |
| 455 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id, | 448 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id, |
| 456 device_id, gurl_security_origin)); | 449 device_id, security_origin)); |
| 457 } | 450 } |
| 458 | 451 |
| 459 void AudioRendererHost::OnDeviceAuthorized(int stream_id, | 452 void AudioRendererHost::OnDeviceAuthorized(int stream_id, |
| 460 const std::string& device_id, | 453 const std::string& device_id, |
| 461 const GURL& gurl_security_origin, | 454 const url::Origin& security_origin, |
| 462 bool have_access) { | 455 bool have_access) { |
| 463 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 456 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 464 const auto& auth_data = authorizations_.find(stream_id); | 457 const auto& auth_data = authorizations_.find(stream_id); |
| 465 | 458 |
| 466 // A close request was received while access check was in progress. | 459 // A close request was received while access check was in progress. |
| 467 if (auth_data == authorizations_.end()) | 460 if (auth_data == authorizations_.end()) |
| 468 return; | 461 return; |
| 469 | 462 |
| 470 if (!have_access) { | 463 if (!have_access) { |
| 471 authorizations_.erase(auth_data); | 464 authorizations_.erase(auth_data); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 483 !media_stream_manager_->audio_output_device_enumerator() | 476 !media_stream_manager_->audio_output_device_enumerator() |
| 484 ->IsCacheEnabled()) { | 477 ->IsCacheEnabled()) { |
| 485 base::PostTaskAndReplyWithResult( | 478 base::PostTaskAndReplyWithResult( |
| 486 audio_manager_->GetTaskRunner(), FROM_HERE, | 479 audio_manager_->GetTaskRunner(), FROM_HERE, |
| 487 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), | 480 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), |
| 488 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, | 481 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, |
| 489 true)); | 482 true)); |
| 490 } else { | 483 } else { |
| 491 media_stream_manager_->audio_output_device_enumerator()->Enumerate( | 484 media_stream_manager_->audio_output_device_enumerator()->Enumerate( |
| 492 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, | 485 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, |
| 493 gurl_security_origin, | 486 security_origin, |
| 494 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, | 487 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, |
| 495 stream_id))); | 488 stream_id))); |
| 496 } | 489 } |
| 497 } | 490 } |
| 498 | 491 |
| 499 void AudioRendererHost::OnDeviceIDTranslated( | 492 void AudioRendererHost::OnDeviceIDTranslated( |
| 500 int stream_id, | 493 int stream_id, |
| 501 bool device_found, | 494 bool device_found, |
| 502 const AudioOutputDeviceInfo& device_info) { | 495 const AudioOutputDeviceInfo& device_info) { |
| 503 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 496 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 AudioEntry* entry = it->second; | 733 AudioEntry* entry = it->second; |
| 741 if (entry->render_frame_id() == render_frame_id && entry->playing()) | 734 if (entry->render_frame_id() == render_frame_id && entry->playing()) |
| 742 return true; | 735 return true; |
| 743 } | 736 } |
| 744 return false; | 737 return false; |
| 745 } | 738 } |
| 746 | 739 |
| 747 void AudioRendererHost::CheckOutputDeviceAccess( | 740 void AudioRendererHost::CheckOutputDeviceAccess( |
| 748 int render_frame_id, | 741 int render_frame_id, |
| 749 const std::string& device_id, | 742 const std::string& device_id, |
| 750 const GURL& gurl_security_origin, | 743 const url::Origin& security_origin, |
| 751 const OutputDeviceAccessCB& callback) { | 744 const OutputDeviceAccessCB& callback) { |
| 752 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 745 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 753 | 746 |
| 754 // Check security origin if nondefault device is requested. | 747 // Check security origin if nondefault device is requested. |
| 755 // Ignore check for default device, which is always authorized. | 748 // Ignore check for default device, which is always authorized. |
| 756 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) && | 749 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) && |
| 757 !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( | 750 !MediaStreamManager::IsOriginAllowed(render_process_id_, |
| 758 render_process_id_, gurl_security_origin)) { | 751 security_origin)) { |
| 759 content::bad_message::ReceivedBadMessage(this, | 752 content::bad_message::ReceivedBadMessage(this, |
| 760 bad_message::ARH_UNAUTHORIZED_URL); | 753 bad_message::ARH_UNAUTHORIZED_URL); |
| 761 return; | 754 return; |
| 762 } | 755 } |
| 763 | 756 |
| 764 if (device_id.empty()) { | 757 if (device_id.empty()) { |
| 765 callback.Run(true); | 758 callback.Run(true); |
| 766 } else { | 759 } else { |
| 767 // Check that MediaStream device permissions have been granted, | 760 // Check that MediaStream device permissions have been granted, |
| 768 // hence the use of a MediaStreamUIProxy. | 761 // hence the use of a MediaStreamUIProxy. |
| 769 std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create(); | 762 std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create(); |
| 770 | 763 |
| 771 // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT | 764 // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT |
| 772 // because MediaStreamUIProxy::CheckAccess does not currently support | 765 // because MediaStreamUIProxy::CheckAccess does not currently support |
| 773 // MEDIA_DEVICE_AUDIO_OUTPUT. | 766 // MEDIA_DEVICE_AUDIO_OUTPUT. |
| 774 // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes | 767 // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes |
| 775 // available. http://crbug.com/498675 | 768 // available. http://crbug.com/498675 |
| 776 ui_proxy->CheckAccess(gurl_security_origin, MEDIA_DEVICE_AUDIO_CAPTURE, | 769 ui_proxy->CheckAccess(security_origin, MEDIA_DEVICE_AUDIO_CAPTURE, |
| 777 render_process_id_, render_frame_id, | 770 render_process_id_, render_frame_id, |
| 778 base::Bind(&AudioRendererHost::AccessChecked, this, | 771 base::Bind(&AudioRendererHost::AccessChecked, this, |
| 779 base::Passed(&ui_proxy), callback)); | 772 base::Passed(&ui_proxy), callback)); |
| 780 } | 773 } |
| 781 } | 774 } |
| 782 | 775 |
| 783 void AudioRendererHost::AccessChecked( | 776 void AudioRendererHost::AccessChecked( |
| 784 std::unique_ptr<MediaStreamUIProxy> ui_proxy, | 777 std::unique_ptr<MediaStreamUIProxy> ui_proxy, |
| 785 const OutputDeviceAccessCB& callback, | 778 const OutputDeviceAccessCB& callback, |
| 786 bool have_access) { | 779 bool have_access) { |
| 787 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 780 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 788 callback.Run(have_access); | 781 callback.Run(have_access); |
| 789 } | 782 } |
| 790 | 783 |
| 791 void AudioRendererHost::TranslateDeviceID( | 784 void AudioRendererHost::TranslateDeviceID( |
| 792 const std::string& device_id, | 785 const std::string& device_id, |
| 793 const GURL& security_origin, | 786 const url::Origin& security_origin, |
| 794 const OutputDeviceInfoCB& callback, | 787 const OutputDeviceInfoCB& callback, |
| 795 const AudioOutputDeviceEnumeration& enumeration) { | 788 const AudioOutputDeviceEnumeration& enumeration) { |
| 796 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 789 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 797 for (const AudioOutputDeviceInfo& device_info : enumeration.devices) { | 790 for (const AudioOutputDeviceInfo& device_info : enumeration.devices) { |
| 798 if (device_id.empty()) { | 791 if (device_id.empty()) { |
| 799 if (device_info.unique_id == | 792 if (device_info.unique_id == |
| 800 media::AudioDeviceDescription::kDefaultDeviceId) { | 793 media::AudioDeviceDescription::kDefaultDeviceId) { |
| 801 callback.Run(true, device_info); | 794 callback.Run(true, device_info); |
| 802 return; | 795 return; |
| 803 } | 796 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 815 callback.Run(false, device_info); | 808 callback.Run(false, device_info); |
| 816 } | 809 } |
| 817 | 810 |
| 818 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 811 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
| 819 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 812 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 820 const auto& i = authorizations_.find(stream_id); | 813 const auto& i = authorizations_.find(stream_id); |
| 821 return i != authorizations_.end(); | 814 return i != authorizations_.end(); |
| 822 } | 815 } |
| 823 | 816 |
| 824 } // namespace content | 817 } // namespace content |
| OLD | NEW |