123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- // Copyright 2018 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 "services/video_capture/device_media_to_mojo_adapter.h"
- #include "base/callback_helpers.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/test/task_environment.h"
- #include "build/chromeos_buildflags.h"
- #include "media/capture/video/mock_device.h"
- #include "mojo/public/cpp/bindings/pending_remote.h"
- #include "services/video_capture/public/cpp/mock_video_frame_handler.h"
- #include "services/video_capture/public/mojom/video_frame_handler.mojom.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using testing::Invoke;
- using testing::_;
- namespace video_capture {
- class DeviceMediaToMojoAdapterTest : public ::testing::Test {
- public:
- DeviceMediaToMojoAdapterTest() = default;
- ~DeviceMediaToMojoAdapterTest() override = default;
- void SetUp() override {
- mock_video_frame_handler_ = std::make_unique<MockVideoFrameHandler>(
- video_frame_handler_.InitWithNewPipeAndPassReceiver());
- auto mock_device = std::make_unique<media::MockDevice>();
- mock_device_ptr_ = mock_device.get();
- #if BUILDFLAG(IS_CHROMEOS_ASH)
- adapter_ = std::make_unique<DeviceMediaToMojoAdapter>(
- std::move(mock_device), base::DoNothing(),
- base::ThreadTaskRunnerHandle::Get());
- #elif BUILDFLAG(IS_WIN)
- adapter_ = std::make_unique<DeviceMediaToMojoAdapter>(
- std::move(mock_device), nullptr);
- #else
- adapter_ =
- std::make_unique<DeviceMediaToMojoAdapter>(std::move(mock_device));
- #endif // BUILDFLAG(IS_CHROMEOS_ASH)
- }
- void TearDown() override {
- // The internals of ReceiverOnTaskRunner perform a DeleteSoon().
- adapter_.reset();
- base::RunLoop wait_loop;
- wait_loop.RunUntilIdle();
- }
- protected:
- raw_ptr<media::MockDevice> mock_device_ptr_;
- std::unique_ptr<DeviceMediaToMojoAdapter> adapter_;
- std::unique_ptr<MockVideoFrameHandler> mock_video_frame_handler_;
- mojo::PendingRemote<mojom::VideoFrameHandler> video_frame_handler_;
- base::test::TaskEnvironment task_environment_;
- };
- TEST_F(DeviceMediaToMojoAdapterTest,
- DeviceIsStoppedWhenReceiverClosesConnection) {
- {
- base::RunLoop run_loop;
- EXPECT_CALL(*mock_device_ptr_, DoAllocateAndStart(_, _))
- .WillOnce(Invoke(
- [](const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client>* client) {
- (*client)->OnStarted();
- }));
- EXPECT_CALL(*mock_video_frame_handler_, OnStarted())
- .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
- const media::VideoCaptureParams kArbitrarySettings;
- adapter_->Start(kArbitrarySettings, std::move(video_frame_handler_));
- run_loop.Run();
- }
- {
- base::RunLoop run_loop;
- EXPECT_CALL(*mock_device_ptr_, DoStopAndDeAllocate())
- .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
- mock_video_frame_handler_.reset();
- run_loop.Run();
- }
- }
- // Triggers a condition that caused a use-after-free reported in
- // https://crbug.com/807887. The use-after-free happened because the connection
- // lost event handler got invoked on a base::Unretained() pointer to |adapter_|
- // after |adapter_| was released.
- TEST_F(DeviceMediaToMojoAdapterTest,
- ReleaseInstanceSynchronouslyAfterReceiverClosedConnection) {
- {
- base::RunLoop run_loop;
- EXPECT_CALL(*mock_device_ptr_, DoAllocateAndStart(_, _))
- .WillOnce(Invoke(
- [](const media::VideoCaptureParams& params,
- std::unique_ptr<media::VideoCaptureDevice::Client>* client) {
- (*client)->OnStarted();
- }));
- EXPECT_CALL(*mock_video_frame_handler_, OnStarted())
- .WillOnce(Invoke([&run_loop]() { run_loop.Quit(); }));
- const media::VideoCaptureParams kArbitrarySettings;
- adapter_->Start(kArbitrarySettings, std::move(video_frame_handler_));
- run_loop.Run();
- }
- {
- base::RunLoop run_loop;
- // This posts invocation of the error event handler to the end of the
- // current sequence.
- mock_video_frame_handler_.reset();
- // This destroys the DeviceMediaToMojoAdapter, which in turn posts a
- // DeleteSoon in ~ReceiverOnTaskRunner() to the end of the current sequence.
- adapter_.reset();
- // Give error handle chance to get invoked
- run_loop.RunUntilIdle();
- }
- }
- } // namespace video_capture
|