Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host.cc

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: Remove unnecessary weak pointer use. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/memory/shared_memory.h" 14 #include "base/memory/shared_memory.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/process/process.h"
17 #include "content/browser/bad_message.h" 16 #include "content/browser/bad_message.h"
18 #include "content/browser/browser_main_loop.h" 17 #include "content/browser/browser_main_loop.h"
19 #include "content/browser/media/audio_stream_monitor.h" 18 #include "content/browser/media/audio_stream_monitor.h"
20 #include "content/browser/media/capture/audio_mirroring_manager.h" 19 #include "content/browser/media/capture/audio_mirroring_manager.h"
21 #include "content/browser/media/media_internals.h" 20 #include "content/browser/media/media_internals.h"
22 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 21 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
23 #include "content/browser/renderer_host/media/audio_sync_reader.h" 22 #include "content/browser/renderer_host/media/audio_sync_reader.h"
24 #include "content/browser/renderer_host/media/media_stream_manager.h" 23 #include "content/browser/renderer_host/media/media_stream_manager.h"
25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 24 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
26 #include "content/browser/renderer_host/render_widget_host_impl.h"
27 #include "content/common/media/audio_messages.h" 25 #include "content/common/media/audio_messages.h"
28 #include "content/public/browser/content_browser_client.h" 26 #include "content/public/browser/content_browser_client.h"
29 #include "content/public/browser/media_device_id.h" 27 #include "content/public/browser/media_device_id.h"
30 #include "content/public/browser/media_observer.h" 28 #include "content/public/browser/media_observer.h"
31 #include "content/public/browser/render_frame_host.h" 29 #include "content/public/browser/render_frame_host.h"
32 #include "content/public/common/content_switches.h"
33 #include "media/audio/audio_device_description.h" 30 #include "media/audio/audio_device_description.h"
34 #include "media/audio/audio_streams_tracker.h" 31 #include "media/audio/audio_streams_tracker.h"
35 #include "media/base/audio_bus.h" 32 #include "media/base/audio_bus.h"
36 #include "media/base/limits.h" 33 #include "media/base/limits.h"
37 34
38 using media::AudioBus; 35 using media::AudioBus;
39 using media::AudioManager; 36 using media::AudioManager;
40 37
41 namespace content { 38 namespace content {
42 39
43 namespace { 40 namespace {
44 41
45 // Tracks the maximum number of simultaneous output streams browser-wide. 42 // Tracks the maximum number of simultaneous output streams browser-wide.
46 // Accessed on IO thread. 43 // Accessed on IO thread.
47 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = 44 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker =
48 LAZY_INSTANCE_INITIALIZER; 45 LAZY_INSTANCE_INITIALIZER;
49 46
50 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( 47 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData(
51 int stream_id, 48 int stream_id,
52 bool authorized, 49 bool authorized,
53 const std::string& device_unique_id) { 50 const std::string& device_unique_id) {
54 return std::make_pair(stream_id, 51 return std::make_pair(stream_id,
55 std::make_pair(authorized, device_unique_id)); 52 std::make_pair(authorized, device_unique_id));
56 } 53 }
57 54
58 bool IsValidDeviceId(const std::string& device_id) {
59 static const std::string::size_type kValidLength = 64;
60
61 if (device_id.empty() ||
62 device_id == media::AudioDeviceDescription::kDefaultDeviceId ||
63 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) {
64 return true;
65 }
66
67 if (device_id.length() != kValidLength)
68 return false;
69
70 for (const char& c : device_id) {
71 if ((c < 'a' || c > 'f') && (c < '0' || c > '9'))
72 return false;
73 }
74
75 return true;
76 }
77 55
78 void NotifyRenderProcessHostThatAudioStateChanged(int render_process_id) { 56 void NotifyRenderProcessHostThatAudioStateChanged(int render_process_id) {
79 DCHECK_CURRENTLY_ON(BrowserThread::UI); 57 DCHECK_CURRENTLY_ON(BrowserThread::UI);
80 58
81 RenderProcessHost* render_process_host = 59 RenderProcessHost* render_process_host =
82 RenderProcessHost::FromID(render_process_id); 60 RenderProcessHost::FromID(render_process_id);
83 61
84 if (render_process_host) 62 if (render_process_host)
85 render_process_host->AudioStateChanged(); 63 render_process_host->AudioStateChanged();
86 } 64 }
87 65
88 void MaybeFixAudioParameters(media::AudioParameters* params) {
89 // If the number of output channels is greater than the maximum, use the
90 // maximum allowed value. Hardware channels are ignored upstream, so it is
91 // better to report a valid value if this is the only problem.
92 if (params->channels() > media::limits::kMaxChannels)
93 params->set_channels_for_discrete(media::limits::kMaxChannels);
94
95 // If hardware parameters are still invalid, use dummy parameters with
96 // fake audio path and let the client handle the error.
97 if (!params->IsValid())
98 *params = media::AudioParameters::UnavailableDeviceParams();
99 }
100
101 void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) {
102 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime",
103 base::TimeTicks::Now() - auth_start_time,
104 base::TimeDelta::FromMilliseconds(1),
105 base::TimeDelta::FromMilliseconds(5000), 50);
106 }
107
108 // Check that the routing ID references a valid RenderFrameHost, and run 66 // Check that the routing ID references a valid RenderFrameHost, and run
109 // |callback| on the IO thread with true if the ID is valid. 67 // |callback| on the IO thread with true if the ID is valid.
110 void ValidateRenderFrameId(int render_process_id, 68 void ValidateRenderFrameId(int render_process_id,
111 int render_frame_id, 69 int render_frame_id,
112 const base::Callback<void(bool)>& callback) { 70 const base::Callback<void(bool)>& callback) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI); 71 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 const bool frame_exists = 72 const bool frame_exists =
115 !!RenderFrameHost::FromID(render_process_id, render_frame_id); 73 !!RenderFrameHost::FromID(render_process_id, render_frame_id);
116 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 74 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
117 base::Bind(callback, frame_exists)); 75 base::Bind(callback, frame_exists));
118 } 76 }
119 77
78 void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) {
79 UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime",
80 base::TimeTicks::Now() - auth_start_time,
81 base::TimeDelta::FromMilliseconds(1),
82 base::TimeDelta::FromMilliseconds(5000), 50);
83 }
84
120 } // namespace 85 } // namespace
121 86
122 class AudioRendererHost::AudioEntry 87 class AudioRendererHost::AudioEntry
123 : public media::AudioOutputController::EventHandler { 88 : public media::AudioOutputController::EventHandler {
124 public: 89 public:
125 ~AudioEntry() override; 90 ~AudioEntry() override;
126 91
127 // Returns nullptr on failure. 92 // Returns nullptr on failure.
128 static std::unique_ptr<AudioRendererHost::AudioEntry> Create( 93 static std::unique_ptr<AudioRendererHost::AudioEntry> Create(
129 AudioRendererHost* host, 94 AudioRendererHost* host,
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 AudioMirroringManager* mirroring_manager, 188 AudioMirroringManager* mirroring_manager,
224 MediaInternals* media_internals, 189 MediaInternals* media_internals,
225 MediaStreamManager* media_stream_manager, 190 MediaStreamManager* media_stream_manager,
226 const std::string& salt) 191 const std::string& salt)
227 : BrowserMessageFilter(AudioMsgStart), 192 : BrowserMessageFilter(AudioMsgStart),
228 render_process_id_(render_process_id), 193 render_process_id_(render_process_id),
229 audio_manager_(audio_manager), 194 audio_manager_(audio_manager),
230 mirroring_manager_(mirroring_manager), 195 mirroring_manager_(mirroring_manager),
231 audio_log_(media_internals->CreateAudioLog( 196 audio_log_(media_internals->CreateAudioLog(
232 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)), 197 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
233 media_stream_manager_(media_stream_manager),
234 num_playing_streams_(0), 198 num_playing_streams_(0),
235 salt_(salt),
236 validate_render_frame_id_function_(&ValidateRenderFrameId), 199 validate_render_frame_id_function_(&ValidateRenderFrameId),
237 max_simultaneous_streams_(0) { 200 max_simultaneous_streams_(0),
201 authorization_manager_(media_stream_manager, render_process_id_, salt) {
202 // Unretained is ok here since this owns the authorization_manager.
203 authorization_manager_.SetBadMessageHandler(
204 base::Bind(&AudioRendererHost::OnBadMessage, base::Unretained(this)));
238 DCHECK(audio_manager_); 205 DCHECK(audio_manager_);
239 DCHECK(media_stream_manager_);
240 } 206 }
241 207
242 AudioRendererHost::~AudioRendererHost() { 208 AudioRendererHost::~AudioRendererHost() {
243 DCHECK_CURRENTLY_ON(BrowserThread::IO); 209 DCHECK_CURRENTLY_ON(BrowserThread::IO);
244 CHECK(audio_entries_.empty()); 210 CHECK(audio_entries_.empty());
245 211
246 // If we had any streams, report UMA stats for the maximum number of 212 // If we had any streams, report UMA stats for the maximum number of
247 // simultaneous streams for this render process and for the whole browser 213 // simultaneous streams for this render process and for the whole browser
248 // process since last reported. 214 // process since last reported.
249 if (max_simultaneous_streams_ > 0) { 215 if (max_simultaneous_streams_ > 0) {
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 } 375 }
410 376
411 void AudioRendererHost::OnRequestDeviceAuthorization( 377 void AudioRendererHost::OnRequestDeviceAuthorization(
412 int stream_id, 378 int stream_id,
413 int render_frame_id, 379 int render_frame_id,
414 int session_id, 380 int session_id,
415 const std::string& device_id, 381 const std::string& device_id,
416 const url::Origin& security_origin) { 382 const url::Origin& security_origin) {
417 DCHECK_CURRENTLY_ON(BrowserThread::IO); 383 DCHECK_CURRENTLY_ON(BrowserThread::IO);
418 const base::TimeTicks auth_start_time = base::TimeTicks::Now(); 384 const base::TimeTicks auth_start_time = base::TimeTicks::Now();
419
420 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization" 385 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
421 << "(stream_id=" << stream_id 386 << "(stream_id=" << stream_id
422 << ", render_frame_id=" << render_frame_id 387 << ", render_frame_id=" << render_frame_id
423 << ", session_id=" << session_id << ", device_id=" << device_id 388 << ", session_id=" << session_id << ", device_id=" << device_id
424 << ", security_origin=" << security_origin << ")"; 389 << ", security_origin=" << security_origin << ")";
425
426 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id)) 390 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
427 return; 391 return;
392 authorizations_.insert(MakeAuthorizationData(stream_id, false, device_id));
393 // Unretained is ok here since this owns the authorization_manager.
394 AudioOutputAuthorizationHandler::AuthorizationCompletedCallback cb =
395 base::Bind(&AudioRendererHost::AuthorizationCompleted,
396 base::Unretained(this), stream_id, auth_start_time);
397 authorization_manager_.RequestDeviceAuthorization(
o1ka 2016/10/27 13:58:09 |authorization_handler_|?
Max Morin 2016/10/28 11:16:07 Done.
398 render_frame_id, session_id, device_id, security_origin, std::move(cb));
399 }
428 400
429 if (!IsValidDeviceId(device_id)) { 401 void AudioRendererHost::AuthorizationCompleted(int stream_id,
430 UMALogDeviceAuthorizationTime(auth_start_time); 402 base::TimeTicks auth_start_time,
431 Send(new AudioMsg_NotifyDeviceAuthorized( 403 media::OutputDeviceStatus status,
432 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, 404 media::AudioParameters params,
433 media::AudioParameters::UnavailableDeviceParams(), std::string())); 405 const std::string& unique_id) {
434 return; 406 UMALogDeviceAuthorizationTime(auth_start_time);
o1ka 2016/10/27 13:58:09 Move it to be called right before Send()
Max Morin 2016/10/28 11:16:07 Done.
Max Morin 2016/11/01 11:26:20 This will actually change the meaning of the stat
407 auto auth_data = authorizations_.find(stream_id);
o1ka 2016/10/27 13:58:09 thread check?
Max Morin 2016/10/28 11:16:07 Done.
408 if (auth_data == authorizations_.end())
409 return; // Stream was closed before finishing authorization
410
411 if (status == media::OUTPUT_DEVICE_STATUS_OK) {
412 auth_data->second.first = true;
413 auth_data->second.second = unique_id;
414 } else {
415 authorizations_.erase(auth_data);
435 } 416 }
436 417 Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, status, params,
437 // If |session_id should be used for output device selection and such output 418 unique_id));
438 // device is found, reuse the input device permissions.
439 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
440 device_id)) {
441 const StreamDeviceInfo* info =
442 media_stream_manager_->audio_input_device_manager()
443 ->GetOpenedDeviceInfoById(session_id);
444 if (info) {
445 media::AudioParameters output_params(
446 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
447 static_cast<media::ChannelLayout>(
448 info->device.matched_output.channel_layout),
449 info->device.matched_output.sample_rate, 16,
450 info->device.matched_output.frames_per_buffer);
451 output_params.set_effects(info->device.matched_output.effects);
452 authorizations_.insert(MakeAuthorizationData(
453 stream_id, true, info->device.matched_output_device_id));
454 MaybeFixAudioParameters(&output_params);
455 UMALogDeviceAuthorizationTime(auth_start_time);
456 // Hash matched device id and pass it to the renderer
457 Send(new AudioMsg_NotifyDeviceAuthorized(
458 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
459 GetHMACForMediaDeviceID(salt_, security_origin,
460 info->device.matched_output_device_id)));
461 return;
462 }
463 }
464
465 authorizations_.insert(
466 MakeAuthorizationData(stream_id, false, std::string()));
467 CheckOutputDeviceAccess(render_frame_id, device_id, security_origin,
468 stream_id, auth_start_time);
469 } 419 }
470 420
471 void AudioRendererHost::OnCreateStream(int stream_id, 421 void AudioRendererHost::OnCreateStream(int stream_id,
472 int render_frame_id, 422 int render_frame_id,
473 const media::AudioParameters& params) { 423 const media::AudioParameters& params) {
474 DCHECK_CURRENTLY_ON(BrowserThread::IO); 424 DCHECK_CURRENTLY_ON(BrowserThread::IO);
475 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" 425 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
476 << "(stream_id=" << stream_id << ")"; 426 << "(stream_id=" << stream_id << ")";
477 427
478 // Determine whether to use the device_unique_id from an authorization, or an 428 // Determine whether to use the device_unique_id from an authorization, or an
479 // empty string (i.e., when no previous authorization was requested, assume 429 // empty string (i.e., when no previous authorization was requested, assume
480 // default device). 430 // default device).
481 std::string device_unique_id; 431 std::string device_unique_id;
482 const auto& auth_data = authorizations_.find(stream_id); 432 const auto& auth_data = authorizations_.find(stream_id);
483 if (auth_data != authorizations_.end()) { 433 if (auth_data != authorizations_.end()) {
484 if (!auth_data->second.first) { 434 if (!auth_data->second.first) {
485 // The authorization for this stream is still pending, so it's an error 435 // The authorization for this stream is still pending, so it's an error
486 // to create it now. 436 // to create it now.
487 content::bad_message::ReceivedBadMessage( 437 OnBadMessage(bad_message::ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION);
488 this, bad_message::ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION);
489 return; 438 return;
490 } 439 }
491 device_unique_id.swap(auth_data->second.second); 440 device_unique_id.swap(auth_data->second.second);
492 authorizations_.erase(auth_data); 441 authorizations_.erase(auth_data);
493 } 442 }
494 443
495 // Fail early if either of two sanity-checks fail: 444 // Fail early if either of two sanity-checks fail:
496 // 1. There should not yet exist an AudioEntry for the given |stream_id| 445 // 1. There should not yet exist an AudioEntry for the given |stream_id|
497 // since the renderer may not create two streams with the same ID. 446 // since the renderer may not create two streams with the same ID.
498 // 2. An out-of-range render frame ID was provided. Renderers must *always* 447 // 2. An out-of-range render frame ID was provided. Renderers must *always*
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 // Inform the RenderProcessHost when there is no more audio playing. 623 // Inform the RenderProcessHost when there is no more audio playing.
675 if (!base::AtomicRefCountDec(&num_playing_streams_)) { 624 if (!base::AtomicRefCountDec(&num_playing_streams_)) {
676 BrowserThread::PostTask( 625 BrowserThread::PostTask(
677 BrowserThread::UI, FROM_HERE, 626 BrowserThread::UI, FROM_HERE,
678 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, 627 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
679 render_process_id_)); 628 render_process_id_));
680 } 629 }
681 } 630 }
682 } 631 }
683 632
633 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
634 return authorizations_.find(stream_id) != authorizations_.end();
o1ka 2016/10/27 13:58:09 thread check?
Max Morin 2016/10/28 11:16:07 Done.
635 }
636
684 bool AudioRendererHost::HasActiveAudio() { 637 bool AudioRendererHost::HasActiveAudio() {
685 return !base::AtomicRefCountIsZero(&num_playing_streams_); 638 return !base::AtomicRefCountIsZero(&num_playing_streams_);
686 } 639 }
687 640
688 void AudioRendererHost::CheckOutputDeviceAccess( 641 void AudioRendererHost::OnBadMessage(
689 int render_frame_id, 642 content::bad_message::BadMessageReason reason) {
690 const std::string& device_id, 643 content::bad_message::ReceivedBadMessage(this, reason);
691 const url::Origin& security_origin,
692 int stream_id,
693 base::TimeTicks auth_start_time) {
694 DCHECK_CURRENTLY_ON(BrowserThread::IO);
695
696 // Check security origin if nondefault device is requested.
697 // Ignore check for default device, which is always authorized.
698 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
699 !MediaStreamManager::IsOriginAllowed(render_process_id_,
700 security_origin)) {
701 content::bad_message::ReceivedBadMessage(this,
702 bad_message::ARH_UNAUTHORIZED_URL);
703 return;
704 }
705
706 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
707 AccessChecked(nullptr, device_id, security_origin, stream_id,
708 auth_start_time, true);
709 } else {
710 // Check that MediaStream device permissions have been granted,
711 // hence the use of a MediaStreamUIProxy.
712 std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
713
714 // Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT
715 // because MediaStreamUIProxy::CheckAccess does not currently support
716 // MEDIA_DEVICE_AUDIO_OUTPUT.
717 // TODO(guidou): Change to MEDIA_DEVICE_AUDIO_OUTPUT when support becomes
718 // available. http://crbug.com/498675
719 ui_proxy->CheckAccess(
720 security_origin, MEDIA_DEVICE_AUDIO_CAPTURE, render_process_id_,
721 render_frame_id,
722 base::Bind(&AudioRendererHost::AccessChecked, this,
723 base::Passed(&ui_proxy), device_id, security_origin,
724 stream_id, auth_start_time));
725 }
726 } 644 }
727
728 void AudioRendererHost::AccessChecked(
729 std::unique_ptr<MediaStreamUIProxy> ui_proxy,
730 const std::string& device_id,
731 const url::Origin& security_origin,
732 int stream_id,
733 base::TimeTicks auth_start_time,
734 bool have_access) {
735 DCHECK_CURRENTLY_ON(BrowserThread::IO);
736
737 const auto& auth_data = authorizations_.find(stream_id);
738 if (auth_data == authorizations_.end()) {
739 // A close request was received while access check was in progress.
740 UMALogDeviceAuthorizationTime(auth_start_time);
741 return;
742 }
743
744 if (!have_access) {
745 authorizations_.erase(auth_data);
746 UMALogDeviceAuthorizationTime(auth_start_time);
747 Send(new AudioMsg_NotifyDeviceAuthorized(
748 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
749 media::AudioParameters::UnavailableDeviceParams(), std::string()));
750 return;
751 }
752
753 // For default device, read output parameters directly. Nondefault devices
754 // require translation first.
755 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
756 base::PostTaskAndReplyWithResult(
757 audio_manager_->GetTaskRunner(), FROM_HERE,
758 base::Bind(&AudioRendererHost::GetDeviceParametersOnDeviceThread, this,
759 media::AudioDeviceDescription::kDefaultDeviceId),
760 base::Bind(&AudioRendererHost::DeviceParametersReceived, this,
761 stream_id, auth_start_time, true,
762 media::AudioDeviceDescription::kDefaultDeviceId));
763 } else {
764 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
765 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
766 media_stream_manager_->media_devices_manager()->EnumerateDevices(
767 devices_to_enumerate,
768 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
769 security_origin, stream_id, auth_start_time));
770 }
771 }
772
773 void AudioRendererHost::TranslateDeviceID(
774 const std::string& device_id,
775 const url::Origin& security_origin,
776 int stream_id,
777 base::TimeTicks auth_start_time,
778 const MediaDeviceEnumeration& enumeration) {
779 DCHECK_CURRENTLY_ON(BrowserThread::IO);
780 DCHECK(!media::AudioDeviceDescription::IsDefaultDevice(device_id));
781 for (const MediaDeviceInfo& device_info :
782 enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
783 if (content::DoesMediaDeviceIDMatchHMAC(salt_, security_origin, device_id,
784 device_info.device_id)) {
785 base::PostTaskAndReplyWithResult(
786 audio_manager_->GetTaskRunner(), FROM_HERE,
787 base::Bind(&AudioRendererHost::GetDeviceParametersOnDeviceThread,
788 this, device_info.device_id),
789 base::Bind(&AudioRendererHost::DeviceParametersReceived, this,
790 stream_id, auth_start_time, true, device_info.device_id));
791 return;
792 }
793 }
794 DeviceParametersReceived(stream_id, auth_start_time, false, std::string(),
795 media::AudioParameters::UnavailableDeviceParams());
796 }
797
798 media::AudioParameters AudioRendererHost::GetDeviceParametersOnDeviceThread(
799 const std::string& unique_id) {
800 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
801
802 if (media::AudioDeviceDescription::IsDefaultDevice(unique_id))
803 return audio_manager_->GetDefaultOutputStreamParameters();
804
805 return audio_manager_->GetOutputStreamParameters(unique_id);
806 }
807
808 void AudioRendererHost::DeviceParametersReceived(
809 int stream_id,
810 base::TimeTicks auth_start_time,
811 bool device_found,
812 const std::string& unique_id,
813 const media::AudioParameters& output_params) {
814 DCHECK_CURRENTLY_ON(BrowserThread::IO);
815 const auto& auth_data = authorizations_.find(stream_id);
816
817 // A close request was received while translation was in progress
818 if (auth_data == authorizations_.end()) {
819 UMALogDeviceAuthorizationTime(auth_start_time);
820 return;
821 }
822
823 if (!device_found) {
824 authorizations_.erase(auth_data);
825 UMALogDeviceAuthorizationTime(auth_start_time);
826 Send(new AudioMsg_NotifyDeviceAuthorized(
827 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
828 media::AudioParameters::UnavailableDeviceParams(),
829 std::string() /* matched_device_id */));
830 return;
831 }
832
833 auth_data->second.first = true;
834 auth_data->second.second = unique_id;
835
836 media::AudioParameters params = std::move(output_params);
837 MaybeFixAudioParameters(&params);
838 UMALogDeviceAuthorizationTime(auth_start_time);
839 Send(new AudioMsg_NotifyDeviceAuthorized(
840 stream_id, media::OUTPUT_DEVICE_STATUS_OK, params,
841 std::string() /* matched_device_id */));
842 }
843
844 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
845 DCHECK_CURRENTLY_ON(BrowserThread::IO);
846 const auto& i = authorizations_.find(stream_id);
847 return i != authorizations_.end();
848 }
849
850 } // namespace content 645 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698