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

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

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: Minor fixes. 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
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/media/audio_output_authorization_handler .h"
6
7 #include "base/task_runner_util.h"
8 #include "content/browser/bad_message.h"
9 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/media_device_id.h"
12 #include "media/base/limits.h"
13
14 namespace {
15
16 media::AudioParameters MaybeFixAudioParameters(
Guido Urdaneta 2016/11/10 15:26:04 Maybe I missed another review comment, but why for
Max Morin 2016/11/11 09:26:55 Updated the code so that this function is only cal
17 const media::AudioParameters& params) {
18 media::AudioParameters params_copy(params);
19
20 // If the number of output channels is greater than the maximum, use the
21 // maximum allowed value. Hardware channels are ignored upstream, so it is
22 // better to report a valid value if this is the only problem.
23 if (params.channels() > media::limits::kMaxChannels) {
24 DCHECK(params.channel_layout() == media::CHANNEL_LAYOUT_DISCRETE);
25 params_copy.set_channels_for_discrete(media::limits::kMaxChannels);
26 }
27
28 // If hardware parameters are still invalid, use dummy parameters with
29 // fake audio path and let the client handle the error.
30 return params_copy.IsValid()
31 ? params_copy
32 : media::AudioParameters::UnavailableDeviceParams();
33 }
34
35 media::AudioParameters GetDeviceParametersOnDeviceThread(
36 const std::string& unique_id) {
37 media::AudioManager* audio_manager = media::AudioManager::Get();
38 DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread());
39
40 return media::AudioDeviceDescription::IsDefaultDevice(unique_id)
41 ? audio_manager->GetDefaultOutputStreamParameters()
42 : audio_manager->GetOutputStreamParameters(unique_id);
43 }
44
45 } // namespace
46
47 namespace content {
48
49 AudioOutputAuthorizationHandler::AudioOutputAuthorizationHandler(
50 MediaStreamManager* media_stream_manager,
51 int render_process_id,
52 const std::string& salt)
53 : media_stream_manager_(media_stream_manager),
54 permission_checker_(new MediaDevicesPermissionChecker()),
55 render_process_id_(render_process_id),
56 salt_(salt),
57 weak_factory_(this) {
58 DCHECK(media_stream_manager_);
59 }
60
61 void AudioOutputAuthorizationHandler::OverridePermissionsForTesting(
62 bool override_value) {
63 DCHECK_CURRENTLY_ON(BrowserThread::IO);
64 DCHECK(permission_checker_);
65 permission_checker_.reset(new MediaDevicesPermissionChecker(override_value));
66 }
67
68 AudioOutputAuthorizationHandler::~AudioOutputAuthorizationHandler() {
69 // weak_factory is not thread safe. Make sure it's destructed on the
70 // right thread.
71 DCHECK_CURRENTLY_ON(BrowserThread::IO);
72 }
73
74 void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
75 int render_frame_id,
76 int session_id,
77 const std::string& device_id,
78 const url::Origin& security_origin,
79 AuthorizationCompletedCallback cb) const {
80 DCHECK_CURRENTLY_ON(BrowserThread::IO);
81
82 if (!IsValidDeviceId(device_id)) {
83 bad_message::ReceivedBadMessage(render_process_id_,
84 bad_message::AOAH_NONSENSE_DEVICE_ID);
85 return;
86 }
87
88 // If |session_id| should be used for output device selection and such
89 // output
90 // device is found, reuse the input device permissions.
91 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
92 device_id)) {
93 const StreamDeviceInfo* info =
94 media_stream_manager_->audio_input_device_manager()
95 ->GetOpenedDeviceInfoById(session_id);
96 if (info && !info->device.matched_output_device_id.empty()) {
97 media::AudioParameters output_params(
98 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
99 static_cast<media::ChannelLayout>(
100 info->device.matched_output.channel_layout),
101 info->device.matched_output.sample_rate, 16,
102 info->device.matched_output.frames_per_buffer);
103 output_params.set_effects(info->device.matched_output.effects);
104
105 DeviceParametersReceived(
106 std::move(cb), info->device.matched_output_device_id, output_params);
107 return;
108 } else {
109 LOG(WARNING) << "session id used for device selection "
110 << "but no device info found";
111 }
112 }
113
114 // Check security origin if nondefault device is requested.
115 // Ignore check for default device, which is always authorized.
116 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
117 !MediaStreamManager::IsOriginAllowed(render_process_id_,
118 security_origin)) {
119 bad_message::ReceivedBadMessage(render_process_id_,
120 bad_message::AOAH_UNAUTHORIZED_URL);
121 return;
122 }
123
124 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
125 AccessChecked(std::move(cb), device_id, security_origin, true);
126 } else {
127 // Check that MediaStream device permissions have been granted for
128 // nondefault devices.
129 permission_checker_->CheckPermission(
130 MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id_, render_frame_id,
131 security_origin,
132 base::Bind(&AudioOutputAuthorizationHandler::AccessChecked,
133 weak_factory_.GetWeakPtr(), std::move(cb), device_id,
134 security_origin));
135 }
136 }
137
138 void AudioOutputAuthorizationHandler::AccessChecked(
139 AuthorizationCompletedCallback cb,
140 const std::string& device_id,
141 const url::Origin& security_origin,
142 bool have_access) const {
143 DCHECK_CURRENTLY_ON(BrowserThread::IO);
144
145 if (!have_access) {
146 cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
147 media::AudioParameters::UnavailableDeviceParams(), std::string());
148 return;
149 }
150
151 // For default device, read output parameters directly. Nondefault
152 // devices require translation first.
153 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
154 base::PostTaskAndReplyWithResult(
155 media::AudioManager::Get()->GetTaskRunner(), FROM_HERE,
156 base::Bind(&GetDeviceParametersOnDeviceThread,
157 media::AudioDeviceDescription::kDefaultDeviceId),
158 base::Bind(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
159 weak_factory_.GetWeakPtr(), std::move(cb),
160 media::AudioDeviceDescription::kDefaultDeviceId));
161 } else {
162 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
163 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
164 media_stream_manager_->media_devices_manager()->EnumerateDevices(
165 devices_to_enumerate,
166 base::Bind(&AudioOutputAuthorizationHandler::TranslateDeviceID,
167 weak_factory_.GetWeakPtr(), std::move(cb), device_id,
168 security_origin));
169 }
170 }
171
172 void AudioOutputAuthorizationHandler::TranslateDeviceID(
173 AuthorizationCompletedCallback cb,
174 const std::string& device_id,
175 const url::Origin& security_origin,
176 const MediaDeviceEnumeration& enumeration) const {
177 DCHECK_CURRENTLY_ON(BrowserThread::IO);
178 DCHECK(!media::AudioDeviceDescription::IsDefaultDevice(device_id));
179 for (const MediaDeviceInfo& device_info :
180 enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
181 if (content::DoesMediaDeviceIDMatchHMAC(salt_, security_origin, device_id,
182 device_info.device_id)) {
183 base::PostTaskAndReplyWithResult(
184 media::AudioManager::Get()->GetTaskRunner(), FROM_HERE,
185 base::Bind(&GetDeviceParametersOnDeviceThread, device_info.device_id),
186 base::Bind(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
187 weak_factory_.GetWeakPtr(), std::move(cb),
188 device_info.device_id));
189 return;
190 }
191 }
192 cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
193 media::AudioParameters::UnavailableDeviceParams(), std::string());
194 }
195
196 void AudioOutputAuthorizationHandler::DeviceParametersReceived(
197 AuthorizationCompletedCallback cb,
198 const std::string& translated_device_id,
199 const media::AudioParameters& output_params) const {
200 DCHECK_CURRENTLY_ON(BrowserThread::IO);
201 DCHECK(!translated_device_id.empty());
202
203 cb.Run(media::OUTPUT_DEVICE_STATUS_OK, MaybeFixAudioParameters(output_params),
204 translated_device_id);
205 }
206
207 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698