chromium/chrome/browser/client_hints/client_hints_browsertest.cc

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

#include "components/client_hints/common/client_hints.h"

#include <cstddef>
#include <memory>
#include <optional>
#include <string_view>

#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/fixed_flat_set.h"
#include "base/dcheck_is_on.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
#include "base/run_loop.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/values_test_util.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_test_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/client_hints/common/switches.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/embedder_support/switches.h"
#include "components/embedder_support/user_agent_utils.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/client_hints.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents_observer.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_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "net/base/features.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/nqe/effective_connection_type.h"
#include "net/ssl/ssl_server_config.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/url_request/url_request.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/client_hints.h"
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/abseil-cpp/absl/strings/ascii.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/origin.h"

namespace {

URLLoaderInterceptor;
EmbeddedTestServer;
Contains;
Eq;
Key;
Not;
Optional;

constexpr unsigned expected_client_hints_number =;
constexpr unsigned expected_default_third_party_client_hints_number =;
constexpr unsigned expected_requested_third_party_client_hints_number =;
constexpr unsigned expected_pre_merge_third_party_client_hints_number =;

constexpr char kDefaultFeatures[] =;

// All of the status codes from HttpResponseHeaders::IsRedirectResponseCode.
const net::HttpStatusCode kRedirectStatusCodes[] =;

// An interceptor that records count of fetches and client hint headers for
// requests to https://{foo|bar}.com/non-existing-{image.jpg|iframe.html}.
class ThirdPartyURLLoaderInterceptor {};

// Returns true only if `header_value` satisfies ABNF: 1*DIGIT [ "." 1*DIGIT ]
bool IsSimilarToDoubleABNF(const std::string& header_value) {}

// Returns true only if `header_value` satisfies ABNF: 1*DIGIT
bool IsSimilarToIntABNF(const std::string& header_value) {}

// User agent minor version matches "0.X.0" which depends on reduced UA
// through kReduceUserAgentMinorVersion experiment, currently the reduced minor
// version is "0.0.0".
void CheckUserAgentMinorVersion(const std::string& user_agent_value,
                                const bool expected_ua_reduced) {}

// A helper function that returns true when the legacy GREASE implementation is
// seen. It relies on the old algorithm having only 3 possible permutations due
// to a very limited set of allowed special characters. This may be removed once
// the legacy algorithm is no longer supported for emergency situations.
bool SawOldGrease(const std::string& ua_ch_result) {}

// A helper function to determine whether the GREASE algorithm per the spec:
// https://wicg.github.io/ua-client-hints/#create-arbitrary-brands-section
// was observed in the client hint user agent header.
bool SawUpdatedGrease(const std::string& ua_ch_result) {}

class AlternatingCriticalCHRequestHandler {};

void ExpectUKMSeen(const ukm::TestAutoSetUkmRecorder& ukm_recorder,
                   const std::vector<network::mojom::WebClientHintsType>& hints,
                   size_t loads,
                   const std::string_view metric_name,
                   const std::string_view type_name) {}

void ExpectAcceptCHHeaderUKMSeen(
    const ukm::TestAutoSetUkmRecorder& ukm_recorder,
    const std::vector<network::mojom::WebClientHintsType>& hints,
    size_t loads) {}

void ExpectCriticalCHHeaderUKMSeen(
    const ukm::TestAutoSetUkmRecorder& ukm_recorder,
    const std::vector<network::mojom::WebClientHintsType>& hints,
    size_t loads) {}

void ExpectAcceptCHMetaUKMSeen(
    const ukm::TestAutoSetUkmRecorder& ukm_recorder,
    const std::vector<network::mojom::WebClientHintsType>& hints,
    size_t loads) {}

void ExpectDelegateCHMetaUKMSeen(
    const ukm::TestAutoSetUkmRecorder& ukm_recorder,
    const std::vector<network::mojom::WebClientHintsType>& hints,
    size_t loads) {}

const std::vector<network::mojom::WebClientHintsType> kStandardHTTPHeaderHints(
    {});

const std::vector<network::mojom::WebClientHintsType>
    kStandardAcceptCHMetaHints(
        {});

const std::vector<network::mojom::WebClientHintsType>
    kStandardDelegateCHMetaHints(
        {});

const std::vector<network::mojom::WebClientHintsType>
    kExtendedAcceptCHMetaHints(
        {});

const std::vector<network::mojom::WebClientHintsType>
    kExtendedDelegateCHMetaHints(
        {});
}  // namespace

class ClientHintsBrowserTest : public policy::PolicyTest {};

// When a test needs to verify all three types of meta tags, they can use this
// test and read the param to verify behavior of all three.
class ClientHintsBrowserTestForMetaTagTypes
    : public ClientHintsBrowserTest,
      public testing::WithParamInterface<network::MetaCHType> {};
INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, CorsChecks) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, HttpEquivWorks) {}
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MetaDelegateWorks) {}

// Loads a webpage that requests persisting of client hints. Verifies that
// the browser receives the mojo notification from the renderer and persists the
// client hints to the disk --- unless it's using http-equiv which shouldn't
// persist.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttps) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       ClientHintsHttps) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsAlps) {}

// Ensure that Critical-CH doesn't restart if headers added via ALPS are already
// present.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       NoCriticalRestartIfHeadersPresentViaAlps) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsAlpsRestartLimit) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsAlpsNavigationPreload) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, PRE_ClientHintsClearSession) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsClearSession) {}

// Test that client hints are attached to subresources only if they belong
// to the same host as document host.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsHttpsSubresourceDifferentOrigin) {}

// Test that client hints are attached to subresources checks the right setting
// for OTR profile.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsHttpsSubresourceOffTheRecord) {}

// Verify that we send only major version information in the `Sec-CH-UA` header
// by default, regardless of opt-in.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) {}

// Verify that client hints send when we restart the browser.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, RestartBrowser) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UAHintsTabletMode) {}

// TODO(morlovich): Move this into WebContentsImplBrowserTest once things are
// refactored enough that UA client hints actually work in content/
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentOverrideClientHints) {}

class ClientHintsUAOverrideBrowserTest : public ClientHintsBrowserTest {};

IN_PROC_BROWSER_TEST_F(ClientHintsUAOverrideBrowserTest,
                       UserAgentOverrideClientHints) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, EmptyAcceptCH) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, InjectAcceptCH_HttpEquiv) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, InjectAcceptCH_MetaDelegate) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateToFoo_HttpEquiv) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateToFoo_MetaDelegate) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateToBar_HttpEquiv) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateToBar_MetaDelegate) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateAndMerge_HttpEquiv) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, DelegateAndMerge_MetaDelegate) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_HttpEquiv) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, MergeAcceptCH_MetaDelegate) {}

void ClientHintsBrowserTest::TestProfilesIndependent(Browser* browser_a,
                                                     Browser* browser_b) {}

// Check that client hints attached to navigation inside OTR profiles
// use the right settings, regular -> OTR direction.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent) {}

// Check that client hints attached to navigation inside OTR profiles
// use the right settings, OTR -> regular direction.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent2) {}

// Only default client hints should be delegated to third party subresources.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Default) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes, Default) {}

// Loads a HTTPS webpage that does not request persisting of client hints.
// A same-origin iframe loaded by the webpage requests persistence of client
// hints. Since that's not a main frame, persistence should not happen.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       PersistenceRequestIframe_SameOrigin) {}

// Loads a HTTPS webpage that does not request persisting of client hints.
// An iframe loaded by the webpage from an cross origin server requests
// persistence of client hints.
// Verify that the request from the cross origin iframe is not honored, and
// client hints preference is not persisted.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       DisregardPersistenceRequestIframe_CrossOrigin) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       DisregardPersistenceRequestIframe) {}

// Loads a HTTPS webpage that does not request persisting of client hints.
// A subresource loaded by the webpage requests persistence of client hints.
// Verify that the request from the subresource is not honored, and client hints
// preference is not persisted.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       DisregardPersistenceRequestSubresource) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       DisregardPersistenceRequestSubresource) {}

// Loads a HTTPS webpage that does not request persisting of client hints.
// A subresource loaded by the webpage in an iframe requests persistence of
// client hints. Verify that the request from the subresource in the iframe
// is not honored, and client hints preference is not persisted.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       DisregardPersistenceRequestSubresourceIframe) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       DisregardPersistenceRequestSubresourceIframe) {}

// Loads a webpage that does not request persisting of client hints.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsFollowedByNoClientHint) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       ClientHintsFollowedByNoClientHint) {}

// The test first fetches a page that sets Accept-CH. Next, it fetches a URL
// from a different origin. However, that URL response redirects to the same
// origin from where the first page was fetched. The test verifies that on
// receiving redirect to an origin for which the browser has persisted client
// hints prefs, the browser attaches the client hints headers when fetching the
// redirected URL.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsFollowedByRedirectToNoClientHint) {}

// Ensure that even when cookies are blocked, client hint preferences are
// persisted.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsPersistedCookiesBlocked) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsAttachedCookiesBlocked) {}

// Ensure that when JavaScript is blocked, client hint preferences are not
// persisted.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsNotPersistedJavaScriptBlocked) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       ClientHintsNotPersistedJavaScriptBlocked) {}

// Ensure that when JavaScript is blocked, persisted client hints are not
// attached to the request headers.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsNotAttachedJavaScriptBlocked) {}

// Test that if the content settings are malformed, then the browser does not
// crash.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsMalformedContentSettings) {}

// Ensure that when JavaScript is blocked, client hints requested using
// Accept-CH are not attached to the request headers for subresources.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsScriptNotAllowed) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       ClientHintsScriptNotAllowed) {}

// Ensure that when the cookies is blocked, client hints are attached to the
// request headers.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsCookiesNotAllowed) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
                       ClientHintsCookiesNotAllowed) {}

// Verify that client hints are sent in the incognito profiles, and server
// client hint opt-ins are honored within the incognito profile.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
                       ClientHintsFollowedByNoClientHintIncognito) {}

class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest {};

// Make sure that when NetInfo holdback experiment is enabled, the NetInfo APIs
// and client hints return the overridden values. Verify that the client hints
// are overridden on both main frame and subresource requests.
IN_PROC_BROWSER_TEST_F(ClientHintsWebHoldbackBrowserTest,
                       EffectiveConnectionTypeChangeNotified) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UseCounter) {}
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes, UseCounter) {}

class CriticalClientHintsBrowserTest : public InProcessBrowserTest {};

// Verify that setting Critical-CH in the response header causes the request to
// be resent with the client hint included.
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       CriticalClientHintInRequestHeader) {}

// Verify that setting Critical-CH in the response header causes the request to
// be resent with the client hint included. Adding a separate test case for
// Sec-CH-UA-Full-Version-List since Sec-CH-UA-Full-Version will be deprecated.
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       CriticalClientHintFullVersionListInRequestHeader) {}

// Verify that setting Critical-CH in the response header with a client hint
// that is filtered out of Accept-CH causes the request to *not* be resent and
// the critical client hint is not included.
IN_PROC_BROWSER_TEST_F(
    CriticalClientHintsBrowserTest,
    CriticalClientHintFilteredOutOfAcceptChNotInRequestHeader) {}

// Some bots disable DCHECK, but GetRenderWidgetHostViewFromFrameTreeNode
// requires it's on for the test specific code to be invoked. This is to reduce
// production overhead.
#if DCHECK_IS_ON()

// Verify that setting Critical-CH for a viewport hint when no size has been
// cached doesn't cause an infinite redirect loop.
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       CriticalClientHintWithUncachedViewport) {}

// Verify that setting Critical-CH for a viewport hint when no size has been
// cached doesn't cause an infinite redirect loop even when hint was cached.
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       CriticalClientHintWithUncachedViewportAndCachedHints) {}

#endif

IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest, OneRestartSingleOrigin) {}

IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       OneRestartPerNavigation) {}

IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       NoRestartIfHintsAlreadyPresent) {}

IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
                       HintsPersistAfterRestart) {}

class CriticalClientHintsRedirectBrowserTest
    : public CriticalClientHintsBrowserTest,
      public testing::WithParamInterface<net::HttpStatusCode> {};

INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(CriticalClientHintsRedirectBrowserTest,
                       RestartDuringRedirect) {}

IN_PROC_BROWSER_TEST_P(CriticalClientHintsRedirectBrowserTest,
                       InsecureRedirectToSecureRedirect) {}

IN_PROC_BROWSER_TEST_P(CriticalClientHintsRedirectBrowserTest,
                       SecureRedirectToInsecureRedirect) {}

IN_PROC_BROWSER_TEST_P(CriticalClientHintsRedirectBrowserTest,
                       OneRestartSingleOriginRedirect) {}

IN_PROC_BROWSER_TEST_P(CriticalClientHintsRedirectBrowserTest,
                       OneRestartMultipleOriginRedirect) {}

class ClientHintsBrowserTestWithEmulatedMedia
    : public DevToolsProtocolTestBase {};

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTestWithEmulatedMedia,
                       PrefersColorScheme) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTestWithEmulatedMedia,
                       PrefersReducedMotion) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTestWithEmulatedMedia,
                       PrefersReducedTransparency) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTestWithEmulatedMedia,
                       MultipleMediaFeatures) {}

// Base class for the User-Agent reduction browser tests.  Common functionality
// shared between the various UA browser tests should go in this class.
class UaReductionBrowserTest : public InProcessBrowserTest {};

// As we completed the user-agent reduction origin trial in May 2023, the tests
// will verify the behavior after user-agent reduction.
class SameOriginUaReductionBrowserTest : public UaReductionBrowserTest {};

constexpr const char SameOriginUaReductionBrowserTest::kOriginUrl[];
constexpr const int SameOriginUaReductionBrowserTest::kSecChUaLowEntropyCount;

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest, NormalRequest) {}

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest,
                       IframeRequestUaReduction) {}

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest, SubresourceRequest) {}

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest, UserAgentOverride) {}

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest,
                       UserAgentOverrideSubresourceRequest) {}

IN_PROC_BROWSER_TEST_F(SameOriginUaReductionBrowserTest,
                       UserAgentOverrideIframeRequest) {}

// Tests that the reduced User-Agent string are sent on request headers for
// third-party embedded resources if user-agent reduction feature enabled and
// the permissions policy allows it.
class ThirdPartyUaReductionBrowserTest : public UaReductionBrowserTest {};

constexpr const char ThirdPartyUaReductionBrowserTest::kFirstPartyOriginUrl[];

IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest,
                       ThirdPartyIframeUaWildcardPolicy) {}

// Tests that headers are not sent to a third-party iframe after script is
// disabled with content settings.
IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest, ScriptDisabled) {}

IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest,
                       ThirdPartySubresourceUaWithWildcardPolicy) {}

IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest,
                       ThirdPartyIframeUaSpecificPolicy) {}

IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest,
                       ThirdPartySubresourceUaSpecificPolicy) {}

// CrOS multi-profiles implementation is too different for these tests.
#if !BUILDFLAG(IS_CHROMEOS_ASH)

void ClientHintsBrowserTest::TestSwitchWithNewProfile(
    const std::string& switch_value,
    size_t origins_stored) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SwitchAppliesStorage) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SwitchNotJson) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SwitchOriginNotSecure) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SwitchAcceptCHInvalid) {}

IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, SwitchAppliesStorageOneOrigin) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

class ClientHintsCommandLineSwitchBrowserTest : public ClientHintsBrowserTest {};

IN_PROC_BROWSER_TEST_F(ClientHintsCommandLineSwitchBrowserTest,
                       NavigationToDifferentOrigins) {}

IN_PROC_BROWSER_TEST_F(ClientHintsCommandLineSwitchBrowserTest,
                       ClearHintsWithAcceptCH) {}

IN_PROC_BROWSER_TEST_F(ClientHintsCommandLineSwitchBrowserTest,
                       StorageNotPresentInOffTheRecordProfile) {}

// Validate that the updated GREASE algorithm is used by default. The continued
// support of the old algorithm (which used only semicolon and space) is tested
// separately below. That functionality will be maintained for a period of time
// until we are confident in more permutations generated by the updated
// algorithm.
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UpdatedGREASEByDefault) {}

class GreaseFeatureParamOptOutTest : public ClientHintsBrowserTest {};

// Checks that the updated GREASE algorithm is not used when explicitly
// disabled.
IN_PROC_BROWSER_TEST_F(GreaseFeatureParamOptOutTest,
                       UpdatedGreaseFeatureParamOptOutTest) {}

class XRClientHintsTest : public ClientHintsBrowserTest {};

// Tests that form_factors client hints include "XR" when
// ClientHintsXRFormFactor is enabled.
IN_PROC_BROWSER_TEST_F(XRClientHintsTest, UAHintsXRMode) {}

// Tests that user-agent reduction on a redirect request.
class RedirectUaReductionBrowserTest : public InProcessBrowserTest {};

constexpr char RedirectUaReductionBrowserTest::kRedirectUrl[];

IN_PROC_BROWSER_TEST_F(RedirectUaReductionBrowserTest, NormalRedirectRequest) {}

class PrefersReducedTransparencyExplicitlyDisabledBrowserTest
    : public ClientHintsBrowserTestWithEmulatedMedia {};

IN_PROC_BROWSER_TEST_F(PrefersReducedTransparencyExplicitlyDisabledBrowserTest,
                       PrefersReducedTransparencyDisabled) {}

class QUICClientHintsTest : public ClientHintsBrowserTest {};

IN_PROC_BROWSER_TEST_F(QUICClientHintsTest, BasicQUICAlps) {}

class ClientHintsBrowserTestForBlockAcceptClientHintsExperiment
    : public ClientHintsBrowserTest,
      public testing::WithParamInterface<bool> {};
INSTANTIATE_TEST_SUITE_P();

IN_PROC_BROWSER_TEST_P(
    ClientHintsBrowserTestForBlockAcceptClientHintsExperiment,
    Block) {}