chromium/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc

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

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

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_key.h"
#include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/supervised_user/supervision_mixin.h"
#include "components/supervised_user/core/browser/permission_request_creator_mock.h"
#include "components/supervised_user/core/browser/supervised_user_interstitial.h"
#include "components/supervised_user/core/browser/supervised_user_service.h"
#include "components/supervised_user/core/browser/supervised_user_settings_service.h"
#include "components/supervised_user/core/browser/supervised_user_url_filter.h"
#include "components/supervised_user/core/browser/supervised_user_utils.h"
#include "components/supervised_user/core/common/features.h"
#include "components/supervised_user/core/common/features_testutils.h"
#include "components/supervised_user/core/common/supervised_user_constants.h"
#include "components/supervised_user/test_support/kids_management_api_server_mock.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/page_type.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/shell.h"
#include "chrome/browser/ui/webui/ash/parent_access/parent_access_dialog.h"
#include "ui/events/event_constants.h"
#include "ui/events/test/event_generator.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace {

NavigationController;
WebContents;

static const char* kExampleHost =;
static const char* kExampleHost2 =;
static const char* kStrippedExampleHost =;
static const char* kFamiliesHost =;
static const char* kIframeHost1 =;
static const char* kIframeHost2 =;

#if BUILDFLAG(IS_CHROMEOS_ASH)
constexpr char kLocalUrlAccessCommand[] = "requestUrlAccessLocal";
#endif
constexpr char kRemoteUrlAccessCommand[] =;

class ThrottleTestParam {};

// Class to keep track of iframes created and destroyed.
// TODO(crbug.com/40173416): Can be replaced with
// WebContents::UnsafeFindFrameByFrameTreeNodeId.
class RenderFrameTracker : public content::WebContentsObserver {};

void RenderFrameTracker::RenderFrameHostChanged(
    content::RenderFrameHost* old_host,
    content::RenderFrameHost* new_host) {}

void RenderFrameTracker::FrameDeleted(int frame_tree_node_id) {}

class InnerWebContentsAttachedWaiter : public content::WebContentsObserver {};

void InnerWebContentsAttachedWaiter::InnerWebContentsAttached(
    content::WebContents* inner_web_contents,
    content::RenderFrameHost* render_frame_host,
    bool is_full_page) {}

void InnerWebContentsAttachedWaiter::WaitForInnerWebContentsAttached() {}

// Helper class to wait for a particular navigation in a particular render
// frame in tests.
class NavigationFinishedWaiter : public content::WebContentsObserver {};

NavigationFinishedWaiter::NavigationFinishedWaiter(
    content::WebContents* web_contents,
    int frame_id,
    const GURL& url)
    :{}

void NavigationFinishedWaiter::Wait() {}

void NavigationFinishedWaiter::DidFinishNavigation(
    content::NavigationHandle* navigation_handle) {}

class SupervisedUserNavigationThrottleTestBase
    : public MixinBasedInProcessBrowserTest {};

bool SupervisedUserNavigationThrottleTestBase::
    IsInterstitialBeingShownInMainFrame(Browser* browser) {}

void SupervisedUserNavigationThrottleTestBase::SetUp() {}

void SupervisedUserNavigationThrottleTestBase::SetUpOnMainThread() {}

class SupervisedUserNavigationThrottleTest
    : public SupervisedUserNavigationThrottleTestBase,
      ::testing::WithParamInterface<ThrottleTestParam::FeatureStatus> {};

class SupervisedUserNavigationThrottleWithPrerenderingTest
    : public SupervisedUserNavigationThrottleTestBase,
      public testing::WithParamInterface<
          std::tuple<std::string, ThrottleTestParam::FeatureStatus>> {};

INSTANTIATE_TEST_SUITE_P();

// Tests that prerendering fails in supervised user mode.
#if BUILDFLAG(IS_CHROMEOS)
// TODO(crbug.com/40201321): Flaky on ChromeOS.
#define MAYBE_DisallowPrerendering
#else
#define MAYBE_DisallowPrerendering
#endif
IN_PROC_BROWSER_TEST_P(SupervisedUserNavigationThrottleWithPrerenderingTest,
                       MAYBE_DisallowPrerendering) {}

// Tests that navigating to a blocked page simply fails if there is no
// SupervisedUserNavigationObserver.
IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest,
                       NoNavigationObserverBlock) {}

IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest,
                       BlockMainFrameWithInterstitial) {}

IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest,
                       DontBlockSubFrame) {}

IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest,
                       AllowFamiliesDotGoogleDotComAccess) {}

class SupervisedUserIframeFilterTest
    : public SupervisedUserNavigationThrottleTestBase,
      public testing::WithParamInterface<
          std::tuple<supervised_user::testing::LocalWebApprovalsTestCase,
                     ThrottleTestParam::FeatureStatus>> {};

void SupervisedUserIframeFilterTest::SetUpOnMainThread() {}

void SupervisedUserIframeFilterTest::TearDownOnMainThread() {}

std::vector<int> SupervisedUserIframeFilterTest::GetBlockedFrames() {}

const GURL& SupervisedUserIframeFilterTest::GetBlockedFrameURL(int frame_id) {}

bool SupervisedUserIframeFilterTest::IsInterstitialBeingShownInFrame(
    int frame_id) {}

bool SupervisedUserIframeFilterTest::IsBlockReasonBeingShown(int frame_id) {}

bool SupervisedUserIframeFilterTest::IsDetailsLinkBeingShown(int frame_id) {}

bool SupervisedUserIframeFilterTest::IsRemoteApprovalsButtonBeingShown(
    int frame_id) {}

bool SupervisedUserIframeFilterTest::IsLocalApprovalsButtonBeingShown(
    int frame_id) {}

void SupervisedUserIframeFilterTest::CheckPreferredApprovalButton(
    int frame_id) {}

bool SupervisedUserIframeFilterTest::IsLocalApprovalsInsteadButtonBeingShown(
    int frame_id) {}

void SupervisedUserIframeFilterTest::SendCommandToFrame(
    const std::string& command_name,
    int frame_id) {}

void SupervisedUserIframeFilterTest::WaitForNavigationFinished(
    int frame_id,
    const GURL& url) {}

bool SupervisedUserIframeFilterTest::RunCommandAndGetBooleanFromFrame(
    int frame_id,
    const std::string& command) {}

// Returns whether the feature is in fact enabled, rather that was requested to
// be enabled.
bool SupervisedUserIframeFilterTest::IsLocalWebApprovalsEnabled() const {}

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, BlockSubFrame) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, BlockMultipleSubFrames) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest, TestBackButton) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
                       TestBackButtonMainFrame) {}

// Tests that the trivial www-subdomain stripping is applied on the url
// of the interstitial. Blocked urls without further conflicts will be
// unblocked by a remote approval.
// TODO(crbug.com/356676072): flaky on ChromeOS.
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_BlockedMainFrameFromClassifyUrlForUnstripedHostIsStrippedInRemoteApproval
#else
#define MAYBE_BlockedMainFrameFromClassifyUrlForUnstripedHostIsStrippedInRemoteApproval
#endif
IN_PROC_BROWSER_TEST_P(
    SupervisedUserIframeFilterTest,
    MAYBE_BlockedMainFrameFromClassifyUrlForUnstripedHostIsStrippedInRemoteApproval) {}

// Tests that the url stripping is applied on the url on the interstitial, when
// there is no unstriped host entry in the blocklist.
IN_PROC_BROWSER_TEST_P(
    SupervisedUserIframeFilterTest,
    BlockedMainFrameFromBlockListIsStrippedInRemoteApproval) {}

// Tests that the url stripping is skipped on the url on the interstitial, when
// there is a unstriped host entry in the blocklist. Blocked urls without
// further conflicts will be unblocked by a remote approval.
IN_PROC_BROWSER_TEST_P(
    SupervisedUserIframeFilterTest,
    BlockedMainFrameFromBlockListForUnstripedHostSkipsStrippingInRemoteApproval) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
                       AllowlistedMainFrameDenylistedIframe) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
                       RememberAlreadyRequestedHosts) {}

IN_PROC_BROWSER_TEST_P(SupervisedUserIframeFilterTest,
                       IFramesWithSameDomainAsMainFrameAllowed) {}

// The switches::kHostWindowBounds commandline flag doesn't appear to work
// for tests on other platforms.
// TODO(b/300426225): enable these tests on Linux/Mac/Windows.
#if BUILDFLAG(IS_CHROMEOS_ASH)
class SupervisedUserNarrowWidthIframeFilterTest
    : public SupervisedUserIframeFilterTest {
 protected:
  SupervisedUserNarrowWidthIframeFilterTest() = default;
  ~SupervisedUserNarrowWidthIframeFilterTest() override = default;

  void SetUp() override;
};

void SupervisedUserNarrowWidthIframeFilterTest::SetUp() {
  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
      ::switches::kHostWindowBounds, "0+0-400x800");
  SupervisedUserIframeFilterTest::SetUp();
}

INSTANTIATE_TEST_SUITE_P(
    LocalWebApprovalsEnabledNarrowWidth,
    SupervisedUserNarrowWidthIframeFilterTest,
    testing::Combine(
        supervised_user::testing::LocalWebApprovalsTestCase::OnlySupported(),
        ThrottleTestParam::Values()),
    [](const testing::TestParamInfo<
        std::tuple<supervised_user::testing::LocalWebApprovalsTestCase,
                   ThrottleTestParam::FeatureStatus>>& info) {
      return base::StrCat(
          {"WithLocalWebApprovalsTestCase",
           static_cast<std::string>(std::get<0>(info.param)), "WithThrottle",
           ThrottleTestParam::ToString(std::get<1>(info.param))});
    });

IN_PROC_BROWSER_TEST_P(SupervisedUserNarrowWidthIframeFilterTest,
                       NarrowWidthWindow) {
  BlockHost(kExampleHost);

  GURL blocked_url = embedded_test_server()->GetURL(
      kExampleHost, "/supervised_user/with_iframes.html");
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), blocked_url));
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));

  auto blocked_frames = GetBlockedFrames();
  EXPECT_EQ(blocked_frames.size(), 1u);

  // Expect that remote approvals button is shown.
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frames[0]));
  // Expect that the local approvals button is shown if the flag is enabled.
  EXPECT_EQ(IsLocalWebApprovalsEnabled(),
            IsLocalApprovalsButtonBeingShown(blocked_frames[0]));
  // Expect that the "Details" link is shown.
  EXPECT_TRUE(IsDetailsLinkBeingShown(blocked_frames[0]));

  // Delay approval/denial by parent.
  permission_creator()->SetPermissionResult(true);
  permission_creator()->DelayHandlingForNextRequests();

  // Request permission.
  SendCommandToFrame(kRemoteUrlAccessCommand, blocked_frames[0]);

  // Navigate to another allowed url.
  GURL allowed_url = embedded_test_server()->GetURL(
      kExampleHost2, "/supervised_user/with_iframes.html");

  kids_management_api_mock().AllowSubsequentClassifyUrl();
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), allowed_url));
  EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));

  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), blocked_url));
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));

  // Navigate back to the blocked url.
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));

  // Error page is being shown, but "Ask Permission" button is not being shown.
  EXPECT_FALSE(IsRemoteApprovalsButtonBeingShown(blocked_frames[0]));
  // Expect that the local approvals instead button is shown on the page if the
  // flag is enabled.
  EXPECT_EQ(IsLocalWebApprovalsEnabled(),
            IsLocalApprovalsInsteadButtonBeingShown(blocked_frames[0]));
  // "Details" link is not shown.
  EXPECT_FALSE(IsDetailsLinkBeingShown(blocked_frames[0]));

  content::WebContents* active_contents =
      browser()->tab_strip_model()->GetActiveWebContents();
  SupervisedUserNavigationObserver* navigation_observer =
      SupervisedUserNavigationObserver::FromWebContents(active_contents);
  ASSERT_NE(navigation_observer, nullptr);

  EXPECT_TRUE(base::Contains(navigation_observer->requested_hosts_for_test(),
                             kExampleHost));

  NavigationFinishedWaiter waiter(
      active_contents,
      active_contents->GetPrimaryMainFrame()->GetFrameTreeNodeId(),
      blocked_url);
  permission_creator()->HandleDelayedRequests();
  waiter.Wait();

  EXPECT_FALSE(base::Contains(navigation_observer->requested_hosts_for_test(),
                              kExampleHost));

  EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));
}

// Tests Chrome OS local web approvals flow.
using ChromeOSLocalWebApprovalsTest = SupervisedUserIframeFilterTest;

// Only test for the local web approvals feature enabled.
INSTANTIATE_TEST_SUITE_P(
    ,
    ChromeOSLocalWebApprovalsTest,
    testing::Combine(
        supervised_user::testing::LocalWebApprovalsTestCase::OnlySupported(),
        ThrottleTestParam::Values()),
    [](const testing::TestParamInfo<
        std::tuple<supervised_user::testing::LocalWebApprovalsTestCase,
                   ThrottleTestParam::FeatureStatus>>& info) {
      return base::StrCat(
          {"WithLocalWebApprovalsTestCase",
           static_cast<std::string>(std::get<0>(info.param)), "WithThrottle",
           ThrottleTestParam::ToString(std::get<1>(info.param))});
    });

IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
                       StartLocalWebApprovalsFromMainFrame) {
  base::HistogramTester histogram_tester;
  BlockHost(kExampleHost);

  GURL blocked_url = embedded_test_server()->GetURL(
      kExampleHost, "/supervised_user/simple.html");
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), blocked_url));
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));

  const std::vector<int> blocked_frames = GetBlockedFrames();
  ASSERT_EQ(blocked_frames.size(), 1u);
  const int blocked_frame = blocked_frames[0];
  EXPECT_TRUE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frame));
  CheckPreferredApprovalButton(blocked_frame);

  // Trigger local approval flow - native dialog should appear.
  SendCommandToFrame(kLocalUrlAccessCommand, blocked_frame);
  EXPECT_TRUE(ash::ParentAccessDialog::GetInstance());

  // Close the flow without approval - interstitial should be still shown.
  ui::test::EventGenerator generator(ash::Shell::Get()->GetPrimaryRootWindow());
  generator.PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);

  EXPECT_FALSE(ash::ParentAccessDialog::GetInstance());
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));
  EXPECT_TRUE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frame));
  CheckPreferredApprovalButton(blocked_frame);

  histogram_tester.ExpectUniqueSample(
      supervised_user::SupervisedUserInterstitial::
          kInterstitialCommandHistogramName,
      supervised_user::SupervisedUserInterstitial::Commands::
          LOCAL_ACCESS_REQUEST,
      1);
  histogram_tester.ExpectUniqueSample(
      supervised_user::SupervisedUserInterstitial::
          kInterstitialPermissionSourceHistogramName,
      supervised_user::SupervisedUserInterstitial::RequestPermissionSource::
          MAIN_FRAME,
      1);
}

IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
                       StartLocalWebApprovalsFromIframe) {
  base::HistogramTester histogram_tester;
  BlockHost(kIframeHost1);

  const GURL allowed_url_with_iframes = embedded_test_server()->GetURL(
      kExampleHost, "/supervised_user/with_iframes.html");

  kids_management_api_mock().AllowSubsequentClassifyUrl();
  ASSERT_TRUE(
      ui_test_utils::NavigateToURL(browser(), allowed_url_with_iframes));
  EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));

  const std::vector<int> blocked_frames = GetBlockedFrames();
  ASSERT_EQ(blocked_frames.size(), 1u);
  const int blocked_frame = blocked_frames[0];
  EXPECT_TRUE(IsInterstitialBeingShownInFrame(blocked_frame));
  EXPECT_TRUE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frame));
  CheckPreferredApprovalButton(blocked_frame);

  // Trigger local approval flow - native dialog should appear.
  SendCommandToFrame(kLocalUrlAccessCommand, blocked_frame);
  EXPECT_TRUE(ash::ParentAccessDialog::GetInstance());

  // Close the flow without approval - interstitial should be still shown.
  ui::test::EventGenerator generator(ash::Shell::Get()->GetPrimaryRootWindow());
  generator.PressKey(ui::VKEY_ESCAPE, ui::EF_NONE);

  EXPECT_FALSE(ash::ParentAccessDialog::GetInstance());
  EXPECT_FALSE(IsInterstitialBeingShownInMainFrame(browser()));
  EXPECT_TRUE(IsInterstitialBeingShownInFrame(blocked_frame));
  EXPECT_TRUE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frame));
  CheckPreferredApprovalButton(blocked_frame);

  histogram_tester.ExpectUniqueSample(
      supervised_user::SupervisedUserInterstitial::
          kInterstitialCommandHistogramName,
      supervised_user::SupervisedUserInterstitial::Commands::
          LOCAL_ACCESS_REQUEST,
      1);
  histogram_tester.ExpectUniqueSample(
      supervised_user::SupervisedUserInterstitial::
          kInterstitialPermissionSourceHistogramName,
      supervised_user::SupervisedUserInterstitial::RequestPermissionSource::
          SUB_FRAME,
      1);
}

IN_PROC_BROWSER_TEST_P(ChromeOSLocalWebApprovalsTest,
                       UpdateUIAfterRemoteRequestSent) {
  BlockHost(kExampleHost);

  GURL blocked_url = embedded_test_server()->GetURL(
      kExampleHost, "/supervised_user/simple.html");
  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), blocked_url));
  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));

  const std::vector<int> blocked_frames = GetBlockedFrames();
  ASSERT_EQ(blocked_frames.size(), 1u);
  const int blocked_frame = blocked_frames[0];
  EXPECT_TRUE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsRemoteApprovalsButtonBeingShown(blocked_frame));

  // Trigger remote approval flow - ui should change.
  SendCommandToFrame(kRemoteUrlAccessCommand, blocked_frame);

  EXPECT_TRUE(IsInterstitialBeingShownInMainFrame(browser()));
  EXPECT_FALSE(IsLocalApprovalsButtonBeingShown(blocked_frame));
  EXPECT_FALSE(IsRemoteApprovalsButtonBeingShown(blocked_frame));
  EXPECT_TRUE(IsLocalApprovalsInsteadButtonBeingShown(blocked_frame));
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class SupervisedUserNavigationThrottleOnlyEnabledForSupervisedUsers
    : public SupervisedUserNavigationThrottleTestBase,
      public testing::WithParamInterface<
          std::tuple<supervised_user::SupervisionMixin::SignInMode,
                     ThrottleTestParam::FeatureStatus>> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(
    SupervisedUserNavigationThrottleOnlyEnabledForSupervisedUsers,
    CheckAgainstBlocklist) {}

// TODO(crbug.com/359268574): Flaky on ChromeOS.
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_CheckAgainstClassifyUrlRPC
#else
#define MAYBE_CheckAgainstClassifyUrlRPC
#endif
IN_PROC_BROWSER_TEST_P(
    SupervisedUserNavigationThrottleOnlyEnabledForSupervisedUsers,
    MAYBE_CheckAgainstClassifyUrlRPC) {}

// Flaky: crbug.com/361463503
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_CheckSameDocumentNavigationAgainstClassifyUrlRPC
#else
#define MAYBE_CheckSameDocumentNavigationAgainstClassifyUrlRPC
#endif  // BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_P(
    SupervisedUserNavigationThrottleOnlyEnabledForSupervisedUsers,
    MAYBE_CheckSameDocumentNavigationAgainstClassifyUrlRPC) {}

class SupervisedUserNavigationThrottleFencedFramesTest
    : public SupervisedUserNavigationThrottleTestBase,
      public testing::WithParamInterface<ThrottleTestParam::FeatureStatus> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(SupervisedUserNavigationThrottleFencedFramesTest,
                       BlockFencedFrame) {}

}  // namespace