chromium/chrome/browser/media/webrtc/desktop_capture_access_handler_unittest.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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  // BUILDFLAG(IS_CHROMEOS)

#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) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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>(/*delegate=*/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(/*requested_video_device_ids=*/{}, 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) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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>(/*delegate=*/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(/*requested_video_device_id=*/{}, 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) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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>(/*delegate=*/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(/*requested_video_device_id=*/{}, GURL(kOrigin),
                               extensionBuilder.Build().get(), &result,
                               &devices, /*expect_result=*/false);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, result);
  EXPECT_FALSE(devices.video_device.has_value());
}

TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpRestricted) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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), /*extension=*/nullptr,
                               &result, &devices);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
  EXPECT_FALSE(devices.video_device.has_value());
}

TEST_F(DesktopCaptureAccessHandlerTest, GenerateStreamDlpNotRestricted) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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), /*extension=*/nullptr,
                               &result, &devices);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
  EXPECT_TRUE(devices.video_device.has_value());
}

TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpRestricted) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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,
      /*request audio=*/false);
  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
  EXPECT_EQ(0u, blink::CountDevices(stream_devices));
}

TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceDlpNotRestricted) {
  // Setup Data Leak Prevention restriction.
  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(/*should_proceed=*/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,
      /*request audio=*/false);
  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
  EXPECT_EQ(1u, blink::CountDevices(stream_devices));
}
#endif  // BUILDFLAG(IS_CHROMEOS)