chromium/chrome/browser/media/webrtc/display_media_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.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/browser/media/webrtc/display_media_access_handler.h"

#include <memory>
#include <string>
#include <utility>

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/mock_callback.h"
#include "build/build_config.h"
#include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/media_stream_request.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/navigation_simulator.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"
#endif  // BUILDFLAG(IS_CHROMEOS)

#if !BUILDFLAG(IS_ANDROID)
#include "base/test/gmock_expected_support.h"
#include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
#include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#endif  // !BUILDFLAG(IS_ANDROID)

class DisplayMediaAccessHandlerTest : public ChromeRenderViewHostTestHarness {};

TEST_F(DisplayMediaAccessHandlerTest, PermissionGiven) {}

#if BUILDFLAG(IS_MAC)
TEST_F(DisplayMediaAccessHandlerTest, WindowPermissionGiven) {
  blink::mojom::MediaStreamRequestResult result;
  blink::mojom::StreamDevices devices;
  content::DesktopMediaID desktop_media_id(content::DesktopMediaID::TYPE_WINDOW,
                                           content::DesktopMediaID::kFakeId);

  // Requests with a window_id will skip macOS screen share permission checks.
  desktop_media_id.window_id = content::DesktopMediaID::kFakeId;
  ProcessRequest(desktop_media_id, &result, devices, false /* request_audio */);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
  EXPECT_EQ(1u, blink::CountDevices(devices));
  EXPECT_EQ(blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE,
            devices.video_device.value().type);
  EXPECT_TRUE(devices.video_device.value().display_media_info);
}
#endif  // BUILDFLAG(IS_MAC)

TEST_F(DisplayMediaAccessHandlerTest, PermissionGivenToRequestWithAudio) {}

TEST_F(DisplayMediaAccessHandlerTest, PermissionDenied) {}

#if BUILDFLAG(IS_CHROMEOS)
TEST_F(DisplayMediaAccessHandlerTest, DlpRestricted) {
  const content::DesktopMediaID media_id(content::DesktopMediaID::TYPE_SCREEN,
                                         content::DesktopMediaID::kFakeId);

  // Setup Data Leak Prevention restriction.
  policy::MockDlpContentManager mock_dlp_content_manager;
  policy::ScopedDlpContentObserverForTesting scoped_dlp_content_observer(
      &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);
      });

  blink::mojom::MediaStreamRequestResult result =
      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
  blink::mojom::StreamDevices devices;
  ProcessRequest(media_id, &result, devices, /*request_audio=*/false);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, result);
  EXPECT_EQ(0u, blink::CountDevices(devices));
}

TEST_F(DisplayMediaAccessHandlerTest, DlpNotRestricted) {
  const content::DesktopMediaID media_id(content::DesktopMediaID::TYPE_SCREEN,
                                         content::DesktopMediaID::kFakeId);

  // 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);
      });

  blink::mojom::MediaStreamRequestResult result =
      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
  blink::mojom::StreamDevices devices;
  ProcessRequest(media_id, &result, devices, /*request_audio=*/false);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result);
  EXPECT_EQ(1u, blink::CountDevices(devices));
}

TEST_F(DisplayMediaAccessHandlerTest, DlpWebContentsDestroyed) {
  const content::DesktopMediaID media_id(content::DesktopMediaID::TYPE_SCREEN,
                                         content::DesktopMediaID::kFakeId);

  // 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) {
        DeleteContents();
        std::move(callback).Run(/*should_proceed=*/true);
      });

  blink::mojom::MediaStreamRequestResult result =
      blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED;
  blink::mojom::StreamDevices devices;
  ProcessRequest(media_id, &result, devices, /*request_audio=*/false,
                 /*expect_result=*/false);

  EXPECT_EQ(blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, result);
  EXPECT_EQ(0u, blink::CountDevices(devices));
}
#endif  // BUILDFLAG(IS_CHROMEOS)

TEST_F(DisplayMediaAccessHandlerTest, UpdateMediaRequestStateWithClosing) {}

TEST_F(DisplayMediaAccessHandlerTest, CorrectHostAsksForPermissions) {}

TEST_F(DisplayMediaAccessHandlerTest, CorrectHostAsksForPermissionsNormalURLs) {}

#if !BUILDFLAG(IS_ANDROID)

TEST_F(DisplayMediaAccessHandlerTest, IsolatedWebAppNameAsksForPermissions) {}
#endif  // !BUILDFLAG(IS_ANDROID)

TEST_F(DisplayMediaAccessHandlerTest, WebContentsDestroyed) {}

TEST_F(DisplayMediaAccessHandlerTest, MultipleRequests) {}

TEST_F(DisplayMediaAccessHandlerTest,
       ChangeSourceWithoutAudioRequestPermissionGiven) {}

TEST_F(DisplayMediaAccessHandlerTest,
       ChangeSourceWithAudioRequestPermissionGiven) {}

#if BUILDFLAG(IS_CHROMEOS)
TEST_F(DisplayMediaAccessHandlerTest, ChangeSourceDlpRestricted) {
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId, GetWebContentsMediaCaptureId());

  // Setup Data Leak Prevention restriction.
  policy::MockDlpContentManager mock_dlp_content_manager;
  policy::ScopedDlpContentObserverForTesting scoped_dlp_content_observer(
      &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);
      });

  ChangeSourceRequestTest(
      /*with_audio=*/false,
      /*expected_result=*/
      blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
      /*expected_number_of_devices=*/0u);
}

TEST_F(DisplayMediaAccessHandlerTest, ChangeSourceDlpNotRestricted) {
  const content::DesktopMediaID media_id(
      content::DesktopMediaID::TYPE_WEB_CONTENTS,
      content::DesktopMediaID::kNullId, GetWebContentsMediaCaptureId());

  // 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);
      });

  ChangeSourceRequestTest(
      /*with_audio=*/false,
      /*expected_result=*/
      blink::mojom::MediaStreamRequestResult::OK,
      /*expected_number_of_devices=*/1u);
}
#endif  // BUILDFLAG(IS_CHROMEOS)

TEST_F(DisplayMediaAccessHandlerTest, ChangeSourceWithPendingPickerRequest) {}

TEST_F(DisplayMediaAccessHandlerTest,
       ChangeSourcePolicyViolationWithPendingPickerRequest) {}

TEST_F(DisplayMediaAccessHandlerTest,
       MalformedChangeSourceBetweenPickerRequests) {}

class DisplayMediaAccessHandlerTestWithSelfBrowserSurface
    : public DisplayMediaAccessHandlerTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(DisplayMediaAccessHandlerTestWithSelfBrowserSurface,
       CheckIsWebContentsExcluded) {}

class DisplayMediaAccessHandlerTestWithMonitorTypeSurfaces
    : public DisplayMediaAccessHandlerTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(DisplayMediaAccessHandlerTestWithMonitorTypeSurfaces,
       CheckMonitorTypeSurfacesAreExcluded) {}