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

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

Issue 2289543003: IPC->mojo of audio_renderer_host (Closed)
Patch Set: New interface. Created 4 years, 3 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/shared_memory.h" 13 #include "base/memory/shared_memory.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/process/process.h" 15 #include "base/process/process.h"
16 #include "content/browser/bad_message.h" 16 #include "content/browser/bad_message.h"
17 #include "content/browser/browser_main_loop.h" 17 #include "content/browser/browser_main_loop.h"
18 #include "content/browser/media/audio_stream_monitor.h" 18 #include "content/browser/media/audio_stream_monitor.h"
19 #include "content/browser/media/capture/audio_mirroring_manager.h" 19 #include "content/browser/media/capture/audio_mirroring_manager.h"
20 #include "content/browser/media/media_internals.h" 20 #include "content/browser/media/media_internals.h"
21 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 21 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
22 #include "content/browser/renderer_host/media/audio_sync_reader.h" 22 #include "content/browser/renderer_host/media/audio_sync_reader.h"
23 #include "content/browser/renderer_host/media/media_stream_manager.h" 23 #include "content/browser/renderer_host/media/media_stream_manager.h"
24 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 24 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
25 #include "content/browser/renderer_host/render_widget_host_impl.h" 25 #include "content/browser/renderer_host/render_widget_host_impl.h"
26 #include "content/common/media/audio_messages.h"
27 #include "content/public/browser/content_browser_client.h" 26 #include "content/public/browser/content_browser_client.h"
28 #include "content/public/browser/media_device_id.h" 27 #include "content/public/browser/media_device_id.h"
29 #include "content/public/browser/media_observer.h" 28 #include "content/public/browser/media_observer.h"
30 #include "content/public/browser/render_frame_host.h" 29 #include "content/public/browser/render_frame_host.h"
31 #include "content/public/common/content_switches.h" 30 #include "content/public/common/content_switches.h"
32 #include "media/audio/audio_device_description.h" 31 #include "media/audio/audio_device_description.h"
33 #include "media/audio/audio_streams_tracker.h" 32 #include "media/audio/audio_streams_tracker.h"
34 #include "media/base/audio_bus.h" 33 #include "media/base/audio_bus.h"
35 #include "media/base/limits.h" 34 #include "media/base/limits.h"
35 #include "media/mojo/interfaces/audio_output.mojom-shared.h"
36 #include "media/mojo/interfaces/audio_output.mojom.h"
37 #include "mojo/edk/embedder/embedder.h"
38 #include "mojo/public/cpp/system/handle.h"
39 #include "mojo/public/cpp/system/platform_handle.h"
36 40
37 using media::AudioBus; 41 using media::AudioBus;
38 using media::AudioManager; 42 using media::AudioManager;
39 43
40 namespace content { 44 namespace content {
41 45
42 namespace { 46 namespace {
43 47
44 // Tracks the maximum number of simultaneous output streams browser-wide. 48 // Tracks the maximum number of simultaneous output streams browser-wide.
45 // Accessed on IO thread. 49 // Accessed on IO thread.
46 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = 50 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker =
47 LAZY_INSTANCE_INITIALIZER; 51 LAZY_INSTANCE_INITIALIZER;
48 52
49 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( 53 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData(
50 int stream_id, 54 int32_t stream_id,
51 bool authorized, 55 bool authorized,
52 const std::string& device_unique_id) { 56 const std::string& device_unique_id) {
53 return std::make_pair(stream_id, 57 return std::make_pair(stream_id,
54 std::make_pair(authorized, device_unique_id)); 58 std::make_pair(authorized, device_unique_id));
55 } 59 }
56 60
57 bool IsValidDeviceId(const std::string& device_id) { 61 bool IsValidDeviceId(const std::string& device_id) {
58 static const std::string::size_type kValidLength = 64; 62 static const std::string::size_type kValidLength = 64;
59 63
60 if (device_id.empty() || 64 if (device_id.empty() ||
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const bool frame_exists = 129 const bool frame_exists =
126 !!RenderFrameHost::FromID(render_process_id, render_frame_id); 130 !!RenderFrameHost::FromID(render_process_id, render_frame_id);
127 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 131 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
128 base::Bind(callback, frame_exists)); 132 base::Bind(callback, frame_exists));
129 } 133 }
130 #endif // DCHECK_IS_ON() 134 #endif // DCHECK_IS_ON()
131 135
132 } // namespace 136 } // namespace
133 137
134 class AudioRendererHost::AudioEntry 138 class AudioRendererHost::AudioEntry
135 : public media::AudioOutputController::EventHandler { 139 : public media::AudioOutputController::EventHandler,
140 private media::mojom::AudioOutputStream {
136 public: 141 public:
137 AudioEntry(AudioRendererHost* host, 142 AudioEntry(AudioRendererHost* host,
138 int stream_id, 143 int32_t stream_id,
139 int render_frame_id, 144 int render_frame_id,
140 const media::AudioParameters& params, 145 const media::AudioParameters& params,
141 const std::string& output_device_id, 146 const std::string& output_device_id,
142 std::unique_ptr<base::SharedMemory> shared_memory, 147 std::unique_ptr<base::SharedMemory> shared_memory,
143 std::unique_ptr<media::AudioOutputController::SyncReader> reader); 148 std::unique_ptr<media::AudioOutputController::SyncReader> reader);
144 ~AudioEntry() override; 149 ~AudioEntry() override;
145 150
146 int stream_id() const { 151 int32_t stream_id() const { return stream_id_; }
147 return stream_id_;
148 }
149 152
150 int render_frame_id() const { return render_frame_id_; } 153 int render_frame_id() const { return render_frame_id_; }
151 154
152 media::AudioOutputController* controller() const { return controller_.get(); } 155 media::AudioOutputController* controller() const { return controller_.get(); }
153 156
154 base::SharedMemory* shared_memory() { 157 base::SharedMemory* shared_memory() {
155 return shared_memory_.get(); 158 return shared_memory_.get();
156 } 159 }
157 160
158 media::AudioOutputController::SyncReader* reader() const { 161 media::AudioOutputController::SyncReader* reader() const {
159 return reader_.get(); 162 return reader_.get();
160 } 163 }
161 164
162 bool playing() const { return playing_; } 165 bool playing() const { return playing_; }
163 void set_playing(bool playing) { playing_ = playing; } 166 void set_playing(bool playing) { playing_ = playing; }
164 167
168 // media::mojom::AudioOutputStream implementation
169 void Play() override;
170 void Pause() override;
171 void SetVolume(double volume) override;
172
173 void OnConnectionError();
174 void BindRequest(media::mojom::AudioOutputStreamRequest);
175
165 private: 176 private:
166 // media::AudioOutputController::EventHandler implementation. 177 // media::AudioOutputController::EventHandler implementation.
167 void OnCreated() override; 178 void OnCreated() override;
168 void OnPlaying() override; 179 void OnPlaying() override;
169 void OnPaused() override; 180 void OnPaused() override;
170 void OnError() override; 181 void OnError() override;
171 182
172 AudioRendererHost* const host_; 183 AudioRendererHost* const host_;
173 const int stream_id_; 184 const int32_t stream_id_;
174 185
175 // The routing ID of the source RenderFrame. 186 // The routing ID of the source RenderFrame.
176 const int render_frame_id_; 187 const int render_frame_id_;
177 188
178 // Shared memory for transmission of the audio data. Used by |reader_|. 189 // Shared memory for transmission of the audio data. Used by |reader_|.
179 const std::unique_ptr<base::SharedMemory> shared_memory_; 190 const std::unique_ptr<base::SharedMemory> shared_memory_;
180 191
181 // The synchronous reader to be used by |controller_|. 192 // The synchronous reader to be used by |controller_|.
182 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; 193 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_;
183 194
184 // The AudioOutputController that manages the audio stream. 195 // The AudioOutputController that manages the audio stream.
185 const scoped_refptr<media::AudioOutputController> controller_; 196 const scoped_refptr<media::AudioOutputController> controller_;
186 197
198 // Binds |this| to an AudioOutputStreamPtr that is passed to the
199 // AudioOutputStreamClient (AudioOutputIPC in the renderer process).
200 std::unique_ptr<mojo::Binding<media::mojom::AudioOutputStream>> binding_;
201
187 bool playing_; 202 bool playing_;
203
204 DISALLOW_COPY_AND_ASSIGN(AudioEntry);
188 }; 205 };
189 206
190 AudioRendererHost::AudioEntry::AudioEntry( 207 AudioRendererHost::AudioEntry::AudioEntry(
191 AudioRendererHost* host, 208 AudioRendererHost* host,
192 int stream_id, 209 int32_t stream_id,
193 int render_frame_id, 210 int render_frame_id,
194 const media::AudioParameters& params, 211 const media::AudioParameters& params,
195 const std::string& output_device_id, 212 const std::string& output_device_id,
196 std::unique_ptr<base::SharedMemory> shared_memory, 213 std::unique_ptr<base::SharedMemory> shared_memory,
197 std::unique_ptr<media::AudioOutputController::SyncReader> reader) 214 std::unique_ptr<media::AudioOutputController::SyncReader> reader)
198 : host_(host), 215 : host_(host),
199 stream_id_(stream_id), 216 stream_id_(stream_id),
200 render_frame_id_(render_frame_id), 217 render_frame_id_(render_frame_id),
201 shared_memory_(std::move(shared_memory)), 218 shared_memory_(std::move(shared_memory)),
202 reader_(std::move(reader)), 219 reader_(std::move(reader)),
203 controller_(media::AudioOutputController::Create(host->audio_manager_, 220 controller_(media::AudioOutputController::Create(host->audio_manager_,
204 this, 221 this,
205 params, 222 params,
206 output_device_id, 223 output_device_id,
207 reader_.get())), 224 reader_.get())),
225 callback_(callback),
208 playing_(false) { 226 playing_(false) {
209 DCHECK(controller_.get()); 227 DCHECK(controller_.get());
228
229 BrowserThread::PostTask(
230 BrowserThread::IO, FROM_HERE,
231 base::Bind(&AudioRendererHost::OnCloseStream, host_, stream_id_));
232 }
233
234 void AudioRendererHost::AudioEntry::Play() {
235 controller_->Play();
236 host_->audio_log_->OnStarted(stream_id_);
237 }
238
239 void AudioRendererHost::AudioEntry::Pause() {
240 controller_->Pause();
241 host_->audio_log_->OnStopped(stream_id_);
242 }
243
244 void AudioRendererHost::AudioEntry::SetVolume(double volume) {
245 if (volume < 0 || volume > 1.0)
246 return;
247
248 controller_->SetVolume(volume);
249 host_->audio_log_->OnSetVolume(stream_id_, volume);
250 }
251
252 void AudioRendererHost::AudioEntry::OnConnectionError() {
253 binding_.reset();
254
255 BrowserThread::PostTask(
256 BrowserThread::IO, FROM_HERE,
257 base::Bind(&AudioRendererHost::CloseStream, host_, stream_id_));
258 }
259
260 void AudioRendererHost::AudioEntry::BindRequest(
261 media::mojom::AudioOutputStreamRequest request) {
262 DCHECK_CURRENTLY_ON(BrowserThread::IO);
263
264 binding_.reset(new mojo::Binding<media::mojom::AudioOutputStream>(
265 this, std::move(request)));
266 binding_->set_connection_error_handler(
267 base::Bind(&AudioEntry::OnConnectionError, base::Unretained(this)));
210 } 268 }
211 269
212 AudioRendererHost::AudioEntry::~AudioEntry() {} 270 AudioRendererHost::AudioEntry::~AudioEntry() {}
213 271
214 /////////////////////////////////////////////////////////////////////////////// 272 ///////////////////////////////////////////////////////////////////////////////
215 // AudioRendererHost implementations. 273 // AudioRendererHost implementations.
216 274
217 AudioRendererHost::AudioRendererHost(int render_process_id, 275 AudioRendererHost::AudioRendererHost(int render_process_id,
218 media::AudioManager* audio_manager, 276 media::AudioManager* audio_manager,
219 AudioMirroringManager* mirroring_manager, 277 AudioMirroringManager* mirroring_manager,
220 MediaInternals* media_internals, 278 MediaInternals* media_internals,
221 MediaStreamManager* media_stream_manager, 279 MediaStreamManager* media_stream_manager,
222 const std::string& salt) 280 const std::string& salt)
223 : BrowserMessageFilter(AudioMsgStart), 281 : render_process_id_(render_process_id),
224 render_process_id_(render_process_id),
225 audio_manager_(audio_manager), 282 audio_manager_(audio_manager),
226 mirroring_manager_(mirroring_manager), 283 mirroring_manager_(mirroring_manager),
227 audio_log_(media_internals->CreateAudioLog( 284 audio_log_(media_internals->CreateAudioLog(
228 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)), 285 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
229 media_stream_manager_(media_stream_manager), 286 media_stream_manager_(media_stream_manager),
230 num_playing_streams_(0), 287 num_playing_streams_(0),
231 salt_(salt), 288 salt_(salt),
289 next_stream_id_(0),
232 #if DCHECK_IS_ON() 290 #if DCHECK_IS_ON()
233 validate_render_frame_id_function_(&ValidateRenderFrameId), 291 validate_render_frame_id_function_(&ValidateRenderFrameId),
234 #endif // DCHECK_IS_ON() 292 #endif // DCHECK_IS_ON()
235 max_simultaneous_streams_(0) { 293 max_simultaneous_streams_(0) {
236 DCHECK(audio_manager_); 294 DCHECK(audio_manager_);
237 DCHECK(media_stream_manager_); 295 DCHECK(media_stream_manager_);
238 } 296 }
239 297
240 AudioRendererHost::~AudioRendererHost() { 298 AudioRendererHost::~AudioRendererHost() {
241 DCHECK_CURRENTLY_ON(BrowserThread::IO); 299 DCHECK_CURRENTLY_ON(BrowserThread::IO);
(...skipping 14 matching lines...) Expand all
256 } 314 }
257 315
258 void AudioRendererHost::GetOutputControllers( 316 void AudioRendererHost::GetOutputControllers(
259 const RenderProcessHost::GetAudioOutputControllersCallback& 317 const RenderProcessHost::GetAudioOutputControllersCallback&
260 callback) const { 318 callback) const {
261 BrowserThread::PostTaskAndReplyWithResult( 319 BrowserThread::PostTaskAndReplyWithResult(
262 BrowserThread::IO, FROM_HERE, 320 BrowserThread::IO, FROM_HERE,
263 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback); 321 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback);
264 } 322 }
265 323
266 void AudioRendererHost::OnChannelClosing() {
267 DCHECK_CURRENTLY_ON(BrowserThread::IO);
268 // Since the IPC sender is gone, close all requested audio streams.
269 while (!audio_entries_.empty()) {
270 // Note: OnCloseStream() removes the entries from audio_entries_.
271 OnCloseStream(audio_entries_.begin()->first);
272 }
273
274 // Remove any authorizations for streams that were not yet created
275 authorizations_.clear();
276 }
277
278 void AudioRendererHost::OnDestruct() const {
279 BrowserThread::DeleteOnIOThread::Destruct(this);
280 }
281
282 void AudioRendererHost::AudioEntry::OnCreated() { 324 void AudioRendererHost::AudioEntry::OnCreated() {
283 BrowserThread::PostTask( 325 // TODO: make sure it's safe to capture |this| in the callback.
284 BrowserThread::IO, 326 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
285 FROM_HERE, 327 base::Bind(&AudioRendererHost::DoCompleteCreation,
286 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); 328 host_, this, stream_id_, callback_));
287 } 329 }
288 330
289 void AudioRendererHost::AudioEntry::OnPlaying() { 331 void AudioRendererHost::AudioEntry::OnPlaying() {
290 BrowserThread::PostTask(
291 BrowserThread::IO,
292 FROM_HERE,
293 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
294 host_,
295 stream_id_,
296 true));
297 } 332 }
298 333
299 void AudioRendererHost::AudioEntry::OnPaused() { 334 void AudioRendererHost::AudioEntry::OnPaused() {
300 BrowserThread::PostTask(
301 BrowserThread::IO,
302 FROM_HERE,
303 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged,
304 host_,
305 stream_id_,
306 false));
307 } 335 }
308 336
309 void AudioRendererHost::AudioEntry::OnError() { 337 void AudioRendererHost::AudioEntry::OnError() {
310 BrowserThread::PostTask( 338 BrowserThread::PostTask(
311 BrowserThread::IO, 339 BrowserThread::IO, FROM_HERE,
312 FROM_HERE, 340 base::Bind(&AudioRendererHost::OnCloseStream, host_, stream_id_));
313 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
314 } 341 }
315 342
316 void AudioRendererHost::DoCompleteCreation(int stream_id) { 343 void AudioRendererHost::DoCompleteCreation(AudioEntry* entry,
344 int32_t stream_id) {
317 DCHECK_CURRENTLY_ON(BrowserThread::IO); 345 DCHECK_CURRENTLY_ON(BrowserThread::IO);
318 346
319 if (!PeerHandle()) { 347 media::mojom::AudioOutputStreamPtr stream_ptr;
320 DLOG(WARNING) << "Renderer process handle is invalid."; 348 entry->BindRequest(mojo::GetProxy(&stream_ptr));
321 ReportErrorAndClose(stream_id);
322 return;
323 }
324
325 AudioEntry* const entry = LookupById(stream_id);
326 if (!entry) {
327 ReportErrorAndClose(stream_id);
328 return;
329 }
330
331 // Once the audio stream is created then complete the creation process by
332 // mapping shared memory and sharing with the renderer process.
333 base::SharedMemoryHandle foreign_memory_handle;
334 if (!entry->shared_memory()->ShareToProcess(PeerHandle(),
335 &foreign_memory_handle)) {
336 // If we failed to map and share the shared memory then close the audio
337 // stream and send an error message.
338 ReportErrorAndClose(entry->stream_id());
339 return;
340 }
341 349
342 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); 350 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
351 base::PlatformFile socket_fd = reader->GetSyncSocket();
352 mojo::ScopedHandle socket_handle = mojo::WrapPlatformFile(socket_fd);
353 DCHECK(socket_handle.is_valid());
343 354
344 base::SyncSocket::TransitDescriptor socket_descriptor; 355 base::SharedMemoryHandle shared_memory_handle =
356 base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle());
357 if (!base::SharedMemory::IsHandleValid(shared_memory_handle)) {
358 // TODO: When can this happen?
359 LOG(FATAL) << "Invalid shared mem handle";
360 return ReportErrorAndClose(stream_id);
361 }
362 mojo::ScopedSharedBufferHandle shared_buffer_handle =
363 mojo::WrapSharedMemoryHandle(shared_memory_handle,
364 entry->shared_memory()->requested_size(),
365 false);
366 DCHECK(shared_buffer_handle.is_valid());
345 367
346 // If we failed to prepare the sync socket for the renderer then we fail 368 /*mojo::ScopedSharedBufferHandle shared_buffer_handle =
347 // the construction of audio stream. 369 mojo::WrapSharedMemoryHandle(shared_memory_handle,
348 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { 370 entry->shared_memory()->requested_size(),
349 ReportErrorAndClose(entry->stream_id()); 371 false);*/
350 return;
351 }
352 372
353 Send(new AudioMsg_NotifyStreamCreated( 373 /* TODO: read comment.
354 entry->stream_id(), foreign_memory_handle, socket_descriptor, 374 // The socket sent from the browser to the renderer is a ForeignSocket, which
355 entry->shared_memory()->requested_size())); 375 // is a part of AudioSyncReader that is owned by AudioEntry. The socket handle
376 // is closed when the owning AudioEntry destructs. With mojo, the ownership of
377 // the handle is transferred to the target process. The handle is no longer
378 // valid in the sending process, and cannot be closed there. If the socket
379 // handle is closed when the AudioEntry is deleted, an error occurs. To WAR
380 // this error, duplicate the socket and send the duplicate to the renderer.
381 #if defined(OS_WIN)
382 mojo::ScopedHandle socket_handle =
383 mojo::WrapPlatformFile(socket_descriptor);
384 #else
385 mojo::ScopedHandle socket_handle =
386 mojo::WrapPlatformFile(socket_descriptor.fd);
387 #endif
388 */
389
390 callback.Run(std::move(stream_ptr), std::move(shared_buffer_handle),
391 std::move(socket_handle));
356 } 392 }
357 393
358 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, 394 /*void AudioRendererHost::DoNotifyStreamStateChanged(int32_t stream_id,
359 bool is_playing) { 395 bool is_playing) {
360 DCHECK_CURRENTLY_ON(BrowserThread::IO); 396 DCHECK_CURRENTLY_ON(BrowserThread::IO);
361 397
362 AudioEntry* const entry = LookupById(stream_id); 398 AudioEntry* const entry = LookupById(stream_id);
363 if (!entry) 399 if (!entry)
364 return; 400 return;
365 401
366 Send(new AudioMsg_NotifyStreamStateChanged( 402 entry->SendStreamStateResponse(
367 stream_id, 403 is_playing ? media::mojom::AudioOutputStreamState::PLAYING
368 is_playing ? media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING 404 : media::mojom::AudioOutputStreamState::PAUSED);
369 : media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED));
370 405
371 if (is_playing) { 406 if (is_playing) {
372 AudioStreamMonitor::StartMonitoringStream( 407 AudioStreamMonitor::StartMonitoringStream(
373 render_process_id_, 408 render_process_id_,
374 entry->render_frame_id(), 409 entry->render_frame_id(),
375 entry->stream_id(), 410 entry->stream_id(),
376 base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip, 411 base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
377 entry->controller())); 412 entry->controller()));
378 } else { 413 } else {
379 AudioStreamMonitor::StopMonitoringStream( 414 AudioStreamMonitor::StopMonitoringStream(
380 render_process_id_, entry->render_frame_id(), entry->stream_id()); 415 render_process_id_, entry->render_frame_id(), entry->stream_id());
381 } 416 }
382 UpdateNumPlayingStreams(entry, is_playing); 417 UpdateNumPlayingStreams(entry, is_playing);
383 } 418 }*/
384 419
385 RenderProcessHost::AudioOutputControllerList 420 RenderProcessHost::AudioOutputControllerList
386 AudioRendererHost::DoGetOutputControllers() const { 421 AudioRendererHost::DoGetOutputControllers() const {
387 DCHECK_CURRENTLY_ON(BrowserThread::IO); 422 DCHECK_CURRENTLY_ON(BrowserThread::IO);
388 423
389 RenderProcessHost::AudioOutputControllerList controllers; 424 RenderProcessHost::AudioOutputControllerList controllers;
390 for (AudioEntryMap::const_iterator it = audio_entries_.begin(); 425 for (AudioEntryMap::const_iterator it = audio_entries_.begin();
391 it != audio_entries_.end(); 426 it != audio_entries_.end();
392 ++it) { 427 ++it) {
393 controllers.push_back(it->second->controller()); 428 controllers.push_back(it->second->controller());
394 } 429 }
395 430
396 return controllers; 431 return controllers;
397 } 432 }
398 433
399 /////////////////////////////////////////////////////////////////////////////// 434 void AudioRendererHost::OnDeviceAuthorized(
400 // IPC Messages handler 435 int32_t stream_id,
401 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { 436 RequestDeviceAuthorizationCallback callback,
402 bool handled = true;
403 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
404 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization,
405 OnRequestDeviceAuthorization)
406 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream)
407 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream)
408 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream)
409 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream)
410 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume)
411 IPC_MESSAGE_UNHANDLED(handled = false)
412 IPC_END_MESSAGE_MAP()
413
414 return handled;
415 }
416
417 void AudioRendererHost::OnRequestDeviceAuthorization(
418 int stream_id,
419 int render_frame_id,
420 int session_id,
421 const std::string& device_id, 437 const std::string& device_id,
422 const url::Origin& security_origin) { 438 const url::Origin& security_origin,
423 DCHECK_CURRENTLY_ON(BrowserThread::IO); 439 base::TimeTicks auth_start_time,
424 const base::TimeTicks auth_start_time = base::TimeTicks::Now(); 440 bool have_access) {
425
426 DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization"
427 << "(stream_id=" << stream_id
428 << ", render_frame_id=" << render_frame_id
429 << ", session_id=" << session_id << ", device_id=" << device_id
430 << ", security_origin=" << security_origin << ")";
431
432 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
433 return;
434
435 if (!IsValidDeviceId(device_id)) {
436 UMALogDeviceAuthorizationTime(auth_start_time);
437 Send(new AudioMsg_NotifyDeviceAuthorized(
438 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
439 media::AudioParameters::UnavailableDeviceParams(), std::string()));
440 return;
441 }
442
443 // If |session_id should be used for output device selection and such output
444 // device is found, reuse the input device permissions.
445 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
446 device_id)) {
447 const StreamDeviceInfo* info =
448 media_stream_manager_->audio_input_device_manager()
449 ->GetOpenedDeviceInfoById(session_id);
450 if (info) {
451 media::AudioParameters output_params(
452 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
453 static_cast<media::ChannelLayout>(
454 info->device.matched_output.channel_layout),
455 info->device.matched_output.sample_rate, 16,
456 info->device.matched_output.frames_per_buffer);
457 output_params.set_effects(info->device.matched_output.effects);
458 authorizations_.insert(MakeAuthorizationData(
459 stream_id, true, info->device.matched_output_device_id));
460 MaybeFixAudioParameters(&output_params);
461 UMALogDeviceAuthorizationTime(auth_start_time);
462 // Hash matched device id and pass it to the renderer
463 Send(new AudioMsg_NotifyDeviceAuthorized(
464 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
465 GetHMACForMediaDeviceID(salt_, security_origin,
466 info->device.matched_output_device_id)));
467 return;
468 }
469 }
470
471 authorizations_.insert(
472 MakeAuthorizationData(stream_id, false, std::string()));
473 CheckOutputDeviceAccess(
474 render_frame_id, device_id, security_origin,
475 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
476 device_id, security_origin, auth_start_time));
477 }
478
479 void AudioRendererHost::OnDeviceAuthorized(int stream_id,
480 const std::string& device_id,
481 const url::Origin& security_origin,
482 base::TimeTicks auth_start_time,
483 bool have_access) {
484 DCHECK_CURRENTLY_ON(BrowserThread::IO); 441 DCHECK_CURRENTLY_ON(BrowserThread::IO);
485 const auto& auth_data = authorizations_.find(stream_id); 442 const auto& auth_data = authorizations_.find(stream_id);
486 443
487 // A close request was received while access check was in progress. 444 // A close request was received while access check was in progress.
488 if (auth_data == authorizations_.end()) { 445 if (auth_data == authorizations_.end()) {
489 UMALogDeviceAuthorizationTime(auth_start_time); 446 UMALogDeviceAuthorizationTime(auth_start_time);
490 return; 447 return;
491 } 448 }
492 449
493 if (!have_access) { 450 if (!have_access) {
494 authorizations_.erase(auth_data); 451 authorizations_.erase(auth_data);
495 UMALogDeviceAuthorizationTime(auth_start_time); 452 UMALogDeviceAuthorizationTime(auth_start_time);
496 Send(new AudioMsg_NotifyDeviceAuthorized( 453 SendAuthorizationMessage(
497 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED, 454 callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
498 media::AudioParameters::UnavailableDeviceParams(), std::string())); 455 media::AudioParameters::UnavailableDeviceParams(), std::string());
499 return; 456 return;
500 } 457 }
501 458
502 // If enumerator caching is disabled, avoid the enumeration if the default 459 // If enumerator caching is disabled, avoid the enumeration if the default
503 // device is requested, since no device ID translation is needed. 460 // device is requested, since no device ID translation is needed.
504 // If enumerator caching is enabled, it is better to use its cache, even 461 // If enumerator caching is enabled, it is better to use its cache, even
505 // for the default device. 462 // for the default device.
506 if (media::AudioDeviceDescription::IsDefaultDevice(device_id) && 463 if (media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
507 !media_stream_manager_->audio_output_device_enumerator() 464 !media_stream_manager_->audio_output_device_enumerator()
508 ->IsCacheEnabled()) { 465 ->IsCacheEnabled()) {
509 base::PostTaskAndReplyWithResult( 466 base::PostTaskAndReplyWithResult(
510 audio_manager_->GetTaskRunner(), FROM_HERE, 467 audio_manager_->GetTaskRunner(), FROM_HERE,
511 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), 468 base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
512 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, 469 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
513 auth_start_time, true)); 470 auth_start_time, callback, true));
514 } else { 471 } else {
515 media_stream_manager_->audio_output_device_enumerator()->Enumerate( 472 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
516 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, 473 base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id,
517 security_origin, 474 security_origin,
518 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, 475 base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this,
519 stream_id, auth_start_time))); 476 stream_id, auth_start_time, callback)));
520 } 477 }
521 } 478 }
522 479
523 void AudioRendererHost::OnDeviceIDTranslated( 480 void AudioRendererHost::OnDeviceIDTranslated(
524 int stream_id, 481 int32_t stream_id,
525 base::TimeTicks auth_start_time, 482 base::TimeTicks auth_start_time,
483 RequestDeviceAuthorizationCallback callback,
526 bool device_found, 484 bool device_found,
527 const AudioOutputDeviceInfo& device_info) { 485 const AudioOutputDeviceInfo& device_info) {
528 DCHECK_CURRENTLY_ON(BrowserThread::IO); 486 DCHECK_CURRENTLY_ON(BrowserThread::IO);
529 const auto& auth_data = authorizations_.find(stream_id); 487 const auto& auth_data = authorizations_.find(stream_id);
530 488
531 // A close request was received while translation was in progress 489 // A close request was received while translation was in progress
532 if (auth_data == authorizations_.end()) { 490 if (auth_data == authorizations_.end()) {
533 UMALogDeviceAuthorizationTime(auth_start_time); 491 UMALogDeviceAuthorizationTime(auth_start_time);
534 return; 492 return;
535 } 493 }
536 494
537 if (!device_found) { 495 if (!device_found) {
538 authorizations_.erase(auth_data); 496 authorizations_.erase(auth_data);
539 UMALogDeviceAuthorizationTime(auth_start_time); 497 UMALogDeviceAuthorizationTime(auth_start_time);
540 Send(new AudioMsg_NotifyDeviceAuthorized( 498 SendAuthorizationMessage(
541 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, 499 callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
542 media::AudioParameters::UnavailableDeviceParams(), std::string())); 500 media::AudioParameters::UnavailableDeviceParams(), std::string());
543 return; 501 return;
544 } 502 }
545 503
546 auth_data->second.first = true; 504 auth_data->second.first = true;
547 auth_data->second.second = device_info.unique_id; 505 auth_data->second.second = device_info.unique_id;
548 506
549 media::AudioParameters output_params = device_info.output_params; 507 media::AudioParameters output_params = device_info.output_params;
550 MaybeFixAudioParameters(&output_params); 508 MaybeFixAudioParameters(&output_params);
551 UMALogDeviceAuthorizationTime(auth_start_time); 509 UMALogDeviceAuthorizationTime(auth_start_time);
552 Send(new AudioMsg_NotifyDeviceAuthorized( 510 SendAuthorizationMessage(callback, stream_id, media::OUTPUT_DEVICE_STATUS_OK,
553 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); 511 output_params, std::string());
554 } 512 }
555 513
556 void AudioRendererHost::OnCreateStream(int stream_id, 514 void AudioRendererHost::DoCreateStream(int32_t stream_id,
557 int render_frame_id,
558 const media::AudioParameters& params) {
559 DCHECK_CURRENTLY_ON(BrowserThread::IO);
560 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream"
561 << "(stream_id=" << stream_id << ")";
562
563 // Determine whether to use the device_unique_id from an authorization, or an
564 // empty string (i.e., when no previous authorization was requested, assume
565 // default device).
566 std::string device_unique_id;
567 const auto& auth_data = authorizations_.find(stream_id);
568 if (auth_data != authorizations_.end()) {
569 CHECK(auth_data->second.first);
570 device_unique_id.swap(auth_data->second.second);
571 authorizations_.erase(auth_data);
572 }
573
574 #if DCHECK_IS_ON()
575 // When DCHECKs are turned on, hop over to the UI thread to validate the
576 // |render_frame_id|, then continue stream creation on the IO thread. See
577 // comment at top of DoCreateStream() for further details.
578 BrowserThread::PostTask(
579 BrowserThread::UI, FROM_HERE,
580 base::Bind(validate_render_frame_id_function_, render_process_id_,
581 render_frame_id,
582 base::Bind(&AudioRendererHost::DoCreateStream, this, stream_id,
583 render_frame_id, params, device_unique_id)));
584 #else
585 DoCreateStream(stream_id, render_frame_id, params, device_unique_id,
586 render_frame_id > 0);
587 #endif // DCHECK_IS_ON()
588 }
589
590 void AudioRendererHost::DoCreateStream(int stream_id,
591 int render_frame_id, 515 int render_frame_id,
592 const media::AudioParameters& params, 516 const media::AudioParameters& params,
593 const std::string& device_unique_id, 517 const std::string& device_unique_id,
594 bool render_frame_id_is_valid) { 518 bool render_frame_id_is_valid) {
595 DCHECK_CURRENTLY_ON(BrowserThread::IO); 519 DCHECK_CURRENTLY_ON(BrowserThread::IO);
596 520
597 // Fail early if either of two sanity-checks fail: 521 // Fail early if either of two sanity-checks fail:
598 // 1. There should not yet exist an AudioEntry for the given |stream_id| 522 // 1. There should not yet exist an AudioEntry for the given |stream_id|
599 // since the renderer may not create two streams with the same ID. 523 // since the renderer may not create two streams with the same ID.
600 // 2. The render frame ID was either invalid or the render frame host it 524 // 2. The render frame ID was either invalid or the render frame host it
(...skipping 11 matching lines...) Expand all
612 if (!render_frame_id_is_valid) { 536 if (!render_frame_id_is_valid) {
613 SendErrorMessage(stream_id); 537 SendErrorMessage(stream_id);
614 return; 538 return;
615 } 539 }
616 540
617 // Create the shared memory and share with the renderer process. 541 // Create the shared memory and share with the renderer process.
618 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + 542 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) +
619 AudioBus::CalculateMemorySize(params); 543 AudioBus::CalculateMemorySize(params);
620 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); 544 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
621 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { 545 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
546 // client->OnStreamStateChange(media::mojom::AudioOutputStreamState::ERROR);
622 SendErrorMessage(stream_id); 547 SendErrorMessage(stream_id);
623 return; 548 return;
624 } 549 }
625 550
626 std::unique_ptr<AudioSyncReader> reader( 551 std::unique_ptr<AudioSyncReader> reader(
627 new AudioSyncReader(shared_memory.get(), params)); 552 new AudioSyncReader(shared_memory.get(), params));
628 if (!reader->Init()) { 553 if (!reader->Init()) {
629 SendErrorMessage(stream_id); 554 SendErrorMessage(stream_id);
630 return; 555 return;
631 } 556 }
632 557
633 MediaObserver* const media_observer = 558 MediaObserver* const media_observer =
634 GetContentClient()->browser()->GetMediaObserver(); 559 GetContentClient()->browser()->GetMediaObserver();
635 if (media_observer) 560 if (media_observer)
636 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); 561 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
637 562
638 std::unique_ptr<AudioEntry> entry( 563 std::unique_ptr<AudioEntry> entry(new AudioEntry(
639 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, 564 this, callback, stream_id, render_frame_id, params, device_unique_id,
640 std::move(shared_memory), std::move(reader))); 565 std::move(shared_memory), std::move(reader)));
641 if (mirroring_manager_) { 566 if (mirroring_manager_) {
642 mirroring_manager_->AddDiverter( 567 mirroring_manager_->AddDiverter(
643 render_process_id_, entry->render_frame_id(), entry->controller()); 568 render_process_id_, entry->render_frame_id(), entry->controller());
644 } 569 }
645 audio_entries_.insert(std::make_pair(stream_id, entry.release())); 570 audio_entries_.insert(std::make_pair(stream_id, entry.release()));
646 g_audio_streams_tracker.Get().IncreaseStreamCount(); 571 g_audio_streams_tracker.Get().IncreaseStreamCount();
647 572
648 audio_log_->OnCreated(stream_id, params, device_unique_id); 573 audio_log_->OnCreated(stream_id, params, device_unique_id);
649 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( 574 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry(
650 stream_id, render_process_id_, render_frame_id, audio_log_.get()); 575 stream_id, render_process_id_, render_frame_id, audio_log_.get());
651 576
652 if (audio_entries_.size() > max_simultaneous_streams_) 577 if (audio_entries_.size() > max_simultaneous_streams_)
653 max_simultaneous_streams_ = audio_entries_.size(); 578 max_simultaneous_streams_ = audio_entries_.size();
654 } 579 }
655 580
656 void AudioRendererHost::OnPlayStream(int stream_id) { 581 void AudioRendererHost::OnPlayStream(int32_t stream_id) {
657 DCHECK_CURRENTLY_ON(BrowserThread::IO); 582 DCHECK_CURRENTLY_ON(BrowserThread::IO);
658 583
659 AudioEntry* entry = LookupById(stream_id); 584 AudioEntry* entry = LookupById(stream_id);
660 if (!entry) { 585 if (!entry) {
661 SendErrorMessage(stream_id); 586 SendErrorMessage(stream_id);
662 return; 587 return;
663 } 588 }
664 589
665 entry->controller()->Play(); 590 entry->controller()->Play();
666 audio_log_->OnStarted(stream_id); 591 audio_log_->OnStarted(stream_id);
667 } 592 }
668 593
669 void AudioRendererHost::OnPauseStream(int stream_id) { 594 void AudioRendererHost::OnPauseStream(int32_t stream_id) {
670 DCHECK_CURRENTLY_ON(BrowserThread::IO); 595 DCHECK_CURRENTLY_ON(BrowserThread::IO);
671 596
672 AudioEntry* entry = LookupById(stream_id); 597 AudioEntry* entry = LookupById(stream_id);
673 if (!entry) { 598 if (!entry) {
674 SendErrorMessage(stream_id); 599 SendErrorMessage(stream_id);
675 return; 600 return;
676 } 601 }
677 602
678 entry->controller()->Pause(); 603 entry->controller()->Pause();
679 audio_log_->OnStopped(stream_id); 604 audio_log_->OnStopped(stream_id);
680 } 605 }
681 606
682 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { 607 void AudioRendererHost::OnSetVolume(int32_t stream_id, double volume) {
683 DCHECK_CURRENTLY_ON(BrowserThread::IO); 608 DCHECK_CURRENTLY_ON(BrowserThread::IO);
684 609
685 AudioEntry* entry = LookupById(stream_id); 610 AudioEntry* entry = LookupById(stream_id);
686 if (!entry) { 611 if (!entry) {
687 SendErrorMessage(stream_id); 612 SendErrorMessage(stream_id);
688 return; 613 return;
689 } 614 }
690 615
691 // Make sure the volume is valid. 616 // Make sure the volume is valid.
692 if (volume < 0 || volume > 1.0) 617 if (volume < 0 || volume > 1.0)
693 return; 618 return;
694 entry->controller()->SetVolume(volume); 619 entry->controller()->SetVolume(volume);
695 audio_log_->OnSetVolume(stream_id, volume); 620 audio_log_->OnSetVolume(stream_id, volume);
696 } 621 }
697 622
698 void AudioRendererHost::SendErrorMessage(int stream_id) { 623 void AudioRendererHost::SendErrorMessage(int32_t stream_id) {
699 Send(new AudioMsg_NotifyStreamStateChanged( 624 // TODO
700 stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR));
701 } 625 }
702 626
703 void AudioRendererHost::OnCloseStream(int stream_id) { 627 void AudioRendererHost::OnCloseStream(int32_t stream_id) {
704 DCHECK_CURRENTLY_ON(BrowserThread::IO); 628 DCHECK_CURRENTLY_ON(BrowserThread::IO);
705 authorizations_.erase(stream_id); 629 authorizations_.erase(stream_id);
706 630
707 // Prevent oustanding callbacks from attempting to close/delete the same 631 // Prevent oustanding callbacks from attempting to close/delete the same
708 // AudioEntry twice. 632 // AudioEntry twice.
709 AudioEntryMap::iterator i = audio_entries_.find(stream_id); 633 AudioEntryMap::iterator i = audio_entries_.find(stream_id);
710 if (i == audio_entries_.end()) 634 if (i == audio_entries_.end())
711 return; 635 return;
712 std::unique_ptr<AudioEntry> entry(i->second); 636 std::unique_ptr<AudioEntry> entry(i->second);
713 audio_entries_.erase(i); 637 audio_entries_.erase(i);
(...skipping 14 matching lines...) Expand all
728 // re-start the default AudioOutputStream and cause a brief audio blip to come 652 // re-start the default AudioOutputStream and cause a brief audio blip to come
729 // out the user's speakers. http://crbug.com/474432 653 // out the user's speakers. http://crbug.com/474432
730 if (mirroring_manager_) 654 if (mirroring_manager_)
731 mirroring_manager_->RemoveDiverter(entry->controller()); 655 mirroring_manager_->RemoveDiverter(entry->controller());
732 656
733 AudioStreamMonitor::StopMonitoringStream( 657 AudioStreamMonitor::StopMonitoringStream(
734 render_process_id_, entry->render_frame_id(), entry->stream_id()); 658 render_process_id_, entry->render_frame_id(), entry->stream_id());
735 UpdateNumPlayingStreams(entry.get(), false); 659 UpdateNumPlayingStreams(entry.get(), false);
736 } 660 }
737 661
738 void AudioRendererHost::ReportErrorAndClose(int stream_id) { 662 void AudioRendererHost::ReportErrorAndClose(int32_t stream_id) {
739 DCHECK_CURRENTLY_ON(BrowserThread::IO); 663 DCHECK_CURRENTLY_ON(BrowserThread::IO);
740 664
741 // Make sure this isn't a stray callback executing after the stream has been 665 // Make sure this isn't a stray callback executing after the stream has been
742 // closed, so error notifications aren't sent after clients believe the stream 666 // closed, so error notifications aren't sent after clients believe the stream
743 // is closed. 667 // is closed.
744 if (!LookupById(stream_id)) 668 if (!LookupById(stream_id))
745 return; 669 return;
746 670
747 SendErrorMessage(stream_id); 671 SendErrorMessage(stream_id);
748 672
749 audio_log_->OnError(stream_id); 673 audio_log_->OnError(stream_id);
750 OnCloseStream(stream_id); 674 OnCloseStream(stream_id);
751 } 675 }
752 676
753 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { 677 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(
678 int32_t stream_id) {
754 DCHECK_CURRENTLY_ON(BrowserThread::IO); 679 DCHECK_CURRENTLY_ON(BrowserThread::IO);
755 680
756 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); 681 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
757 return i != audio_entries_.end() ? i->second : NULL; 682 return i != audio_entries_.end() ? i->second : NULL;
758 } 683 }
759 684
760 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, 685 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
761 bool is_playing) { 686 bool is_playing) {
762 DCHECK_CURRENTLY_ON(BrowserThread::IO); 687 DCHECK_CURRENTLY_ON(BrowserThread::IO);
763 if (entry->playing() == is_playing) 688 if (entry->playing() == is_playing)
(...skipping 20 matching lines...) Expand all
784 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged, 709 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
785 render_process_id_)); 710 render_process_id_));
786 } 711 }
787 } 712 }
788 } 713 }
789 714
790 bool AudioRendererHost::HasActiveAudio() { 715 bool AudioRendererHost::HasActiveAudio() {
791 return !base::AtomicRefCountIsZero(&num_playing_streams_); 716 return !base::AtomicRefCountIsZero(&num_playing_streams_);
792 } 717 }
793 718
719 void AudioRendererHost::BindRequest(media::mojom::AudioOutputRequest request) {
720 DCHECK_CURRENTLY_ON(BrowserThread::IO);
721
722 binding_.reset(
723 new mojo::Binding<media::mojom::AudioOutput>(this, std::move(request)));
724 }
725
726 // media::mojom::AudioOutput implementation
727 void AudioRendererHost::RequestDeviceAuthorization(
728 int64_t render_frame_id,
729 int64_t session_id,
730 const mojo::String& device_id,
731 const url::Origin& origin,
732 const RequestDeviceAuthorizationCallback& callback) {
733 DCHECK_CURRENTLY_ON(BrowserThread::IO);
734 const base::TimeTicks auth_start_time = base::TimeTicks::Now();
735 int32_t stream_id = next_stream_id++;
736
737 DVLOG(1) << "AudioRendererHost@" << this << "::RequestDeviceAuthorization"
738 << "(stream_id=" << stream_id
739 << ", render_frame_id=" << render_frame_id
740 << ", session_id=" << session_id << ", device_id=" << device_id
741 << ", origin=" << origin << ")";
742
743 if (LookupById(stream_id) || IsAuthorizationStarted(stream_id))
744 return;
745
746 if (!IsValidDeviceId(device_id)) {
747 UMALogDeviceAuthorizationTime(auth_start_time);
748 SendAuthorizationMessage(
749 callback, stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
750 media::AudioParameters::UnavailableDeviceParams(), std::string());
751 return;
752 }
753
754 // If |session_id should be used for output device selection and such output
755 // device is found, reuse the input device permissions.
756 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
757 device_id)) {
758 const StreamDeviceInfo* info =
759 media_stream_manager_->audio_input_device_manager()
760 ->GetOpenedDeviceInfoById(session_id);
761 if (info) {
762 media::AudioParameters output_params(
763 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
764 static_cast<media::ChannelLayout>(
765 info->device.matched_output.channel_layout),
766 info->device.matched_output.sample_rate, 16,
767 info->device.matched_output.frames_per_buffer);
768 output_params.set_effects(info->device.matched_output.effects);
769 authorizations_.insert(MakeAuthorizationData(
770 stream_id, true, info->device.matched_output_device_id));
771 MaybeFixAudioParameters(&output_params);
772 UMALogDeviceAuthorizationTime(auth_start_time);
773 // Hash matched device id and pass it to the renderer
774 SendAuthorizationMessage(
775 callback, stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params,
776 GetHMACForMediaDeviceID(salt_, origin,
777 info->device.matched_output_device_id));
778 return;
779 }
780 }
781
782 authorizations_.insert(
783 MakeAuthorizationData(stream_id, false, std::string()));
784 CheckOutputDeviceAccess(
785 render_frame_id, device_id, origin,
786 base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id,
787 callback, device_id, origin, auth_start_time));
788 }
789
790 void AudioRendererHost::CreateStream(int32_t stream_id,
791 int render_frame_id,
792 const media::AudioParameters& params) {
793 DCHECK_CURRENTLY_ON(BrowserThread::IO);
794 DVLOG(1) << "AudioRendererHost@" << this << "::CreateStream"
795 << "(stream_id=" << stream_id << ")";
796
797 // Determine whether to use the device_unique_id from an authorization, or an
798 // empty string (i.e., when no previous authorization was requested, assume
799 // default device).
800 std::string device_unique_id;
801 const auto& auth_data = authorizations_.find(stream_id);
802 if (auth_data != authorizations_.end()) {
803 CHECK(auth_data->second.first);
804 device_unique_id.swap(auth_data->second.second);
805 authorizations_.erase(auth_data);
806 }
807
808 #if DCHECK_IS_ON()
809 // When DCHECKs are turned on, hop over to the UI thread to validate the
810 // |render_frame_id|, then continue stream creation on the IO thread. See
811 // comment at top of DoCreateStream() for further details.
812 BrowserThread::PostTask(
813 BrowserThread::UI, FROM_HERE,
814 base::Bind(validate_render_frame_id_function_, render_process_id_,
815 render_frame_id,
816 base::Bind(&AudioRendererHost::DoCreateStream, this, stream_id,
817 render_frame_id, params, device_unique_id)));
818 #else
819 DoCreateStream(stream_id, render_frame_id, params, device_unique_id,
820 render_frame_id > 0);
821 #endif // DCHECK_IS_ON()
822 }
823
824 void AudioRendererHost::CloseStream(int32_t stream_id) {
825 DCHECK_CURRENTLY_ON(BrowserThread::IO);
826
827 OnCloseStream(stream_id);
828 }
829
830 void AudioRendererHost::SendAuthorizationMessage(
831 RequestDeviceAuthorizationCallback callback,
832 int32_t stream_id,
833 media::OutputDeviceStatus status,
834 const media::AudioParameters& params,
835 const std::string& matched_device_id) {
836 DCHECK_CURRENTLY_ON(BrowserThread::IO);
837
838 callback.Run(status, params, matched_device_id);
839 }
840
794 void AudioRendererHost::CheckOutputDeviceAccess( 841 void AudioRendererHost::CheckOutputDeviceAccess(
795 int render_frame_id, 842 int render_frame_id,
796 const std::string& device_id, 843 const std::string& device_id,
797 const url::Origin& security_origin, 844 const url::Origin& security_origin,
798 const OutputDeviceAccessCB& callback) { 845 const OutputDeviceAccessCB& callback) {
799 DCHECK_CURRENTLY_ON(BrowserThread::IO); 846 DCHECK_CURRENTLY_ON(BrowserThread::IO);
800 847
801 // Check security origin if nondefault device is requested. 848 // Check security origin if nondefault device is requested.
802 // Ignore check for default device, which is always authorized. 849 // Ignore check for default device, which is always authorized.
803 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) && 850 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) &&
804 !MediaStreamManager::IsOriginAllowed(render_process_id_, 851 !MediaStreamManager::IsOriginAllowed(render_process_id_,
805 security_origin)) { 852 security_origin)) {
806 content::bad_message::ReceivedBadMessage(this, 853 // content::bad_message::ReceivedBadMessage(this,
807 bad_message::ARH_UNAUTHORIZED_URL); 854 // bad_message::ARH_UNAUTHORIZED_URL);
808 return; 855 return;
809 } 856 }
810 857
811 if (device_id.empty()) { 858 if (device_id.empty()) {
812 callback.Run(true); 859 callback.Run(true);
813 } else { 860 } else {
814 // Check that MediaStream device permissions have been granted, 861 // Check that MediaStream device permissions have been granted,
815 // hence the use of a MediaStreamUIProxy. 862 // hence the use of a MediaStreamUIProxy.
816 std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create(); 863 std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
817 864
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 return; 901 return;
855 } 902 }
856 } 903 }
857 DCHECK(!device_id.empty()); // Default device must always be found 904 DCHECK(!device_id.empty()); // Default device must always be found
858 AudioOutputDeviceInfo device_info = { 905 AudioOutputDeviceInfo device_info = {
859 std::string(), std::string(), 906 std::string(), std::string(),
860 media::AudioParameters::UnavailableDeviceParams()}; 907 media::AudioParameters::UnavailableDeviceParams()};
861 callback.Run(false, device_info); 908 callback.Run(false, device_info);
862 } 909 }
863 910
864 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { 911 bool AudioRendererHost::IsAuthorizationStarted(int32_t stream_id) {
865 DCHECK_CURRENTLY_ON(BrowserThread::IO); 912 DCHECK_CURRENTLY_ON(BrowserThread::IO);
866 const auto& i = authorizations_.find(stream_id); 913 const auto& i = authorizations_.find(stream_id);
867 return i != authorizations_.end(); 914 return i != authorizations_.end();
868 } 915 }
869 916
870 } // namespace content 917 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698