| Index: content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
|
| diff --git a/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc b/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
|
| deleted file mode 100644
|
| index 2e3f864930138de9d28b287cdf73af6fd3b902f6..0000000000000000000000000000000000000000
|
| --- a/content/browser/renderer_host/media/render_frame_audio_output_stream_factory_unittest.cc
|
| +++ /dev/null
|
| @@ -1,371 +0,0 @@
|
| -// 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 <limits>
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/memory/shared_memory.h"
|
| -#include "base/memory/shared_memory_handle.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/sync_socket.h"
|
| -#include "content/browser/renderer_host/media/media_stream_manager.h"
|
| -#include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context.h"
|
| -#include "content/common/media/renderer_audio_output_stream_factory.mojom.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "content/public/test/test_browser_context.h"
|
| -#include "content/public/test/test_browser_thread_bundle.h"
|
| -#include "media/audio/audio_output_controller.h"
|
| -#include "media/base/audio_parameters.h"
|
| -#include "mojo/edk/embedder/embedder.h"
|
| -#include "mojo/public/cpp/bindings/binding.h"
|
| -#include "mojo/public/cpp/system/platform_handle.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace content {
|
| -
|
| -namespace {
|
| -
|
| -using testing::Test;
|
| -using AudioOutputStreamFactory = mojom::RendererAudioOutputStreamFactory;
|
| -using AudioOutputStreamFactoryPtr =
|
| - mojo::InterfacePtr<AudioOutputStreamFactory>;
|
| -using AudioOutputStreamFactoryRequest =
|
| - mojo::InterfaceRequest<AudioOutputStreamFactory>;
|
| -using AudioOutputStream = media::mojom::AudioOutputStream;
|
| -using AudioOutputStreamPtr = mojo::InterfacePtr<AudioOutputStream>;
|
| -using AudioOutputStreamRequest = mojo::InterfaceRequest<AudioOutputStream>;
|
| -using AudioOutputStreamProvider = media::mojom::AudioOutputStreamProvider;
|
| -using AudioOutputStreamProviderPtr =
|
| - mojo::InterfacePtr<AudioOutputStreamProvider>;
|
| -using AudioOutputStreamProviderRequest =
|
| - mojo::InterfaceRequest<AudioOutputStreamProvider>;
|
| -
|
| -const int kStreamId = 0;
|
| -const int kNoSessionId = 0;
|
| -const int kRenderProcessId = 42;
|
| -const int kRenderFrameId = 24;
|
| -const int kSampleFrequency = 44100;
|
| -const int kBitsPerSample = 16;
|
| -const int kSamplesPerBuffer = kSampleFrequency / 100;
|
| -const char kSalt[] = "salt";
|
| -
|
| -media::AudioParameters GetTestAudioParameters() {
|
| - return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
|
| - media::CHANNEL_LAYOUT_MONO, kSampleFrequency,
|
| - kBitsPerSample, kSamplesPerBuffer);
|
| -}
|
| -
|
| -class MockAudioOutputDelegate : public media::AudioOutputDelegate {
|
| - public:
|
| - // |on_destruction| can be used to observe the destruction of the delegate.
|
| - explicit MockAudioOutputDelegate(
|
| - base::OnceClosure on_destruction = base::OnceClosure())
|
| - : on_destruction_(std::move(on_destruction)) {}
|
| -
|
| - ~MockAudioOutputDelegate() {
|
| - if (on_destruction_)
|
| - std::move(on_destruction_).Run();
|
| - }
|
| -
|
| - MOCK_CONST_METHOD0(GetController,
|
| - scoped_refptr<media::AudioOutputController>());
|
| - MOCK_CONST_METHOD0(GetStreamId, int());
|
| - MOCK_METHOD0(OnPlayStream, void());
|
| - MOCK_METHOD0(OnPauseStream, void());
|
| - MOCK_METHOD1(OnSetVolume, void(double));
|
| -
|
| - private:
|
| - base::OnceClosure on_destruction_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockAudioOutputDelegate);
|
| -};
|
| -
|
| -class MockContext : public RendererAudioOutputStreamFactoryContext {
|
| - public:
|
| - explicit MockContext(bool auth_ok) : salt_(kSalt), auth_ok_(auth_ok) {}
|
| -
|
| - ~MockContext() override { EXPECT_EQ(nullptr, delegate_); }
|
| -
|
| - int GetRenderProcessId() const override { return kRenderProcessId; }
|
| -
|
| - std::string GetHMACForDeviceId(
|
| - const url::Origin& origin,
|
| - const std::string& raw_device_id) const override {
|
| - return MediaStreamManager::GetHMACForMediaDeviceID(salt_, origin,
|
| - raw_device_id);
|
| - }
|
| -
|
| - void RequestDeviceAuthorization(
|
| - int render_frame_id,
|
| - int session_id,
|
| - const std::string& device_id,
|
| - const url::Origin& security_origin,
|
| - AuthorizationCompletedCallback cb) const override {
|
| - EXPECT_EQ(render_frame_id, kRenderFrameId);
|
| - EXPECT_EQ(session_id, 0);
|
| - if (auth_ok_) {
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(cb, media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK,
|
| - false, GetTestAudioParameters(), "default"));
|
| - return;
|
| - }
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(cb,
|
| - media::OutputDeviceStatus::
|
| - OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
|
| - false, media::AudioParameters::UnavailableDeviceParams(),
|
| - ""));
|
| - }
|
| -
|
| - // The event handler for the delegate will be stored at
|
| - // |*event_handler_location| when the delegate is created.
|
| - void PrepareDelegateForCreation(
|
| - std::unique_ptr<media::AudioOutputDelegate> delegate,
|
| - media::AudioOutputDelegate::EventHandler** event_handler_location) {
|
| - EXPECT_EQ(nullptr, delegate_);
|
| - EXPECT_EQ(nullptr, delegate_event_handler_location_);
|
| - delegate_ = std::move(delegate);
|
| - delegate_event_handler_location_ = event_handler_location;
|
| - }
|
| -
|
| - std::unique_ptr<media::AudioOutputDelegate> CreateDelegate(
|
| - const std::string& unique_device_id,
|
| - int render_frame_id,
|
| - const media::AudioParameters& params,
|
| - media::AudioOutputDelegate::EventHandler* handler) override {
|
| - EXPECT_NE(nullptr, delegate_);
|
| - EXPECT_NE(nullptr, delegate_event_handler_location_);
|
| - *delegate_event_handler_location_ = handler;
|
| - delegate_event_handler_location_ = nullptr;
|
| - return std::move(delegate_);
|
| - }
|
| -
|
| - AudioOutputStreamFactoryPtr CreateFactory() {
|
| - DCHECK(!factory_);
|
| - AudioOutputStreamFactoryPtr ret;
|
| - factory_ = base::MakeUnique<RenderFrameAudioOutputStreamFactory>(
|
| - kRenderFrameId, this);
|
| - factory_binding_ = base::MakeUnique<
|
| - mojo::Binding<mojom::RendererAudioOutputStreamFactory>>(factory_.get(),
|
| - &ret);
|
| - return ret;
|
| - }
|
| -
|
| - private:
|
| - const std::string salt_;
|
| - const bool auth_ok_;
|
| - std::unique_ptr<RenderFrameAudioOutputStreamFactory> factory_;
|
| - std::unique_ptr<mojo::Binding<mojom::RendererAudioOutputStreamFactory>>
|
| - factory_binding_;
|
| - std::unique_ptr<media::AudioOutputDelegate> delegate_;
|
| - media::AudioOutputDelegate::EventHandler** delegate_event_handler_location_ =
|
| - nullptr;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockContext);
|
| -};
|
| -
|
| -class MockClient {
|
| - public:
|
| - MockClient() {}
|
| - ~MockClient() {}
|
| -
|
| - void StreamCreated(mojo::ScopedSharedBufferHandle handle1,
|
| - mojo::ScopedHandle handle2) {
|
| - was_called_ = true;
|
| - }
|
| -
|
| - bool was_called() { return was_called_; }
|
| -
|
| - private:
|
| - bool was_called_ = false;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockClient);
|
| -};
|
| -
|
| -void AuthCallback(media::OutputDeviceStatus* status_out,
|
| - media::AudioParameters* params_out,
|
| - std::string* id_out,
|
| - media::OutputDeviceStatus status,
|
| - const media::AudioParameters& params,
|
| - const std::string& id) {
|
| - *status_out = status;
|
| - *params_out = params;
|
| - *id_out = id;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -// This test authorizes and creates a stream, and checks that
|
| -// 1. the authorization callback is called with appropriate parameters.
|
| -// 2. the AudioOutputDelegate is created.
|
| -// 3. when the delegate calls OnStreamCreated, this is propagated to the client.
|
| -TEST(RenderFrameAudioOutputStreamFactoryTest, CreateStream) {
|
| - content::TestBrowserThreadBundle thread_bundle;
|
| - AudioOutputStreamProviderPtr provider;
|
| - AudioOutputStreamPtr output_stream;
|
| - MockClient client;
|
| - media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
|
| - auto factory_context = base::MakeUnique<MockContext>(true);
|
| - factory_context->PrepareDelegateForCreation(
|
| - base::MakeUnique<MockAudioOutputDelegate>(), &event_handler);
|
| - AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
|
| -
|
| - media::OutputDeviceStatus status;
|
| - media::AudioParameters params;
|
| - std::string id;
|
| - factory_ptr->RequestDeviceAuthorization(
|
| - mojo::MakeRequest(&provider), kNoSessionId, "default",
|
| - base::Bind(&AuthCallback, base::Unretained(&status),
|
| - base::Unretained(¶ms), base::Unretained(&id)));
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_OK);
|
| - EXPECT_EQ(params.AsHumanReadableString(),
|
| - GetTestAudioParameters().AsHumanReadableString());
|
| - EXPECT_TRUE(id.empty());
|
| -
|
| - provider->Acquire(
|
| - mojo::MakeRequest<AudioOutputStream>(&output_stream), params,
|
| - base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
|
| - base::RunLoop().RunUntilIdle();
|
| - ASSERT_NE(event_handler, nullptr);
|
| -
|
| - base::SharedMemory shared_memory;
|
| - ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(100));
|
| -
|
| - base::CancelableSyncSocket local, remote;
|
| - ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&local, &remote));
|
| - event_handler->OnStreamCreated(kStreamId, &shared_memory, &remote);
|
| -
|
| - base::RunLoop().RunUntilIdle();
|
| - // Make sure we got the callback from creating stream.
|
| - EXPECT_TRUE(client.was_called());
|
| -}
|
| -
|
| -TEST(RenderFrameAudioOutputStreamFactoryTest, NotAuthorized_Denied) {
|
| - content::TestBrowserThreadBundle thread_bundle;
|
| - AudioOutputStreamProviderPtr output_provider;
|
| - auto factory_context = base::MakeUnique<MockContext>(false);
|
| - AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
|
| -
|
| - media::OutputDeviceStatus status;
|
| - media::AudioParameters params;
|
| - std::string id;
|
| - factory_ptr->RequestDeviceAuthorization(
|
| - mojo::MakeRequest(&output_provider), kNoSessionId, "default",
|
| - base::Bind(&AuthCallback, base::Unretained(&status),
|
| - base::Unretained(¶ms), base::Unretained(&id)));
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_EQ(status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED);
|
| - EXPECT_TRUE(id.empty());
|
| -}
|
| -
|
| -TEST(RenderFrameAudioOutputStreamFactoryTest, ConnectionError_DeletesStream) {
|
| - content::TestBrowserThreadBundle thread_bundle;
|
| - AudioOutputStreamProviderPtr provider;
|
| - AudioOutputStreamPtr output_stream;
|
| - MockClient client;
|
| - bool delegate_is_destructed = false;
|
| - media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
|
| - auto factory_context = base::MakeUnique<MockContext>(true);
|
| - factory_context->PrepareDelegateForCreation(
|
| - base::MakeUnique<MockAudioOutputDelegate>(
|
| - base::BindOnce([](bool* destructed) { *destructed = true; },
|
| - &delegate_is_destructed)),
|
| - &event_handler);
|
| - AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
|
| -
|
| - factory_ptr->RequestDeviceAuthorization(
|
| - mojo::MakeRequest(&provider), kNoSessionId, "default",
|
| - base::Bind([](media::OutputDeviceStatus status,
|
| - const media::AudioParameters& params,
|
| - const std::string& id) {}));
|
| - base::RunLoop().RunUntilIdle();
|
| -
|
| - provider->Acquire(
|
| - mojo::MakeRequest<AudioOutputStream>(&output_stream),
|
| - GetTestAudioParameters(),
|
| - base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
|
| - base::RunLoop().RunUntilIdle();
|
| - ASSERT_NE(event_handler, nullptr);
|
| - EXPECT_FALSE(delegate_is_destructed);
|
| - output_stream.reset();
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_TRUE(delegate_is_destructed);
|
| -}
|
| -
|
| -TEST(RenderFrameAudioOutputStreamFactoryTest, DelegateError_DeletesStream) {
|
| - content::TestBrowserThreadBundle thread_bundle;
|
| - AudioOutputStreamProviderPtr provider;
|
| - AudioOutputStreamPtr output_stream;
|
| - MockClient client;
|
| - bool delegate_is_destructed = false;
|
| - media::AudioOutputDelegate::EventHandler* event_handler = nullptr;
|
| - auto factory_context = base::MakeUnique<MockContext>(true);
|
| - factory_context->PrepareDelegateForCreation(
|
| - base::MakeUnique<MockAudioOutputDelegate>(
|
| - base::BindOnce([](bool* destructed) { *destructed = true; },
|
| - &delegate_is_destructed)),
|
| - &event_handler);
|
| - AudioOutputStreamFactoryPtr factory_ptr = factory_context->CreateFactory();
|
| -
|
| - factory_ptr->RequestDeviceAuthorization(
|
| - mojo::MakeRequest(&provider), kNoSessionId, "default",
|
| - base::Bind([](media::OutputDeviceStatus status,
|
| - const media::AudioParameters& params,
|
| - const std::string& id) {}));
|
| - base::RunLoop().RunUntilIdle();
|
| -
|
| - provider->Acquire(
|
| - mojo::MakeRequest<AudioOutputStream>(&output_stream),
|
| - GetTestAudioParameters(),
|
| - base::Bind(&MockClient::StreamCreated, base::Unretained(&client)));
|
| - base::RunLoop().RunUntilIdle();
|
| - ASSERT_NE(event_handler, nullptr);
|
| - EXPECT_FALSE(delegate_is_destructed);
|
| - event_handler->OnStreamError(kStreamId);
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_TRUE(delegate_is_destructed);
|
| -}
|
| -
|
| -TEST(RenderFrameAudioOutputStreamFactoryTest, OutOfRangeSessionId_BadMessage) {
|
| - // This test checks that we get a bad message if session_id is too large
|
| - // to fit in an integer. This ensures that we don't overflow when casting the
|
| - // int64_t to an int
|
| - if (sizeof(int) >= sizeof(int64_t)) {
|
| - // In this case, any int64_t would fit in an int, and the case we are
|
| - // checking for is impossible.
|
| - return;
|
| - }
|
| -
|
| - bool got_bad_message = false;
|
| - mojo::edk::SetDefaultProcessErrorCallback(
|
| - base::Bind([](bool* got_bad_message,
|
| - const std::string& s) { *got_bad_message = true; },
|
| - &got_bad_message));
|
| -
|
| - TestBrowserThreadBundle thread_bundle;
|
| -
|
| - AudioOutputStreamProviderPtr output_provider;
|
| - auto factory_context = base::MakeUnique<MockContext>(true);
|
| - auto factory_ptr = factory_context->CreateFactory();
|
| -
|
| - int64_t session_id = std::numeric_limits<int>::max();
|
| - ++session_id;
|
| -
|
| - EXPECT_FALSE(got_bad_message);
|
| - factory_ptr->RequestDeviceAuthorization(
|
| - mojo::MakeRequest(&output_provider), session_id, "default",
|
| - base::Bind([](media::OutputDeviceStatus, const media::AudioParameters&,
|
| - const std::string&) {}));
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_TRUE(got_bad_message);
|
| -}
|
| -
|
| -} // namespace content
|
|
|