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

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

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: Guidos comments. Created 4 years, 1 month 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_devices_permission_checker.h"
22 #include "content/browser/media/media_internals.h" 20 #include "content/browser/media/media_internals.h"
23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 21 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
24 #include "content/browser/renderer_host/media/audio_sync_reader.h" 22 #include "content/browser/renderer_host/media/audio_sync_reader.h"
25 #include "content/browser/renderer_host/media/media_stream_manager.h" 23 #include "content/browser/renderer_host/media/media_stream_manager.h"
26 #include "content/browser/renderer_host/render_widget_host_impl.h" 24 #include "content/browser/renderer_host/media/media_stream_ui_proxy.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_handler_(media_stream_manager, render_process_id_, salt) {
238 DCHECK(audio_manager_); 202 DCHECK(audio_manager_);
239 DCHECK(media_stream_manager_);
240 } 203 }
241 204
242 AudioRendererHost::~AudioRendererHost() { 205 AudioRendererHost::~AudioRendererHost() {
243 DCHECK_CURRENTLY_ON(BrowserThread::IO); 206 DCHECK_CURRENTLY_ON(BrowserThread::IO);
244 CHECK(audio_entries_.empty()); 207 CHECK(audio_entries_.empty());
245 208
246 // If we had any streams, report UMA stats for the maximum number of 209 // 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 210 // simultaneous streams for this render process and for the whole browser
248 // process since last reported. 211 // process since last reported.
249 if (max_simultaneous_streams_ > 0) { 212 if (max_simultaneous_streams_ > 0) {
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 } 372 }
410 373
411 void AudioRendererHost::OnRequestDeviceAuthorization( 374 void AudioRendererHost::OnRequestDeviceAuthorization(
412 int stream_id, 375 int stream_id,
413 int render_frame_id, 376 int render_frame_id,
414 int session_id, 377 int session_id,
415 const std::string& device_id, 378 const std::string& device_id,
416 const url::Origin& security_origin) { 379 const url::Origin& security_origin) {
417 DCHECK_CURRENTLY_ON(BrowserThread::IO); 380 DCHECK_CURRENTLY_ON(BrowserThread::IO);
418 const base::TimeTicks auth_start_time = base::TimeTicks::Now(); 381 const base::TimeTicks auth_start_time = base::TimeTicks::Now();
419
420 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization" 382 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
421 << "(stream_id=" << stream_id 383 << "(stream_id=" << stream_id
422 << ", render_frame_id=" << render_frame_id 384 << ", render_frame_id=" << render_frame_id
423 << ", session_id=" << session_id << ", device_id=" << device_id 385 << ", session_id=" << session_id << ", device_id=" << device_id
424 << ", security_origin=" << security_origin << ")"; 386 << ", security_origin=" << security_origin << ")";
425
426 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id)) 387 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
427 return; 388 return;
389 authorizations_.insert(MakeAuthorizationData(stream_id, false, device_id));
390 // Unretained is ok here since |this| owns |authorization_handler_| and
391 // |authorization_handler_| owns the callback.
392 AudioOutputAuthorizationHandler::AuthorizationCompletedCallback cb =
393 base::Bind(&AudioRendererHost::AuthorizationCompleted,
394 base::Unretained(this), stream_id, auth_start_time);
395 authorization_handler_.RequestDeviceAuthorization(
396 render_frame_id, session_id, device_id, security_origin, std::move(cb));
397 }
428 398
429 if (!IsValidDeviceId(device_id)) { 399 void AudioRendererHost::AuthorizationCompleted(int stream_id,
430 UMALogDeviceAuthorizationTime(auth_start_time); 400 base::TimeTicks auth_start_time,
431 Send(new AudioMsg_NotifyDeviceAuthorized( 401 media::OutputDeviceStatus status,
432 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, 402 media::AudioParameters params,
DaleCurtis 2016/11/01 22:01:13 const& We don't have a move constructor for params
Max Morin 2016/11/02 11:47:07 Ah, we actually don't. I'll change it back then.
433 media::AudioParameters::UnavailableDeviceParams(), std::string())); 403 const std::string& unique_id) {
434 return; 404 DCHECK_CURRENTLY_ON(BrowserThread::IO);
405 auto auth_data = authorizations_.find(stream_id);
406 if (auth_data == authorizations_.end())
407 return; // Stream was closed before finishing authorization
408
409 if (status == media::OUTPUT_DEVICE_STATUS_OK) {
410 auth_data->second.first = true;
411 auth_data->second.second = unique_id;
412 } else {
413 authorizations_.erase(auth_data);
435 } 414 }
436 415 UMALogDeviceAuthorizationTime(auth_start_time);
437 // If |session_id should be used for output device selection and such output 416 Send(new AudioMsg_NotifyDeviceAuthorized(stream_id, status, std::move(params),
438 // device is found, reuse the input device permissions. 417 unique_id));
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 } 418 }
470 419
471 void AudioRendererHost::OnCreateStream(int stream_id, 420 void AudioRendererHost::OnCreateStream(int stream_id,
472 int render_frame_id, 421 int render_frame_id,
473 const media::AudioParameters& params) { 422 const media::AudioParameters& params) {
474 DCHECK_CURRENTLY_ON(BrowserThread::IO); 423 DCHECK_CURRENTLY_ON(BrowserThread::IO);
475 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" 424 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
476 << "(stream_id=" << stream_id << ")"; 425 << "(stream_id=" << stream_id << ")";
477 426
478 // Determine whether to use the device_unique_id from an authorization, or an 427 // Determine whether to use the device_unique_id from an authorization, or an
(...skipping 195 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 DCHECK_CURRENTLY_ON(BrowserThread::IO);
635 return authorizations_.find(stream_id) != authorizations_.end();
636 }
637
684 bool AudioRendererHost::HasActiveAudio() { 638 bool AudioRendererHost::HasActiveAudio() {
685 return !base::AtomicRefCountIsZero(&num_playing_streams_); 639 return !base::AtomicRefCountIsZero(&num_playing_streams_);
686 } 640 }
687 641
688 void AudioRendererHost::CheckOutputDeviceAccess(
689 int render_frame_id,
690 const std::string& device_id,
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(device_id, security_origin, stream_id, auth_start_time, true);
708 } else {
709 // Check that device permissions have been granted for nondefault devices.
710 MediaDevicesPermissionChecker permission_checker;
711 permission_checker.CheckPermission(
712 MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id_, render_frame_id,
713 security_origin,
714 base::Bind(&AudioRendererHost::AccessChecked, this, device_id,
715 security_origin, stream_id, auth_start_time));
716 }
717 }
718
719 void AudioRendererHost::AccessChecked(
720 const std::string& device_id,
721 const url::Origin& security_origin,
722 int stream_id,
723 base::TimeTicks auth_start_time,
724 bool have_access) {
725 DCHECK_CURRENTLY_ON(BrowserThread::IO);
726
727 const auto& auth_data = authorizations_.find(stream_id);
728 if (auth_data == authorizations_.end()) {
729 // A close request was received while access check was in progress.
730 UMALogDeviceAuthorizationTime(auth_start_time);
731 return;
732 }
733
734 if (!have_access) {
735 authorizations_.erase(auth_data);
736 UMALogDeviceAuthorizationTime(auth_start_time);
737 Send(new AudioMsg_NotifyDeviceAuthorized(
738 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
739 media::AudioParameters::UnavailableDeviceParams(), std::string()));
740 return;
741 }
742
743 // For default device, read output parameters directly. Nondefault devices
744 // require translation first.
745 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
746 base::PostTaskAndReplyWithResult(
747 audio_manager_->GetTaskRunner(), FROM_HERE,
748 base::Bind(&AudioRendererHost::GetDeviceParametersOnDeviceThread, this,
749 media::AudioDeviceDescription::kDefaultDeviceId),
750 base::Bind(&AudioRendererHost::DeviceParametersReceived, this,
751 stream_id, auth_start_time, true,
752 media::AudioDeviceDescription::kDefaultDeviceId));
753 } else {
754 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
755 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
756 media_stream_manager_->media_devices_manager()->EnumerateDevices(
757 devices_to_enumerate,
758 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
759 security_origin, stream_id, auth_start_time));
760 }
761 }
762
763 void AudioRendererHost::TranslateDeviceID(
764 const std::string& device_id,
765 const url::Origin& security_origin,
766 int stream_id,
767 base::TimeTicks auth_start_time,
768 const MediaDeviceEnumeration& enumeration) {
769 DCHECK_CURRENTLY_ON(BrowserThread::IO);
770 DCHECK(!media::AudioDeviceDescription::IsDefaultDevice(device_id));
771 for (const MediaDeviceInfo& device_info :
772 enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
773 if (content::DoesMediaDeviceIDMatchHMAC(salt_, security_origin, device_id,
774 device_info.device_id)) {
775 base::PostTaskAndReplyWithResult(
776 audio_manager_->GetTaskRunner(), FROM_HERE,
777 base::Bind(&AudioRendererHost::GetDeviceParametersOnDeviceThread,
778 this, device_info.device_id),
779 base::Bind(&AudioRendererHost::DeviceParametersReceived, this,
780 stream_id, auth_start_time, true, device_info.device_id));
781 return;
782 }
783 }
784 DeviceParametersReceived(stream_id, auth_start_time, false, std::string(),
785 media::AudioParameters::UnavailableDeviceParams());
786 }
787
788 media::AudioParameters AudioRendererHost::GetDeviceParametersOnDeviceThread(
789 const std::string& unique_id) {
790 DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
791
792 if (media::AudioDeviceDescription::IsDefaultDevice(unique_id))
793 return audio_manager_->GetDefaultOutputStreamParameters();
794
795 return audio_manager_->GetOutputStreamParameters(unique_id);
796 }
797
798 void AudioRendererHost::DeviceParametersReceived(
799 int stream_id,
800 base::TimeTicks auth_start_time,
801 bool device_found,
802 const std::string& unique_id,
803 const media::AudioParameters& output_params) {
804 DCHECK_CURRENTLY_ON(BrowserThread::IO);
805 const auto& auth_data = authorizations_.find(stream_id);
806
807 // A close request was received while translation was in progress
808 if (auth_data == authorizations_.end()) {
809 UMALogDeviceAuthorizationTime(auth_start_time);
810 return;
811 }
812
813 if (!device_found) {
814 authorizations_.erase(auth_data);
815 UMALogDeviceAuthorizationTime(auth_start_time);
816 Send(new AudioMsg_NotifyDeviceAuthorized(
817 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
818 media::AudioParameters::UnavailableDeviceParams(),
819 std::string() /* matched_device_id */));
820 return;
821 }
822
823 auth_data->second.first = true;
824 auth_data->second.second = unique_id;
825
826 media::AudioParameters params = std::move(output_params);
827 MaybeFixAudioParameters(&params);
828 UMALogDeviceAuthorizationTime(auth_start_time);
829 Send(new AudioMsg_NotifyDeviceAuthorized(
830 stream_id, media::OUTPUT_DEVICE_STATUS_OK, params,
831 std::string() /* matched_device_id */));
832 }
833
834 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
835 DCHECK_CURRENTLY_ON(BrowserThread::IO);
836 const auto& i = authorizations_.find(stream_id);
837 return i != authorizations_.end();
838 }
839
840 } // namespace content 642 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698