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

Side by Side Diff: content/browser/renderer_host/media/audio_output_authorization_handler.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
(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 bool IsValidDeviceId(const std::string& device_id) {
17 static const std::string::size_type kValidLength = 64;
DaleCurtis 2016/11/01 22:01:13 No need for static const? Just use constexpr? Seem
Max Morin 2016/11/02 11:47:06 I was lazy and just moved this code over from ARH,
18
19 if (media::AudioDeviceDescription::IsDefaultDevice(device_id) ||
20 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) {
21 return true;
22 }
23
24 if (device_id.length() != kValidLength)
25 return false;
26
27 for (const char& c : device_id) {
28 if ((c < 'a' || c > 'f') && (c < '0' || c > '9'))
29 return false;
30 }
31
32 return true;
33 }
34
35 void MaybeFixAudioParameters(media::AudioParameters* params) {
36 // If the number of output channels is greater than the maximum, use the
37 // maximum allowed value. Hardware channels are ignored upstream, so it is
38 // better to report a valid value if this is the only problem.
39 if (params->channels() > media::limits::kMaxChannels)
DaleCurtis 2016/11/01 22:01:13 Probably this should DCHECK that the channel layou
Max Morin 2016/11/02 11:47:06 Done.
40 params->set_channels_for_discrete(media::limits::kMaxChannels);
41
42 // If hardware parameters are still invalid, use dummy parameters with
43 // fake audio path and let the client handle the error.
44 if (!params->IsValid())
45 *params = media::AudioParameters::UnavailableDeviceParams();
46 }
47
48 media::AudioParameters GetDeviceParametersOnDeviceThread(
49 const std::string& unique_id) {
50 media::AudioManager* audio_manager = media::AudioManager::Get();
51 DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread());
52
53 if (media::AudioDeviceDescription::IsDefaultDevice(unique_id))
DaleCurtis 2016/11/01 22:01:13 Prefer ternary? Up to you though.
Max Morin 2016/11/02 11:47:06 Done.
54 return audio_manager->GetDefaultOutputStreamParameters();
55 return audio_manager->GetOutputStreamParameters(unique_id);
56 }
57
58 } // namespace
59
60 namespace content {
61
62 AudioOutputAuthorizationHandler::AudioOutputAuthorizationHandler(
63 MediaStreamManager* media_stream_manager,
64 int render_process_id,
65 const std::string& salt)
66 : media_stream_manager_(media_stream_manager),
67 render_process_id_(render_process_id),
68 salt_(salt),
69 weak_factory_(this) {
70 DCHECK(media_stream_manager_);
71 }
72
73 AudioOutputAuthorizationHandler::~AudioOutputAuthorizationHandler() = default;
74
75 void AudioOutputAuthorizationHandler::RequestDeviceAuthorization(
76 int render_frame_id,
77 int session_id,
78 const std::string& device_id,
79 const url::Origin& security_origin,
80 AuthorizationCompletedCallback cb) {
81 DCHECK_CURRENTLY_ON(BrowserThread::IO);
82
83 if (!IsValidDeviceId(device_id)) {
DaleCurtis 2016/11/01 22:01:13 Seems like this should be BadMessage?
Max Morin 2016/11/02 11:47:06 Done.
84 cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
85 media::AudioParameters::UnavailableDeviceParams(), std::string());
86 return;
87 }
88
89 // If |session_id| should be used for output device selection and such 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) {
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 MaybeFixAudioParameters(&output_params);
105
106 cb.Run(media::OUTPUT_DEVICE_STATUS_OK, std::move(output_params),
107 GetHMACForMediaDeviceID(salt_, security_origin,
108 info->device.matched_output_device_id));
109 return;
110 }
111 }
112
113 CheckOutputDeviceAccess(std::move(cb), render_frame_id, device_id,
114 security_origin);
115 }
116
117 void AudioOutputAuthorizationHandler::CheckOutputDeviceAccess(
118 AuthorizationCompletedCallback cb,
119 int render_frame_id,
120 const std::string& device_id,
121 const url::Origin& security_origin) {
122 DCHECK_CURRENTLY_ON(BrowserThread::IO);
123
124 // Check security origin if nondefault device is requested.
125 // Ignore check for default device, which is always authorized.
126 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
127 !MediaStreamManager::IsOriginAllowed(render_process_id_,
128 security_origin)) {
129 bad_message::ReceivedBadMessage(render_process_id_,
130 bad_message::ARH_UNAUTHORIZED_URL);
131 return;
132 }
133
134 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
135 AccessChecked(std::move(cb), device_id, security_origin, true);
136 } else {
137 // Check that MediaStream device permissions have been granted for
138 // nondefault devices.
139 permission_checker_.CheckPermission(
DaleCurtis 2016/11/01 22:01:13 How does this interplay with the device authorizat
Guido Urdaneta 2016/11/01 22:08:17 This introduces some delay with nondefault devices
140 MEDIA_DEVICE_TYPE_AUDIO_OUTPUT, render_process_id_, render_frame_id,
141 security_origin,
142 base::Bind(&AudioOutputAuthorizationHandler::AccessChecked,
143 weak_factory_.GetWeakPtr(), std::move(cb), device_id,
144 security_origin));
145 }
146 }
147
148 void AudioOutputAuthorizationHandler::AccessChecked(
149 AuthorizationCompletedCallback cb,
150 const std::string& device_id,
151 const url::Origin& security_origin,
152 bool have_access) {
153 DCHECK_CURRENTLY_ON(BrowserThread::IO);
154
155 if (!have_access) {
156 cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
157 media::AudioParameters::UnavailableDeviceParams(), std::string());
158 return;
159 }
160
161 // For default device, read output parameters directly. Nondefault devices
162 // require translation first.
163 if (media::AudioDeviceDescription::IsDefaultDevice(device_id)) {
164 base::PostTaskAndReplyWithResult(
165 media::AudioManager::Get()->GetTaskRunner(), FROM_HERE,
166 base::Bind(&GetDeviceParametersOnDeviceThread,
167 media::AudioDeviceDescription::kDefaultDeviceId),
168 base::Bind(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
169 weak_factory_.GetWeakPtr(), std::move(cb), true,
170 media::AudioDeviceDescription::kDefaultDeviceId));
171 } else {
172 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
173 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
174 media_stream_manager_->media_devices_manager()->EnumerateDevices(
175 devices_to_enumerate,
176 base::Bind(&AudioOutputAuthorizationHandler::TranslateDeviceID,
177 weak_factory_.GetWeakPtr(), std::move(cb), device_id,
178 security_origin));
179 }
180 }
181
182 void AudioOutputAuthorizationHandler::TranslateDeviceID(
183 AuthorizationCompletedCallback cb,
184 const std::string& device_id,
185 const url::Origin& security_origin,
186 const MediaDeviceEnumeration& enumeration) {
187 DCHECK_CURRENTLY_ON(BrowserThread::IO);
188 DCHECK(!media::AudioDeviceDescription::IsDefaultDevice(device_id));
189 for (const MediaDeviceInfo& device_info :
190 enumeration[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]) {
191 if (content::DoesMediaDeviceIDMatchHMAC(salt_, security_origin, device_id,
192 device_info.device_id)) {
193 base::PostTaskAndReplyWithResult(
194 media::AudioManager::Get()->GetTaskRunner(), FROM_HERE,
195 base::Bind(&GetDeviceParametersOnDeviceThread, device_info.device_id),
196 base::Bind(&AudioOutputAuthorizationHandler::DeviceParametersReceived,
197 weak_factory_.GetWeakPtr(), std::move(cb), true,
198 device_info.device_id));
199 return;
200 }
201 }
202 DeviceParametersReceived(std::move(cb), false, std::string(),
203 media::AudioParameters::UnavailableDeviceParams());
204 }
205
206 void AudioOutputAuthorizationHandler::DeviceParametersReceived(
207 AuthorizationCompletedCallback cb,
208 bool device_found,
209 const std::string& unique_id,
210 media::AudioParameters output_params) {
211 DCHECK_CURRENTLY_ON(BrowserThread::IO);
212
213 if (!device_found) {
214 cb.Run(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
215 media::AudioParameters::UnavailableDeviceParams(), "");
216 return;
217 }
218
219 MaybeFixAudioParameters(&output_params);
220 cb.Run(media::OUTPUT_DEVICE_STATUS_OK, std::move(output_params), unique_id);
221 }
222
223 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698