Index: content/browser/renderer_host/media/audio_output_service_impl.cc |
diff --git a/content/browser/renderer_host/media/audio_output_service_impl.cc b/content/browser/renderer_host/media/audio_output_service_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..909abe063733fc36c50efb82278a11dfecc8624e |
--- /dev/null |
+++ b/content/browser/renderer_host/media/audio_output_service_impl.cc |
@@ -0,0 +1,125 @@ |
+// Copyright 2016 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/audio_output_service_impl.h" |
+ |
+#include <utility> |
+ |
+#include "base/metrics/histogram_macros.h" |
+#include "base/single_thread_task_runner.h" |
+#include "content/browser/bad_message.h" |
+#include "content/browser/media/capture/audio_mirroring_manager.h" |
+#include "content/browser/renderer_host/media/audio_output_impl.h" |
+#include "content/browser/renderer_host/media/audio_output_service_context.h" |
+#include "content/browser/renderer_host/media/media_stream_manager.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "media/audio/audio_manager.h" |
+#include "media/base/audio_parameters.h" |
+#include "media/mojo/interfaces/audio_output.mojom.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 |
+ |
+// TODO GetOutputControllers :( |
+ |
+AudioOutputServiceImpl::AudioOutputServiceImpl( |
+ AudioOutputServiceContext* context, |
+ int render_frame_id, |
+ base::Callback<void(AudioOutputServiceImpl*)> finished_callback, |
+ media::mojom::AudioOutputServiceRequest request) |
+ : context_(context), |
+ binding_(this, std::move(request)), |
+ audio_outputs_(), |
+ render_frame_id_(render_frame_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ binding_.set_connection_error_handler( |
+ base::Bind(std::move(finished_callback), base::Unretained(this))); |
+} |
+ |
+AudioOutputServiceImpl::~AudioOutputServiceImpl() { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+} |
+ |
+void AudioOutputServiceImpl::RequestDeviceAuthorization( |
+ int64_t session_id, |
+ const std::string& device_id, |
+ media::mojom::AudioOutputRequest audio_output_request, |
+ const url::Origin& origin, |
+ const RequestDeviceAuthorizationCallback& callback) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ const base::TimeTicks auth_start_time = base::TimeTicks::Now(); |
+ |
+ if (!base::IsValueInRangeForNumericType<int>(session_id)) { |
+ UMALogDeviceAuthorizationTime(auth_start_time); |
+ bad_message::ReceivedBadMessage(context_->render_process_id(), |
+ bad_message::AOSI_OUT_OF_RANGE_INTEGER); |
+ return; |
+ } |
+ |
+ context_->authorization_handler()->RequestDeviceAuthorization( |
+ render_frame_id_, static_cast<int>(session_id), device_id, origin, |
+ base::Bind(&AudioOutputServiceImpl::AuthorizationCompleted, |
+ base::Unretained(this), origin, auth_start_time, |
+ base::Passed(std::move(audio_output_request)), callback)); |
+} |
+ |
+void AudioOutputServiceImpl::AuthorizationCompleted( |
+ const url::Origin& origin, |
+ base::TimeTicks auth_start_time, |
+ media::mojom::AudioOutputRequest request, |
+ const RequestDeviceAuthorizationCallback& callback, |
+ media::OutputDeviceStatus status, |
+ bool should_send_id, |
+ const media::AudioParameters& params, |
+ const std::string& raw_device_id) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ UMALogDeviceAuthorizationTime(auth_start_time); |
+ |
+ if (status != media::OUTPUT_DEVICE_STATUS_OK) { |
+ callback.Run(media::OutputDeviceStatus(status), |
+ media::AudioParameters::UnavailableDeviceParams(), |
+ std::string()); |
+ return; |
+ } |
+ |
+ if (request.is_pending()) { |
+ audio_outputs_.push_back(base::MakeUnique<AudioOutputImpl>( |
+ std::move(request), base::BindOnce(&AudioOutputServiceImpl::CloseStream, |
+ base::Unretained(this)), |
+ base::BindOnce(&AudioOutputServiceContext::CreateDelegate, |
+ base::Unretained(context_), raw_device_id, |
+ render_frame_id_))); |
+ } |
+ |
+ callback.Run(media::OutputDeviceStatus(status), params, |
+ should_send_id ? MediaStreamManager::GetHMACForMediaDeviceID( |
+ context_->salt(), origin, raw_device_id) |
+ : std::string()); |
+} |
+ |
+void AudioOutputServiceImpl::CloseStream(AudioOutputImpl* audio_output) { |
+ DCHECK_CURRENTLY_ON(BrowserThread::IO); |
+ auto iter = std::find_if( |
+ audio_outputs_.begin(), audio_outputs_.end(), |
+ [audio_output](const std::unique_ptr<AudioOutputImpl>& other) { |
+ return audio_output == other.get(); |
+ }); |
+ if (iter == audio_outputs_.end()) |
+ return; |
+ std::swap(*iter, audio_outputs_.back()); |
+ audio_outputs_.pop_back(); |
+} |
+ |
+} // namespace content |