#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[] = …;
const net::HttpStatusCode kRedirectStatusCodes[] = …;
class ThirdPartyURLLoaderInterceptor { … };
bool IsSimilarToDoubleABNF(const std::string& header_value) { … }
bool IsSimilarToIntABNF(const std::string& header_value) { … }
void CheckUserAgentMinorVersion(const std::string& user_agent_value,
const bool expected_ua_reduced) { … }
bool SawOldGrease(const std::string& ua_ch_result) { … }
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(
{ … });
}
class ClientHintsBrowserTest : public policy::PolicyTest { … };
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) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsHttps) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
ClientHintsHttps) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsAlps) { … }
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) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsHttpsSubresourceDifferentOrigin) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsHttpsSubresourceOffTheRecord) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UserAgentVersion) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, RestartBrowser) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UAHintsTabletMode) { … }
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) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, OffTheRecordIndependent2) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, Default) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes, Default) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
PersistenceRequestIframe_SameOrigin) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
DisregardPersistenceRequestIframe_CrossOrigin) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
DisregardPersistenceRequestIframe) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
DisregardPersistenceRequestSubresource) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
DisregardPersistenceRequestSubresource) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
DisregardPersistenceRequestSubresourceIframe) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
DisregardPersistenceRequestSubresourceIframe) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, NoClientHintsHttps) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsFollowedByNoClientHint) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
ClientHintsFollowedByNoClientHint) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsFollowedByRedirectToNoClientHint) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsPersistedCookiesBlocked) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsAttachedCookiesBlocked) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsNotPersistedJavaScriptBlocked) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
ClientHintsNotPersistedJavaScriptBlocked) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsNotAttachedJavaScriptBlocked) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsMalformedContentSettings) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsScriptNotAllowed) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
ClientHintsScriptNotAllowed) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, ClientHintsCookiesNotAllowed) { … }
IN_PROC_BROWSER_TEST_P(ClientHintsBrowserTestForMetaTagTypes,
ClientHintsCookiesNotAllowed) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest,
ClientHintsFollowedByNoClientHintIncognito) { … }
class ClientHintsWebHoldbackBrowserTest : public ClientHintsBrowserTest { … };
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 { … };
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
CriticalClientHintInRequestHeader) { … }
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
CriticalClientHintFullVersionListInRequestHeader) { … }
IN_PROC_BROWSER_TEST_F(
CriticalClientHintsBrowserTest,
CriticalClientHintFilteredOutOfAcceptChNotInRequestHeader) { … }
#if DCHECK_IS_ON()
IN_PROC_BROWSER_TEST_F(CriticalClientHintsBrowserTest,
CriticalClientHintWithUncachedViewport) { … }
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) { … }
class UaReductionBrowserTest : public InProcessBrowserTest { … };
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) { … }
class ThirdPartyUaReductionBrowserTest : public UaReductionBrowserTest { … };
constexpr const char ThirdPartyUaReductionBrowserTest::kFirstPartyOriginUrl[];
IN_PROC_BROWSER_TEST_F(ThirdPartyUaReductionBrowserTest,
ThirdPartyIframeUaWildcardPolicy) { … }
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) { … }
#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
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) { … }
IN_PROC_BROWSER_TEST_F(ClientHintsBrowserTest, UpdatedGREASEByDefault) { … }
class GreaseFeatureParamOptOutTest : public ClientHintsBrowserTest { … };
IN_PROC_BROWSER_TEST_F(GreaseFeatureParamOptOutTest,
UpdatedGreaseFeatureParamOptOutTest) { … }
class XRClientHintsTest : public ClientHintsBrowserTest { … };
IN_PROC_BROWSER_TEST_F(XRClientHintsTest, UAHintsXRMode) { … }
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) { … }