chromium/content/browser/fenced_frame/fenced_frame_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.

#include "content/browser/fenced_frame/fenced_frame.h"

#include <memory>
#include <string>
#include <tuple>

#include "base/containers/contains.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/attribution_reporting/attribution_os_level_manager.h"
#include "content/browser/attribution_reporting/attribution_test_utils.h"
#include "content/browser/attribution_reporting/test/mock_content_browser_client.h"
#include "content/browser/back_forward_cache_browsertest.h"
#include "content/browser/fenced_frame/fenced_frame_reporter.h"
#include "content/browser/preloading/prefetch/prefetch_service.h"
#include "content/browser/private_aggregation/private_aggregation_manager.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_entry_restore_context_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/frame_type.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/mock_web_contents_observer.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/resource_load_observer.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_monitor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/fenced_frame_test_utils.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/features.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/connection_tracker.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest-spi.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
#include "third_party/blink/public/mojom/fenced_frame/fenced_frame.mojom.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {

namespace {

cors;

constexpr char kAddIframeScript[] =;

constexpr char kReportingURL[] =;

GURL GenerateAndVerifyPendingMappedURN(
    FencedFrameURLMapping* fenced_frame_url_mapping) {}

}  // namespace

class FencedFrameBrowserTestBase : public ContentBrowserTest {};

class FencedFrameMPArchBrowserTest : public FencedFrameBrowserTestBase {};

// This is a test class for tests that need to use IsolateAllSiteForTesting()
// and that will be testing process assignments. It is important that
// IsolateAllSiteForTesting is enabled early in these cases, otherwise the
// tests can end up with a main frame where
// AreOriginKeyedProcessesEnabledByDefault() was false when the main frame was
// created (and this is stored in the main frame's BrowsingInstance), and then
// AreOriginKeyedProcessesEnabledByDefault() later returns true due to
// IsolateAllSiteForTesting() turning on site-per-process. This sequence can
// lead to inconsistent SiteInfo settings.
class FencedFrameMPArchBrowserTest_IsolateAllSites
    : public FencedFrameMPArchBrowserTest {};

// Tests that the renderer can create a <fencedframe> that results in a
// browser-side content::FencedFrame also being created.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       CreateFromScriptAndDestroy) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, CreateFromParser) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, Navigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, AboutBlankNavigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       SettingNullConfigNavigatesToAboutBlank) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, FrameIteration) {}

namespace {

// Intercepts calls to RenderFramHostImpl's CreateFencedFrame mojo method, and
// connects a NavigationDelayer which delays the FencedFrameOwnerHost's
// Navigate mojo method.
class NavigationDelayerInterceptor
    : public blink::mojom::LocalFrameHostInterceptorForTesting {};

}  // namespace

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, NavigationStartTime) {}

// Test that ensures we can post from an cross origin iframe into the
// fenced frame root.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, CrossOriginMessagePost) {}

// Test that when the documents inside fenced frame tree are loading,
// WebContentsObserver::DocumentOnLoadCompletedInPrimaryMainFrame is not invoked
// for fenced frames as it is only invoked for primary main frames.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       DocumentOnLoadCompletedInPrimaryMainFrame) {}

// Test that when the documents inside the fenced frame tree are loading,
// WebContentsObserver::PrimaryMainDocumentElementAvailable is not invoked for
// fenced frames as it is only invoked for primary main frames.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       PrimaryMainDocumentElementAvailable) {}

// Test that a fenced-frame does not perform any of the Android main-frame
// viewport behaviors like zoom-out-to-fit-content or parsing the viewport
// <meta>.
// Flaky on Mac https://crbug.com/1349900
#if BUILDFLAG(IS_MAC)
#define MAYBE_ViewportSettings
#else
#define MAYBE_ViewportSettings
#endif
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, MAYBE_ViewportSettings) {}

// Test that fenced frames use the primary main frame's UKM source id during
// navigation.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, GetPageUkmSourceId) {}

// Test that iframes that nested within fenced frames use the primary main
// frame's UKM source id during navigation.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       GetPageUkmSourceId_NestedFrame) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       DocumentUKMSourceIdShouldNotBeAssociatedWithURL) {}

// Test that FrameTree::CollectNodesForIsLoading doesn't include inner
// WebContents nodes.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, NodesForIsLoading) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       NoErrorPageOnEmptyFrameHttpError) {}

// Test that when the documents inside the fenced frame tree are loading, then
// `WebContents::IsLoading`, `FrameTree::IsLoadingIncludingInnerFrameTrees`, and
// `FrameTreeNode::IsLoading` should return true. Primary
// `FrameTree::IsLoadingIncludingInnerFrameTrees` value should reflect the
// loading state of descendant fenced frames.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, IsLoading) {}

// Test that when the documents inside the fenced frame tree are loading,
// WebContentsObserver::DidStartLoading is fired and when document stops loading
// WebContentsObserver::DidStopLoading is fired. In this test primary page
// completed loading before fenced frame starts loading and we test the loading
// state in the end when both primary page and fenced frame completed loading.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       DidStartAndDidStopLoading) {}

// Ensure that WebContentsObserver::LoadProgressChanged is not invoked when
// there is a change in load state of fenced frame as LoadProgressChanged is
// attributed to only primary main frame load progress change.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, LoadProgressChanged) {}

// Tests that NavigationHandle::GetNavigatingFrameType() returns the correct
// type.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       NavigationHandleFrameType) {}

// Tests that an unload/beforeunload event handler won't be set from
// fenced frames.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, UnloadHandler) {}

// Tests that an input event targeted to a fenced frame correctly
// triggers a user interaction notification for WebContentsObservers.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       UserInteractionForFencedFrame) {}

// Test that WebContents::GetFocusedFrame includes results from a fenced
// frame's frame tree.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       FocusedFrameInFencedFrame) {}

// Test that the initial navigation in a fenced frame, which navigates from the
// initial empty document, is not classified as a client redirect.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       InitialNavigationIsNotClientRedirect) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest_IsolateAllSites,
                       ProcessAllocationWithFullSiteIsolation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest_IsolateAllSites,
                       CrossSiteFencedFramesShareProcess) {}

// Tests to ensure that the owner forced sandbox flags are set when a fenced
// frame is created, and are kept after the fenced frame is navigated
// to a page with a CSP sandbox header.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       EnsureSandboxFlagsEnforced) {}

IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       CreateFencedFrameWhileInBackForwardCache) {}

// Verify preload from a link element works in fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, LinkPreload) {}

// Verify preload from a link element is disabled after fenced frame network
// cutoff.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       NetworkCutoffDisablesLinkPreload) {}

// Verify module preload from a link element works in fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest, LinkModulePreload) {}

// Verify module preload from a link element is disabled after fenced frame
// network cutoff.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       NetworkCutoffDisablesLinkModulePreload) {}

// Verify script speculationrules prefetch is not started in fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameMPArchBrowserTest,
                       ScriptSpeculationRulesPrefetchNotStarted) {}

class FencedFrameWithSiteIsolationDisabledBrowserTest
    : public FencedFrameMPArchBrowserTest,
      public testing::WithParamInterface<std::tuple<bool, bool>> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(FencedFrameWithSiteIsolationDisabledBrowserTest,
                       ProcessAllocationWithSiteIsolationDisabled) {}

IN_PROC_BROWSER_TEST_P(FencedFrameWithSiteIsolationDisabledBrowserTest,
                       ProcessAllocationWithDynamicIsolatedOrigin) {}

IN_PROC_BROWSER_TEST_P(FencedFrameWithSiteIsolationDisabledBrowserTest,
                       ProcessAllocationWhenRootIsIsolated) {}

IN_PROC_BROWSER_TEST_P(FencedFrameWithSiteIsolationDisabledBrowserTest,
                       ProcessAllocationForNestedFencedFrame) {}

IN_PROC_BROWSER_TEST_P(FencedFrameWithSiteIsolationDisabledBrowserTest,
                       ProcessAllocationForFencedFrameInIsolatedPopup) {}

class FencedFrameIsolatedSandboxedIframesBrowserTest
    : public FencedFrameMPArchBrowserTest_IsolateAllSites,
      public ::testing::WithParamInterface<bool> {};

// This is a basic test to make sure the kIsolateSandboxedIframes (OOPSIF) load
// properly with FencedFrames, both when FencedFrames isolation mode is off and
// on. The OOPSIF frame is sandboxed due to a CSP sandbox header delivered with
// the page loaded into the FencedFrame. The FencedFrame element doesn't support
// the 'sandbox' attribute directly, nor can it be loaded inside an OOPSIF since
// OOPSIFs by definition disallow same-origin, whereas the FencedFrame element
// will only load inside a sandbox if allow-same-origin is specified on the
// sandbox. See kFencedFrameMandatoryUnsandboxedFlags.
IN_PROC_BROWSER_TEST_P(FencedFrameIsolatedSandboxedIframesBrowserTest,
                       CSP_Mainframe) {}

// Similar to CSP_Mainframe, but in this test OOPSIF doesn't isolate the fenced
// frames, while kIsolateFencedFrames does.
IN_PROC_BROWSER_TEST_P(FencedFrameIsolatedSandboxedIframesBrowserTest,
                       Non_CSP_Mainframe) {}

// A test to confirm that a FencedFrame fails to create inside a CSP sandbox
// frame without allow-same-origin. This test should fail regardless of the
// state of kIsolateSandboxedIframes or kIsolateFencedFrames.
IN_PROC_BROWSER_TEST_P(FencedFrameIsolatedSandboxedIframesBrowserTest,
                       NoFencedFramesInIsolatedSandboxedIframes) {}

class FencedFrameProcessIsolationBrowserTest
    : public FencedFrameMPArchBrowserTest {};

IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest, BasicTest) {}

// Tests that fenced frames that are same-origin with each other are put in
// the same process.
IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest,
                       SameOriginFencedFramesArePutInTheSameProcess) {}

// Tests that fenced frames that are cross-origin with each other are put in
// different processes.
IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest,
                       CrossOriginFencedFramesArePutInDifferentProcesses) {}

// Tests that a subframe inside a primary page is allocated to a separate
// process from a subframe inside a fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest,
                       SubframeIsolation) {}

// Tests process assignment in the following scenario:
// a.com
//   <fencedframe src=a.com>
//     <iframe src=a.com>
//       <fencedframe src=a.com>
IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest,
                       NestedFencedFrames) {}

// Tests that error pages inside fenced frames are process-isolated from the
// embedding page.
IN_PROC_BROWSER_TEST_F(FencedFrameProcessIsolationBrowserTest, ErrorPage) {}

namespace {

enum class FrameTypeWithOrigin {};

const std::vector<FrameTypeWithOrigin> kTestParameters[] =;

static std::string TestParamToString(
    ::testing::TestParamInfo<std::vector<FrameTypeWithOrigin>> param_info) {}

const char* kSameOriginHostName =;
const char* kCrossOriginHostName =;

const char* GetHostNameForFrameType(FrameTypeWithOrigin type) {}

bool IsFencedFrameType(FrameTypeWithOrigin type) {}

}  // namespace

class FencedFrameNestedFrameBrowserTest
    : public FencedFrameBrowserTestBase,
      public testing::WithParamInterface<std::vector<FrameTypeWithOrigin>> {};

IN_PROC_BROWSER_TEST_P(FencedFrameNestedFrameBrowserTest,
                       IsNestedWithinFencedFrame) {}

INSTANTIATE_TEST_SUITE_P();

namespace {

static std::string ModeTestParamToString(
    ::testing::TestParamInfo<
        std::tuple<blink::FencedFrame::DeprecatedFencedFrameMode,
                   blink::FencedFrame::DeprecatedFencedFrameMode>> param_info) {}

}  // namespace

class FencedFrameNestedModesTest
    : public FencedFrameBrowserTestBase,
      public testing::WithParamInterface<
          std::tuple<blink::FencedFrame::DeprecatedFencedFrameMode,
                     blink::FencedFrame::DeprecatedFencedFrameMode>> {};

// This test runs the following steps:
//   1.) Creates a "parent" fenced frame with a particular mode
//   2.) Creates a nested/child fenced frame with a particular mode
//   3.) Asserts that creation of the child fenced frame either failed or
//       succeeded depending on its mode.
IN_PROC_BROWSER_TEST_P(FencedFrameNestedModesTest, NestedModes) {}

class FledgeFencedFrameOriginContentBrowserClient
    : public ContentBrowserTestContentBrowserClient {};

INSTANTIATE_TEST_SUITE_P();

// TODO(domfarolino): Rename this.
class FencedFrameParameterizedBrowserTest : public FencedFrameBrowserTestBase {};

// Tests that the fenced frame gets navigated to an actual url given a urn:uuid.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckFencedFrameNavigationWithUUID) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       SharedStorageMetadataInNestedFencedFrame) {}

IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    TwoFencedFrameNavigationToSameSharedStorageOriginatedUUID_SameMetadata) {}

// Test the scenario where the FF navigation is deferred and then resumed, and
// the mapped url is a valid one. The navigation is expected to succeed.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    FencedFrameNavigationWithPendingMappedUUID_MappingSuccess_ValidURL) {}

// Test the scenario where the FF navigation is deferred and then resumed, and
// the mapped url is invalid. The navigation is expected to fail.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    FencedFrameNavigationWithPendingMappedUUID_MappingSuccess_InvalidURL) {}

IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    FencedFrameNavigationWithPendingMappedUUID_NavigationCanceledDuringDeferring) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckFencedFrameCookiesNavigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckPartitionedCookiesWithNonce) {}

// Similar to `CheckPartitionedCookiesWithNonce`, but this test set up consists
// of three layers nested frames, from top to bottom:
// - A fenced frame loads an origin of "a.test".
// - An urn iframe loads an origin of "a.test".
// - An iframe loads origin of "a.test".
// Both the nested urn iframe in the middle and the iframe in the bottom should
// be able to access the same cookies as the top-level fenced frame because they
// operate on the same partition nonce.
// TODO(crbug.com/40060657): Once navigation support for urn::uuid in iframes is
// deprecated, this test should be removed.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    CheckPartitionedCookiesWithNonceShouldTraverseFrameTree) {}

// Tests when a frame is considered a fenced frame or being inside a fenced
// frame tree.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckIsFencedFrame) {}

// Tests a nonce is correctly set in the isolation info for a fenced frame tree.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckIsolationInfoAndStorageKeyNonce) {}

// Tests that a fenced frame and a same-origin iframe at the same level do not
// share the same storage partition.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckUniqueStorage) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckFencedFrameNotNavigatedWithoutOptIn) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckNestedIframeNotNavigatedWithoutOptIn) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckSecFetchDestHeader) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckOpaqueUrlFlag) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CancelledNavigationCheckOpaqueUrlFlag) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       RTCPeerConnectionDisabled) {}

namespace {
class InsecureContentTestContentBrowserClient
    : public ContentBrowserTestContentBrowserClient {};
}  // namespace

class FencedFrameIgnoreCertErrors : public FencedFrameParameterizedBrowserTest {};

IN_PROC_BROWSER_TEST_F(FencedFrameIgnoreCertErrors, FencedframeHasCertError) {}

namespace {
class TestJavaScriptDialogManager : public JavaScriptDialogManager,
                                    public WebContentsDelegate {};
}  // namespace

// Test that navigation in fenced frame happens regardless of dialogs.
// It should also keep the dialogs as-is.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       ShouldIgnoreJsDialog) {}

// An observer class that asserts the page transition always is
// `ui::PageTransition::PAGE_TRANSITION_AUTO_SUBFRAME`.
class AlwaysAutoSubframeNavigationObserver : public WebContentsObserver {};

// Tests that any navigation or history API calls always replace the current
// entry and do not increase the back/forward entries.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       NavigationAndHistoryShouldBeReplaceOnly) {}

// Tests successfully going back to a page with a fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       GoBackToPageWithFencedFrame) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       ReloadPageWithFencedFrame) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       NavigateUnfencedTopAndGoBack) {}

// Simulates the crash in crbug.com/1317642 by disabling BFCache and going back
// to a page with a fenced frame navigation. This is a regression test
// originally for Shadow DOM fenced frames, which no longer exist, but we still
// explicitly test this scenario.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       GoBackToPageWithFencedFrameNavigationNoBFCache) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       RestorePageWithFencedFrameNavigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckInvalidUrnError) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       CheckCSPFencedFrameSrcOpaqueURL) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       FenceUserActivation) {}

// TODO(crbug.com/40919516): Flaky on Android release bots.
#if BUILDFLAG(IS_ANDROID) && defined(NDEBUG)
#define MAYBE_FencedAdSizes
#else
#define MAYBE_FencedAdSizes
#endif
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       MAYBE_FencedAdSizes) {}

// 1. creates a default mode fenced frame.
// 2. creates an opaque mode urn iframe nested in the fenced frame.
// 3. do an `_unfencedTop` navigation from the urn iframe.
//
// The `_unfencedTop` navigation should succeed. This verifies the fenced frame
// properties from the urn iframe are used for checks in
// `ValidateUnfencedTopNavigation`. Otherwise, if the fenced frame properties
// from the top-level fenced frame are used, a mojo bad message should be
// received.
//
// Note: Outside tests, one common scenairo that results in the same setup is
// creating a shared storage urn iframe nested inside a default fenced frame.
//
// TODO(crbug.com/40060657): Once navigation support for urn::uuid in iframes is
// deprecated, this test should be removed.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       NestedUrnIframeUnderFencedFrameUnfencedTopNavigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       EmbedderInitiatedNavigationForceNewBrowsingInstance) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       DisableUntrustedNetworkNestedFrames) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       DisableUntrustedNetworkParallelTrees) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       AddFencedFrameToDisabledNetworkTree) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       AddFencedFrameAfterNetworkCutoff) {}

// Helper class. Immediately run a callback when a navigation starts.
class DidStartNavigationCallback final : public WebContentsObserver {};

// Test that calling `window.fence.disableUntrustedNetwork` from a fenced frame
// that has a nested fenced frame with an ongoing navigation. The promise
// returned should not be resolved.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    RevokeNetworkAccessNotResolveWithOngoingNestedFencedFrameNavigation) {}

// Test that calling `window.fence.disableUntrustedNetwork` from a fenced frame
// that has a nested iframe with an ongoing navigation. The promise returned
// should not be resolved.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    RevokeNetworkAccessNotResolveWithOngoingNestedIframeNavigation) {}

// This test exercises this scenario:
// 1. There are two fenced frames: a child FF nested in a parent FF.
// 2. Child FF disables untrusted network.
// 3. Parent FF initiates a navigation of child FF to a new config.
// 4. Parent FF disables untrusted network immediately after the navigation is
// initiated. The promise returned by `window.fence.disableUntrustedNetwork()`
// should not resolve.
// 5. Attempt at this time to call shared storage get from parent FF should fail
// because the network hasn't been disabled yet due to the ongoing navigation.
// 6. The in-progress child FF navigation should be aborted.
// 7. Call `window.fence.disableUntrustedNetwork()` again for parent FF. This
// time the nonce should be resolved and the network is considered revoked.
// 8. Access to shared storage get is now allowed.
//
// Otherwise if the child FF navigation commits, the child FF will get a new
// nonce and no longer has untrusted network disabled. Parent FF can then
// communicate cross-site data into child via width or height fields, etc.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    ParentChildFencedFramesBothDisableNetworkCancelEmbedderInitiatedNavigation) {}

// Disable untrusted network in a fenced frame. An ongoing navigation taking
// place in the frame itself should not prevent the promise returned by the
// `window.fence.disableUntrustedNetwork` call from being resolved. The
// navigation should succeed.
IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       DiableNetworkWithOngoingNavigationInTargetFencedFrame) {}

// This test has a nested iframe in middle of two fenced frames.
// 1. Bottom fenced frame disables network.
// 2. The top fenced frame initiates the nested iframe navigation.
// 3. The top fenced frame disables its network right after the navigation
// starts.
// 4. The nested iframe navigation should fail.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    TopAndLeafFencedFramesRevokeNetworkNavigateNestedIframe) {}

// This test exercises this scenario:
// 1. There are two fenced frames: a child FF nested in a parent FF.
// 2. Child FF disables untrusted network.
// 3. Parent FF initiates a navigation of child FF to a new config.
// 4. The in-progress child FF navigation should succeed.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    OnlyTargetFencedFrameDisablesNetworkDoesNotCancelEmbedderInitiatedNavigation) {}

// This test exercises this scenario:
// 1. A child urn iframe nested in a parent FF.
// 2. Parent FF initiates a navigation of child urn iframe to a new urn.
// 3. Parent FF disables untrusted network.
// 4. The in-progress child urn iframe navigation should commit an error page.
//
// Note the navigation commits an error page not because of the check in
// `NavigationRequest::IsDisabledEmbedderInitiatedFencedFrameNavigation` which
// only applies to fenced frame. It is because of the check in
// `CorsURLLoaderFactory::CreateLoaderAndStart` which iterates over all active
// requests and commits those matching the nonce whose network is disabled to
// an error page.
IN_PROC_BROWSER_TEST_F(
    FencedFrameParameterizedBrowserTest,
    ParentFencedFrameDisablesNetworkCancelNestedUrnIframeNavigation) {}

IN_PROC_BROWSER_TEST_F(FencedFrameParameterizedBrowserTest,
                       ClearNonceFromNetworkContextAfterFencedFrameIsRemoved) {}

class FencedFrameReportEventBrowserTest
    : public FencedFrameParameterizedBrowserTest {};

// Fenced frame not in opaque-ads mode should fail reportEvent().
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventNonOpaqueAdsMode) {}

// The simplest test case: URN navigation into reportEvent.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventEmbedderURNNavigation) {}

// reportEvent shouldn't work if `window.fence.disableUntrustedNetwork` has been
// called in a fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventDisableUntrustedNetwork) {}

// The `eventData` field of `fence.reportEvent` should be optional.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventWithoutEventData) {}

// The `eventData` field should not exceed the limit of 64KB.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventEventDataExceedsLengthLimit) {}

// reportEvent shouldn't work if there is no associated reporting metadata with
// the reporting destination.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventNoMetadataForReportingDestination) {}

// reportEvent shouldn't work if there is no associated reporting url with
// the event type and the reporting destination.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventNoReportingURLForEventType) {}

// reportEvent shouldn't work if the reporting url is invalid.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventInvalidReportingURL) {}

// reportEvent should work in subframes that are same-origin to the most recent
// embedder-initiated committed url in the fenced frame, regardless of the
// fenced frame root's current url.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventNestedIframeSameOriginNavigation) {}

// reportEvent shouldn't work in subframes that are cross-origin to the most
// recent embedder-initiated committed url in the fenced frame, regardless of
// the fenced frame root's current url.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventNestedIframeCrossOriginNavigation) {}

// Reporting metadata should persist across FF-initiated same-origin
// navigations.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventFFSameOriginNavigation) {}

// Reporting metadata should be dropped upon cross-origin navigations,
// but come back upon new URN navigations.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventFFCrossOriginNavigation) {}

// Embedder-initiated URL navigations should always be considered cross-origin.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventEmbedderURLNavigation) {}

// Same-origin redirects in the initial URN navigation shouldn't affect
// reporting metadata.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventEmbedderSameOriginRedirect) {}

// Cross-origin redirects in the initial URN navigation shouldn't affect
// reporting metadata either. The final URL in the redirect chain should be the
// one used for subsequent same- or cross- origin checks.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventEmbedderCrossOriginRedirect) {}

// Metadata should be preserved as long as the final URL in a FF-initiated
// redirect chain is same-origin.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventFFSameOriginInterveningRedirect) {}

// Metadata should be preserved as long as the final URL in an FF-initiated
// redirect chain is same-origin.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventFFCrossOriginInterveningRedirect) {}

// Attribution Reporting headers are not set if attribution-reporting permission
// policy is disallowed for the fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventAttributionReportingDisallowed) {}

// Attribution Reporting headers are not set if attribution-reporting permission
// policy is disallowed for the nested iframe.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventNestedIframeAttributionReportingDisallowed) {}

// Tests for reportEvent to a custom destinationURL:

// The simplest test case: URN navigation into reportEvent.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       FencedFrameReportEventCustomURLEmbedderURNNavigation) {}

// reportEvent should work in subframes that are same-origin to the most recent
// embedder-initiated committed url in the fenced frame, regardless of the
// fenced frame root's current url.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventCustomURLNestedIframeSameOriginNavigation) {}

// reportEvent shouldn't work in subframes that are cross-origin to the most
// recent embedder-initiated committed url in the fenced frame, regardless of
// the fenced frame root's current url.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventCustomURLNestedIframeCrossOriginNavigation) {}

// Attribution Reporting headers are not set if attribution-reporting permission
// policy is disallowed for the fenced frame.
IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventBrowserTest,
    FencedFrameReportEventCustomURLAttributionReportingDisallowed) {}

// (Temporary test for FLEDGE iframe OT.)
// Tests that an iframe with a urn:uuid commits the navigation with the
// associated reporting metadata and `fence.reportEvent` sends the beacon to
// the registered reporting url.
// TODO(crbug.com/40053214): Disable window.fence.reportEvent in iframes.
// Remove this test once the FLEDGE origin trial stops supporting iframes.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       IframeReportingMetadata) {}

// The reportEvent beacon is a POST request. Upon receiving a 302 redirect
// response, the request is changed to a GET request. In this test case, the
// reporting url is same-origin. There are no preflight requests.
// 1. A POST request is sent to the reporting destination.
// 2. A response with 302 redirect is sent back to the requester.
// 3. A GET request is sent to the redirected destination.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       SameOriginReportEventPost302RedirectGet) {}

// The reportEvent beacon is a POST request. Upon receiving a 302 redirect
// response, the request is changed to a GET request. In this test case, the
// reporting url is cross-origin. There are no preflight requests.
// 1. A POST request is sent to the reporting destination.
// 2. A response with 302 redirect is sent back to the requester.
// 3. A GET request is sent to the redirected destination.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       CrossOriginReportEventPost302RedirectGet) {}

IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       AttributionNoneSupported_EligibleHeaderNotSet) {}

// This test case covers the crash due to different implementations are used to
// get fenced frame properties at renderer side v.s. browser side. The test set
// up consists of three layers nested frames, from top to bottom:
// - A fenced frame loads an origin of "a.test", with reporting metadata.
// - An urn iframe loads an origin of "b.test", with reporting metadata.
// - An iframe loads origin of "a.test".
//
// At the time of crashing, `FrameTreeNode::GetFencedFrameProperties()` has
// two different behaviors, controlled by its parameter `source_node`. Plus
// feature `kAllowURNsInIframes` is enabled, so urn iframes are allowed.
// - When `source_node` is set to `kClosestAncestor`, the fenced frame
// properties are obtained by doing a bottom-up traversal from the frame tree
// node.
// - When it is set to `kFrameTreeRoot`, the fenced frame properties are
// obtained directly from the fenced frame tree root node if the node is in a
// fenced frame tree. Otherwise it performs a traversal just like the case
// above.
//
// In both cases if there is no fenced frame properties found in the end, the
// fenced frame properties of this frame tree node itself is returned.
//
// Crash happens when calling `reportEvent()` from the bottom iframe.
// The renderer gets fenced frame properties with `source_node` set to
// `kFrameTreeRoot`. The fenced frame properties are from the top-level fenced
// frame. However, at browser side, the fenced frame properties are obtained
// with `source_node` set to `kClosestAncestor`. The fenced frame properties are
// from the middle urn iframe.
//
// When reportEvent is called, renderer side checks will pass. But browser side
// checks will fail because the mapped url of the fenced frame properties is
// "b.test", which is cross-origin with the iframe origin "a.test". This results
// in a mojo bad message because browser assumes this error should be caught at
// renderer side before it reaches here.
//
// The solution is to let renderer call the getter with `source_node`
// set to `kClosestAncestor`. Now both renderer and browser should get the
// fenced frame properties from the nested urn iframe. Then the expected
// behavior is that the reportEvent call fails at renderer because there is no
// reporting metadata registered. If the nested iframe is navigated to "b.test",
// `reportEvent()` should succeed.
//
// See crbug.com/1470634.
//
// Note: If the urn iframe in the middle is an ad component, the nested iframe
// is not allowed to call `reportEvent()`.
// See test `ReportEventNotAllowedInNestedIframeUnderAdComponent` in
// `InterestGroupAdComponentAutomaticBeaconBrowserTest`.
//
// TODO(crbug.com/40060657): Once navigation support for urn::uuid in iframes is
// deprecated, this test should be removed.
IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       GetFencedFramePropertiesShouldTraverseFrameTree) {}

IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       NestedIframeCrossOriginNavigationWithOptIn) {}

IN_PROC_BROWSER_TEST_F(FencedFrameReportEventBrowserTest,
                       CustomURLNestedIframeCrossOriginNavigationWithOptIn) {}

class FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest
    : public FencedFrameReportEventBrowserTest {};

IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest,
    ReportEventSameOriginSetsSupportHeader) {}

IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventAttributionCrossAppWebEnabledBrowserTest,
    ReportEventCrossOriginSetsSupportHeader) {}

class FencedFrameReportEventFacilitatedTestingEnabledBrowserTest
    : public FencedFrameReportEventBrowserTest {};

IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventFacilitatedTestingEnabledBrowserTest,
    NestedIframeCrossOriginNavigationWithOptIn) {}

IN_PROC_BROWSER_TEST_F(
    FencedFrameReportEventFacilitatedTestingEnabledBrowserTest,
    CustomURLNestedIframeCrossOriginNavigationWithOptIn) {}

// Parameterized on whether the feature is enabled or not.
class UUIDFrameTreeBrowserTest
    : public FencedFrameBrowserTestBase,
      public ::testing::WithParamInterface<std::tuple<bool, bool>> {};

IN_PROC_BROWSER_TEST_P(UUIDFrameTreeBrowserTest,
                       CheckIframeNavigationWithUUID) {}

IN_PROC_BROWSER_TEST_P(UUIDFrameTreeBrowserTest,
                       CheckIframeNavigationWithInvalidUUID) {}

IN_PROC_BROWSER_TEST_P(UUIDFrameTreeBrowserTest,
                       CheckMainFrameNavigationWithUUIDFails) {}

class FencedFrameAutomaticBeaconBrowserTest
    : public FencedFrameReportEventBrowserTest,
      public testing::WithParamInterface<const char*> {};

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest, SameOriginBasic) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       CrossOriginBasic) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest, BFCacheDisabled) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest, EmptyMessage) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       MessageExceedsLengthLimit) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       UntrustedNetworkDisabled) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       HasEventDataField) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       NoEventDataField) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       NoBeaconDataRegistered) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       NoUserActivation) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       TargetBlankNavigation) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       CrossOriginToMappedURL) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       NoDestinationsRegistered) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       AutomaticBeaconCredentialsDisallowed) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       DeprecatedTopNavigation) {}

IN_PROC_BROWSER_TEST_P(FencedFrameAutomaticBeaconBrowserTest,
                       TopNavigationStart) {}

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

INSTANTIATE_TEST_SUITE_P();

class FencedFramePreconnectBrowserTest : public FencedFrameMPArchBrowserTest {};

// Verify preconnect is working in fenced frame.
IN_PROC_BROWSER_TEST_F(FencedFramePreconnectBrowserTest, Preconnect) {}

// Verify preconnect is disabled after fenced frame untrusted network cutoff.
IN_PROC_BROWSER_TEST_F(FencedFramePreconnectBrowserTest,
                       NetworkCutoffDisablesPreconnect) {}

// Verify preconnect triggered by link response header is working in fenced
// frame.
IN_PROC_BROWSER_TEST_F(FencedFramePreconnectBrowserTest,
                       PreconnectFromLinkHeader) {}

// Verify preconnect triggered by link response header is disabled after fenced
// frame untrusted network cutoff.
IN_PROC_BROWSER_TEST_F(FencedFramePreconnectBrowserTest,
                       NetworkCutoffDisablesPreconnectFromLinkHeader) {}

}  // namespace content