Chromium Code Reviews| Index: content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc |
| diff --git a/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc b/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3e078343a3de21f4e3c8a95fb5d2f6f324039cc3 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/media/render_frame_audio_output_stream_factory.cc |
| @@ -0,0 +1,117 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/media/render_frame_audio_output_stream_factory.h" |
| + |
| +#include <utility> |
| + |
| +#include "base/metrics/histogram_macros.h" |
| +#include "base/threading/thread_checker.h" |
| +#include "content/browser/bad_message.h" |
| +#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h" |
| +#include "media/base/audio_parameters.h" |
| +#include "media/mojo/services/mojo_audio_output_stream_provider.h" |
| +#include "mojo/public/cpp/bindings/binding.h" |
| + |
| +namespace content { |
| + |
| +namespace { |
| + |
| +void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) { |
| + UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime", |
| + base::TimeTicks::Now() - auth_start_time, |
| + base::TimeDelta::FromMilliseconds(1), |
| + base::TimeDelta::FromMilliseconds(5000), 50); |
| +} |
| + |
| +} // namespace |
| + |
| +RenderFrameAudioOutputStreamFactory::RenderFrameAudioOutputStreamFactory( |
| + RendererAudioOutputStreamFactoryContext* context, |
| + int render_frame_id) |
| + : context_(context), render_frame_id_(render_frame_id) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
|
DaleCurtis
2017/03/24 17:47:12
Meaningless right? It's bound to the thread first
Max Morin
2017/03/27 14:40:50
Done.
|
| + DCHECK(context_); |
| +} |
| + |
| +RenderFrameAudioOutputStreamFactory::~RenderFrameAudioOutputStreamFactory() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| +} |
|
DaleCurtis
2017/03/24 17:47:12
DCHECK(stream_providers_.empty()) ? Otherwise you
Max Morin
2017/03/27 14:40:50
I changed this to explicitly clear |stream_provide
|
| + |
| +void RenderFrameAudioOutputStreamFactory::RequestDeviceAuthorization( |
| + media::mojom::AudioOutputStreamProviderRequest stream_provider_request, |
| + int64_t session_id, |
| + const std::string& device_id, |
| + const url::Origin& origin, |
| + const RequestDeviceAuthorizationCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + const base::TimeTicks auth_start_time = base::TimeTicks::Now(); |
| + |
| + if (!base::IsValueInRangeForNumericType<int>(session_id)) { |
| + UMALogDeviceAuthorizationTime(auth_start_time); |
|
DaleCurtis
2017/03/24 17:47:12
We don't log this in the existing ARH, so it will
Max Morin
2017/03/27 14:40:50
In practice, this branch will hopefully never happ
|
| + bad_message::ReceivedBadMessage(context_->GetRenderProcessId(), |
| + bad_message::RFAOSF_OUT_OF_RANGE_INTEGER); |
| + // Note: We must call the callback even though we are killing the renderer. |
| + // This is mandated by mojo. |
| + callback.Run( |
| + media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED, |
| + media::AudioParameters::UnavailableDeviceParams(), std::string()); |
| + return; |
| + } |
| + |
| + context_->RequestDeviceAuthorization( |
| + render_frame_id_, static_cast<int>(session_id), device_id, origin, |
|
DaleCurtis
2017/03/24 17:47:12
Hmm, why do we bother sending int64_t across if we
Max Morin
2017/03/27 14:40:50
Since mojom files are cross-platform, we cannot us
|
| + base::Bind(&RenderFrameAudioOutputStreamFactory::AuthorizationCompleted, |
| + base::Unretained(this), origin, auth_start_time, |
| + base::Passed(&stream_provider_request), callback)); |
| +} |
| + |
| +void RenderFrameAudioOutputStreamFactory::AuthorizationCompleted( |
| + const url::Origin& origin, |
| + base::TimeTicks auth_start_time, |
| + media::mojom::AudioOutputStreamProviderRequest request, |
| + const RequestDeviceAuthorizationCallback& callback, |
| + media::OutputDeviceStatus status, |
| + bool should_send_id, |
| + const media::AudioParameters& params, |
| + const std::string& raw_device_id) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + UMALogDeviceAuthorizationTime(auth_start_time); |
| + |
| + if (status != media::OUTPUT_DEVICE_STATUS_OK) { |
| + callback.Run(media::OutputDeviceStatus(status), |
| + media::AudioParameters::UnavailableDeviceParams(), |
| + std::string()); |
| + return; |
| + } |
| + |
| + stream_providers_.push_back( |
| + base::MakeUnique<media::MojoAudioOutputStreamProvider>( |
| + std::move(request), |
| + base::BindOnce( |
| + &RendererAudioOutputStreamFactoryContext::CreateDelegate, |
| + base::Unretained(context_), raw_device_id, render_frame_id_), |
| + base::Bind(&RenderFrameAudioOutputStreamFactory::RemoveStream, |
| + base::Unretained(this)))); |
|
DaleCurtis
2017/03/24 17:47:12
See note above; seems like this could lead to call
Max Morin
2017/03/27 14:40:50
I clarified the lifetime of all stream providers a
|
| + |
| + callback.Run(media::OutputDeviceStatus(status), params, |
| + should_send_id |
| + ? context_->GetHMACForDeviceId(origin, raw_device_id) |
| + : std::string()); |
| +} |
| + |
| +void RenderFrameAudioOutputStreamFactory::RemoveStream( |
| + media::mojom::AudioOutputStreamProvider* stream_provider) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| + auto it = std::find_if( |
|
DaleCurtis
2017/03/24 17:47:12
base::EraseIf, if you want.
Max Morin
2017/03/27 14:40:50
Done. Since I found flat_set, I also changed to us
|
| + stream_providers_.begin(), stream_providers_.end(), |
| + [stream_provider]( |
| + const std::unique_ptr<media::mojom::AudioOutputStreamProvider>& |
| + other) { return other.get() == stream_provider; }); |
| + std::swap(*it, stream_providers_.back()); |
| + stream_providers_.pop_back(); |
| +} |
| + |
| +} // namespace content |