blob: 6baf2598ea4866fe7c36c041786d4689d4965206 [file] [log] [blame]
// Copyright (c) 2012 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 "third_party/blink/renderer/modules/mediastream/media_stream_device_observer.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h"
#include "third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h"
namespace blink {
class MediaStreamDeviceObserverTest : public ::testing::Test {
public:
MediaStreamDeviceObserverTest()
: observer_(std::make_unique<MediaStreamDeviceObserver>(nullptr)) {}
void OnDeviceOpened(base::OnceClosure quit_closure,
bool success,
const String& label,
const blink::MediaStreamDevice& device) {
if (success) {
stream_label_ = label;
current_device_ = device;
observer_->AddStream(label, device);
}
std::move(quit_closure).Run();
}
protected:
String stream_label_;
MockMojoMediaStreamDispatcherHost mock_dispatcher_host_;
std::unique_ptr<MediaStreamDeviceObserver> observer_;
blink::MediaStreamDevice current_device_;
};
TEST_F(MediaStreamDeviceObserverTest, GetNonScreenCaptureDevices) {
const int kRequestId1 = 5;
const int kRequestId2 = 7;
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
// OpenDevice request 1
base::RunLoop run_loop1;
mock_dispatcher_host_.OpenDevice(
kRequestId1, "device_path",
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop1.QuitClosure()));
run_loop1.Run();
String stream_label1 = stream_label_;
// OpenDevice request 2
base::RunLoop run_loop2;
mock_dispatcher_host_.OpenDevice(
kRequestId2, "screen_capture",
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop2.QuitClosure()));
run_loop2.Run();
String stream_label2 = stream_label_;
EXPECT_EQ(observer_->label_stream_map_.size(), 2u);
// Only the device with type
// blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE will be returned.
blink::MediaStreamDevices video_devices =
observer_->GetNonScreenCaptureDevices();
EXPECT_EQ(video_devices.size(), 1u);
EXPECT_EQ(video_devices[0].type,
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
// Close the device from request 2.
observer_->RemoveStream(stream_label2);
EXPECT_TRUE(observer_->GetVideoSessionId(stream_label2).is_empty());
// Close the device from request 1.
observer_->RemoveStream(stream_label1);
EXPECT_TRUE(observer_->GetVideoSessionId(stream_label1).is_empty());
// Verify that the request have been completed.
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
}
TEST_F(MediaStreamDeviceObserverTest, OnDeviceStopped) {
const int kRequestId = 5;
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
// OpenDevice request.
base::RunLoop run_loop1;
mock_dispatcher_host_.OpenDevice(
kRequestId, "device_path",
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop1.QuitClosure()));
run_loop1.Run();
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
observer_->OnDeviceStopped(stream_label_, current_device_);
// Verify that the request have been completed.
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
}
TEST_F(MediaStreamDeviceObserverTest, OnDeviceChanged) {
const int kRequestId1 = 5;
const base::UnguessableToken kSessionId = base::UnguessableToken::Create();
const String example_video_id1 = "fake_video_device1";
const String example_video_id2 = "fake_video_device2";
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
// OpenDevice request.
base::RunLoop run_loop1;
mock_dispatcher_host_.OpenDevice(
kRequestId1, example_video_id1,
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop1.QuitClosure()));
run_loop1.Run();
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
blink::MediaStreamDevices video_devices =
observer_->GetNonScreenCaptureDevices();
EXPECT_EQ(video_devices.size(), 1u);
EXPECT_EQ(video_devices[0].id, example_video_id1.Utf8());
// OnDeviceChange request.
blink::MediaStreamDevice fake_video_device(
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
example_video_id2.Utf8(), "Fake Video Device");
fake_video_device.set_session_id(kSessionId);
observer_->OnDeviceChanged(stream_label_, current_device_, fake_video_device);
// Verify that the device has been changed to the new |fake_video_device|.
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
video_devices = observer_->GetNonScreenCaptureDevices();
EXPECT_EQ(video_devices.size(), 1u);
EXPECT_EQ(video_devices[0].id, example_video_id2.Utf8());
EXPECT_EQ(video_devices[0].session_id(), kSessionId);
// Close the device from request.
observer_->RemoveStream(stream_label_);
EXPECT_TRUE(observer_->GetVideoSessionId(stream_label_).is_empty());
// Verify that the request have been completed.
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
}
TEST_F(MediaStreamDeviceObserverTest, OnDeviceChangedChangesDeviceAfterRebind) {
const String kStreamLabel = "stream_label";
const std::string kDeviceName = "Video Device";
const blink::mojom::MediaStreamType kDeviceType =
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE;
// Add a device to the |observer_|, to be changed using OnChangedDevice().
blink::MediaStreamDevice initial_device(kDeviceType, "initial_device",
kDeviceName);
observer_->AddStream(kStreamLabel, initial_device);
// Call the |observer_|'s bind callback and check that its internal
// |receiver_| is bound.
mojo::Remote<mojom::blink::MediaStreamDeviceObserver> remote_observer;
EXPECT_FALSE(observer_->receiver_.is_bound());
observer_->BindMediaStreamDeviceObserverReceiver(
remote_observer.BindNewPipeAndPassReceiver());
EXPECT_TRUE(observer_->receiver_.is_bound());
// Send an OnDeviceChanged() message using the remote mojo pipe, and verify
// that the device is changed.
blink::MediaStreamDevice changed_device =
blink::MediaStreamDevice(kDeviceType, "video_device-123", kDeviceName);
remote_observer->OnDeviceChanged(kStreamLabel, initial_device,
changed_device);
base::RunLoop().RunUntilIdle();
blink::MediaStreamDevices video_devices =
observer_->GetNonScreenCaptureDevices();
ASSERT_EQ(video_devices.size(), 1u);
EXPECT_EQ(video_devices[0].id, "video_device-123");
// Reset the remote end of the mojo pipe, then rebind it, and verify that
// OnDeviceChanged() changes the device after rebind.
remote_observer.reset();
observer_->BindMediaStreamDeviceObserverReceiver(
remote_observer.BindNewPipeAndPassReceiver());
remote_observer->OnDeviceChanged(
kStreamLabel, changed_device,
blink::MediaStreamDevice(kDeviceType, "video_device-456", kDeviceName));
base::RunLoop().RunUntilIdle();
video_devices = observer_->GetNonScreenCaptureDevices();
ASSERT_EQ(video_devices.size(), 1u);
EXPECT_EQ(video_devices[0].id, "video_device-456");
}
TEST_F(MediaStreamDeviceObserverTest, OnDeviceRequestStateChange) {
const int kRequestId = 5;
EXPECT_EQ(observer_->label_stream_map_.size(), 0u);
// OpenDevice request.
base::RunLoop run_loop1;
mock_dispatcher_host_.OpenDevice(
kRequestId, "device_path",
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
base::BindOnce(&MediaStreamDeviceObserverTest::OnDeviceOpened,
base::Unretained(this), run_loop1.QuitClosure()));
run_loop1.Run();
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
observer_->OnDeviceRequestStateChange(
stream_label_, current_device_,
mojom::blink::MediaStreamStateChange::PAUSE);
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
observer_->OnDeviceRequestStateChange(
stream_label_, current_device_,
mojom::blink::MediaStreamStateChange::PLAY);
EXPECT_EQ(observer_->label_stream_map_.size(), 1u);
}
} // namespace blink