#include "chrome/browser/media/webrtc/desktop_capture_access_handler.h"
#include <memory>
#include <string>
#include <utility>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.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-shared.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/chromeos/policy/dlp/test/mock_dlp_content_manager.h"
#include "ui/aura/window.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/test/scoped_feature_list.h"
#include "chrome/common/chrome_features.h"
#endif
constexpr char kOrigin[] = …;
constexpr char kComponentExtension[] = …;
class DesktopCaptureAccessHandlerTest : public ChromeRenderViewHostTestHarness { … };
TEST_F(DesktopCaptureAccessHandlerTest,
ChangeSourceWithoutAudioRequestPermissionGiven) { … }
TEST_F(DesktopCaptureAccessHandlerTest,
ChangeSourceWithAudioRequestPermissionGiven) { … }
TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourcePermissionDenied) { … }
TEST_F(DesktopCaptureAccessHandlerTest,
ChangeSourceUpdateMediaRequestStateWithClosing) { … }
TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceWebContentsDestroyed) { … }
TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceMultipleRequests) { … }
TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamSuccess) { … }
TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessSuccess) { … }
#if BUILDFLAG(IS_CHROMEOS)
TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.WillOnce([&](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(false);
});
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUserMediaScreenCapturing);
extensions::ExtensionBuilder extensionBuilder(kComponentExtension);
extensionBuilder.SetLocation(extensions::mojom::ManifestLocation::kComponent);
std::unique_ptr<aura::Window> primary_root_window =
std::make_unique<aura::Window>(nullptr);
primary_root_window->Init(ui::LAYER_NOT_DRAWN);
SetPrimaryRootWindow(primary_root_window.get());
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices devices;
ProcessGenerateStreamRequest({}, GURL(kOrigin),
extensionBuilder.Build().get(), &result,
&devices);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
EXPECT_FALSE(devices.video_device.has_value());
}
TEST_F(DesktopCaptureAccessHandlerTest, ScreenCaptureAccessDlpNotRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.WillOnce([&](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(true);
});
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUserMediaScreenCapturing);
extensions::ExtensionBuilder extensionBuilder(kComponentExtension);
extensionBuilder.SetLocation(extensions::mojom::ManifestLocation::kComponent);
std::unique_ptr<aura::Window> primary_root_window =
std::make_unique<aura::Window>(nullptr);
primary_root_window->Init(ui::LAYER_NOT_DRAWN);
SetPrimaryRootWindow(primary_root_window.get());
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices devices;
ProcessGenerateStreamRequest({}, GURL(kOrigin),
extensionBuilder.Build().get(), &result,
&devices);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
EXPECT_TRUE(devices.video_device.has_value());
}
TEST_F(DesktopCaptureAccessHandlerTest,
ScreenCaptureAccessDlpWebContentsDestroyed) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.Times(1)
.WillOnce([&](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
DeleteContents();
std::move(callback).Run(false);
});
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUserMediaScreenCapturing);
extensions::ExtensionBuilder extensionBuilder(kComponentExtension);
extensionBuilder.SetLocation(extensions::mojom::ManifestLocation::kComponent);
std::unique_ptr<aura::Window> primary_root_window =
std::make_unique<aura::Window>(nullptr);
primary_root_window->Init(ui::LAYER_NOT_DRAWN);
SetPrimaryRootWindow(primary_root_window.get());
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices devices;
ProcessGenerateStreamRequest({}, GURL(kOrigin),
extensionBuilder.Build().get(), &result,
&devices, false);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, result);
EXPECT_FALSE(devices.video_device.has_value());
}
TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.Times(1)
.WillOnce([](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(false);
});
const std::string id =
content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID(),
web_contents()->GetPrimaryMainFrame()->GetRoutingID(),
url::Origin::Create(GURL(kOrigin)),
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
content::DesktopMediaID::kFakeId),
content::DesktopStreamRegistryType::kRegistryStreamTypeDesktop);
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices devices;
ProcessGenerateStreamRequest({id}, GURL(kOrigin), nullptr,
&result, &devices);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
EXPECT_FALSE(devices.video_device.has_value());
}
TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpNotRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.Times(1)
.WillOnce([](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(true);
});
const std::string id =
content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID(),
web_contents()->GetPrimaryMainFrame()->GetRoutingID(),
url::Origin::Create(GURL(kOrigin)),
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
content::DesktopMediaID::kFakeId),
content::DesktopStreamRegistryType::kRegistryStreamTypeDesktop);
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices devices;
ProcessGenerateStreamRequest({id}, GURL(kOrigin), nullptr,
&result, &devices);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
EXPECT_TRUE(devices.video_device.has_value());
}
TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.Times(1)
.WillOnce([](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(false);
});
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices stream_devices;
ProcessDeviceUpdateRequest(
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
content::DesktopMediaID::kFakeId),
&result, &stream_devices, blink::MEDIA_DEVICE_UPDATE,
false);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
EXPECT_EQ(0u, blink::CountDevices(stream_devices));
}
TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpNotRestricted) {
policy::MockDlpContentManager mock_dlp_content_manager;
policy::ScopedDlpContentObserverForTesting scoped_dlp_content_manager(
&mock_dlp_content_manager);
EXPECT_CALL(mock_dlp_content_manager, CheckScreenShareRestriction)
.Times(1)
.WillOnce([](const content::DesktopMediaID& media_id,
const std::u16string& application_title,
base::OnceCallback<void(bool)> callback) {
std::move(callback).Run(true);
});
blink::mojom::MediaStreamRequestResult result =
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
blink::mojom::StreamDevices stream_devices;
ProcessDeviceUpdateRequest(
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
content::DesktopMediaID::kFakeId),
&result, &stream_devices, blink::MEDIA_DEVICE_UPDATE,
false);
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
EXPECT_EQ(1u, blink::CountDevices(stream_devices));
}
#endif