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

// Copyright 2021 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 <memory>
#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/permissions/permission_request_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_base.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/prerender_test_util.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "third_party/blink/public/common/features.h"
#include "ui/gl/gl_switches.h"

// TODO(crbug.com/40184242): Enable this test suite on Lacros.
#if !BUILDFLAG(IS_CHROMEOS_LACROS)

namespace {

WebContents;
SubCaptureTargetType;
Bool;
Combine;
TestParamInfo;
Values;
WithParamInterface;

// Comparisons with sub-capture targets (CropTargets/RestrictionTargets) are
// limited. We can only know that a one was returned by the test. However, we
// keep this matcher around in anticipation of targets being made either
// comparable or stringifiable. Then we can do more interesting comparisons,
// like ensuring uniqueness or checking that repeatedly calling
// CropTarget.fromElement() or RestrictionTarget.fromElement() on the same
// Element yields either the same target, or an equivalent one.
MATCHER_P(IsExpectedTarget, expected_target_index, "") {}

const char kMainPageTitle[] =;
const char kOtherPageTitle[] =;

// Tracks SubCaptureTargetIdWebContentsHelper::kMaxIdsPerWebContents.
constexpr size_t kMaxIdsPerWebContents =;

enum {};

enum Tab {};

enum class Frame {};

enum class Track {};

const char* ToString(Frame frame) {}

const char* ToString(Track track) {}

const char* ToString(SubCaptureTargetType type) {}

// Conveniently pack together all relevant information about a tab and
// conveniently expose test controls on it.
struct TabInfo {};

}  // namespace

// Essentially depends on InProcessBrowserTest, but WebRtcTestBase provides
// detection of JS errors.
class SubCaptureBrowserTestBase : public WebRtcTestBase {};

// Test that cropTo() and restrictTo() work on some expected element types.
class SubCaptureBrowserTargetElementTest
    : public SubCaptureBrowserTestBase,
      public WithParamInterface<std::tuple<SubCaptureTargetType, const char*>> {};

std::string SubCaptureBrowserTargetElementTestParamsToString(
    const TestParamInfo<SubCaptureBrowserTargetElementTest::ParamType>& info) {}

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTargetElementTest, ApplyToElement) {}

class SubCaptureBrowserTest : public SubCaptureBrowserTestBase,
                              public WithParamInterface<SubCaptureTargetType> {};

std::string SubCaptureBrowserTestParamsToString(
    const TestParamInfo<SubCaptureBrowserTest::ParamType>& info) {}

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest,
                       FromElementReturnsValidIdInMainPage) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest,
                       FromElementReturnsValidIdInCrossOriginIframe) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest,
                       SubCaptureAllowedIfTopLevelAppliesToElementInTopLevel) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest,
                       SubCaptureAllowedIfTopLevelAppliesToElementInEmbedded) {}

IN_PROC_BROWSER_TEST_P(
    SubCaptureBrowserTest,
    SubCaptureAllowedIfEmbeddedFrameAppliesToElementInTopLevel) {}

IN_PROC_BROWSER_TEST_P(
    SubCaptureBrowserTest,
    SubCaptureAllowedIfEmbeddedFrameAppliesToElementInEmbedded) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest, SubCaptureAllowedToUndo) {}

IN_PROC_BROWSER_TEST_P(
    SubCaptureBrowserTest,
    MayAttemptToUndoSubCaptureOnTracksWhereSubCaptureHasNotBeenApplied) {}

// The Promise resolves when it's guaranteed that no additional frames will be
// issued with an earlier sub-capture-target version. That an actual frame be
// issued at all, let alone with the new sub-capture-target version, is not
// actually required, or else these promises could languish unfulfilled
// indefinitely.
IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest,
                       SubCaptureOfInvisibleElementResolvesInTimelyFashion) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest, MaxIdsInTopLevelDocument) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest, MaxIdsInEmbeddedFrame) {}

IN_PROC_BROWSER_TEST_P(SubCaptureBrowserTest, MaxIdsSharedBetweenFramesInTab) {}

// Tests related to behavior when cloning.
class SubCaptureClonesBrowserTestBase : public SubCaptureBrowserTestBase {};

class SubCaptureClonesBrowserTest
    : public SubCaptureClonesBrowserTestBase,
      public WithParamInterface<SubCaptureTargetType> {};

std::string SubCaptureClonesBrowserTestParamsToString(
    const TestParamInfo<SubCaptureClonesBrowserTest::ParamType>& info) {}

INSTANTIATE_TEST_SUITE_P();

// Sanity cloning 1/2.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CanCloneTracksWhichHadNoSubCaptureApplied) {}

// Sanity cloning 2/2.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CanCloneTrackWhichHaveSubCaptureApplied) {}

// Restrictions on cloned tracks 1/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotApplySubCaptureOnClones) {}

// Restrictions on cloned tracks 2/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotReapplySubCaptureOnClones) {}

// Restrictions on cloned tracks 3/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotUndoSubCaptureOnClones) {}

// Restrictions on original track that has a clone 1/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotApplySubCaptureOnTracksThatHaveClones) {}

// Restrictions on original track that has a clone 2/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotReapplySubCaptureOnTracksThatHaveClones) {}

// Restrictions on original track that has a clone 3/3.
IN_PROC_BROWSER_TEST_P(SubCaptureClonesBrowserTest,
                       CannotUndoSubCaptureOnTracksThatHaveClones) {}

// Original track becomes unblocked for sub-capture after clone is GCed 1/3.
//
// TODO(crbug.com/40858400)  Re-enable for macOS and ChromeOS after flakes are
// resolved.
// TODO(crbug.com/40919381): Also flakes on linux-bfcache-rel, so turning the
// test off entirely.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanApplySubCaptureOnOriginalTrackAfterCloneIsGarbageCollected) {}

// Original track becomes unblocked for sub-capture after clone is GCed 2/3.
//
// TODO(crbug.com/40858400) Re-enable after flakes are resolved.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanReapplySubCaptureOnOriginalTrackAfterCloneIsGarbageCollected) {}

// Original track becomes unblocked for sub-capture clone is GCed 3/3.
//
// TODO(crbug.com/40860614): Re-enable this test.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanUndoSubCaptureOnOriginalTrackAfterCloneIsGarbageCollected) {}

// Cloned track becomes unblocked for sub-capture after original is GCed 1/3.
//
// The following test is disabled because of a loosely-related issue,
// where an original track is kept alive if a clone exists, but not vice versa.
// TODO(crbug.com/40845775): Uncomment after fixing the aforementioned issue.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanApplySubCaptureOnCloneAfterOriginalTrackIsGarbageCollected) {}

// Cloned track becomes unblocked for sub-capture after original is GCed 2/3.
//
// The following test is disabled because of a loosely-related issue,
// where an original track is kept alive if a clone exists, but not vice versa.
// TODO(crbug.com/40845775): Uncomment after fixing the aforementioned issue.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanReapplySubCaptureOnCloneAfterOriginalTrackIsGarbageCollected) {}

// Cloned track becomes unblocked for sub-capture after original is GCed 3/3.
//
// The following test is disabled because of a loosely-related issue,
// where an original track is kept alive if a clone exists, but not vice versa.
// TODO(crbug.com/40845775): Uncomment after fixing the aforementioned issue.
IN_PROC_BROWSER_TEST_P(
    SubCaptureClonesBrowserTest,
    DISABLED_CanUndoSubCaptureOnCloneAfterOriginalTrackIsGarbageCollected) {}

// Tests similar issues to cloning, but with multiple captures triggering
// these issues instead.
class SubCaptureMultiCaptureBrowserTest
    : public SubCaptureClonesBrowserTestBase,
      public WithParamInterface<std::tuple<SubCaptureTargetType, Frame>> {};

std::string SubCaptureMultiCaptureBrowserTestParamsToString(
    const TestParamInfo<SubCaptureMultiCaptureBrowserTest::ParamType>& info) {}

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SubCaptureMultiCaptureBrowserTest,
                       CanSelfCaptureAgainIfNeverAppliedSubCapture) {}

IN_PROC_BROWSER_TEST_P(SubCaptureMultiCaptureBrowserTest,
                       CannotSelfCaptureAgainIfAppliedSubCapture) {}

IN_PROC_BROWSER_TEST_P(SubCaptureMultiCaptureBrowserTest,
                       CannotSelfCaptureAgainIfSubCapturedAppliedAndUnapplied) {}

IN_PROC_BROWSER_TEST_P(SubCaptureMultiCaptureBrowserTest,
                       CanSelfCaptureAgainIfSubCaptureSessionStopped) {}

IN_PROC_BROWSER_TEST_P(
    SubCaptureMultiCaptureBrowserTest,
    CannotApplySubCaptureIfMultipleSelfCaptureSessionsExist) {}

// Suite of tests ensuring that only self-capture sessions may be the target of
// sub-capture, and that the app may only apply sub-capture using targets in its
// own tab. (However, any target in the current tab is permitted.)
class SubCaptureSelfCaptureOnlyBrowserTest
    : public SubCaptureBrowserTestBase,
      public WithParamInterface<
          std::tuple<SubCaptureTargetType, Frame, bool, Tab, Frame>> {};

std::string SubCaptureSelfCaptureOnlyBrowserTestParamsToString(
    const TestParamInfo<SubCaptureSelfCaptureOnlyBrowserTest::ParamType>&
        info) {}

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SubCaptureSelfCaptureOnlyBrowserTest, ApplySubCapture) {}

#endif  //  !BUILDFLAG(IS_CHROMEOS_LACROS)