| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h" |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/platform/web_runtime_features.h" |
| #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" |
| #include "third_party/blink/renderer/platform/network/http_names.h" |
| #include "third_party/blink/renderer/platform/weborigin/kurl.h" |
| #include "third_party/blink/renderer/platform/wtf/time.h" |
| |
| namespace blink { |
| |
| class ClientHintsPreferencesTest : public testing::Test {}; |
| |
| TEST_F(ClientHintsPreferencesTest, BasicSecure) { |
| struct TestCase { |
| const char* header_value; |
| bool expectation_resource_width; |
| bool expectation_dpr; |
| bool expectation_viewport_width; |
| bool expectation_rtt; |
| bool expectation_downlink; |
| bool expectation_ect; |
| bool expectation_lang; |
| } cases[] = { |
| {"width, dpr, viewportWidth", true, true, false, false, false, false, |
| false}, |
| {"WiDtH, dPr, viewport-width, rtt, downlink, ect, lang", true, true, true, |
| true, true, true, true}, |
| {"WiDtH, dPr, viewport-width, rtt, downlink, effective-connection-type", |
| true, true, true, true, true, false, false}, |
| {"WIDTH, DPR, VIWEPROT-Width", true, true, false, false, false, false, |
| false}, |
| {"VIewporT-Width, wutwut, width", true, false, true, false, false, false, |
| false}, |
| {"dprw", false, false, false, false, false, false, false}, |
| {"DPRW", false, false, false, false, false, false, false}, |
| }; |
| |
| for (const auto& test_case : cases) { |
| ClientHintsPreferences preferences; |
| const KURL kurl(String::FromUTF8("https://www.google.com/")); |
| preferences.UpdateFromAcceptClientHintsHeader(test_case.header_value, kurl, |
| nullptr); |
| EXPECT_EQ( |
| test_case.expectation_resource_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_EQ(test_case.expectation_dpr, |
| preferences.ShouldSend(mojom::WebClientHintsType::kDpr)); |
| EXPECT_EQ( |
| test_case.expectation_viewport_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth)); |
| EXPECT_EQ(test_case.expectation_rtt, |
| preferences.ShouldSend(mojom::WebClientHintsType::kRtt)); |
| EXPECT_EQ(test_case.expectation_downlink, |
| preferences.ShouldSend(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_EQ(test_case.expectation_ect, |
| preferences.ShouldSend(mojom::WebClientHintsType::kEct)); |
| EXPECT_EQ(test_case.expectation_lang, |
| preferences.ShouldSend(mojom::WebClientHintsType::kLang)); |
| |
| // Calling UpdateFromAcceptClientHintsHeader with empty header should have |
| // no impact on client hint preferences. |
| preferences.UpdateFromAcceptClientHintsHeader("", kurl, nullptr); |
| EXPECT_EQ( |
| test_case.expectation_resource_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_EQ(test_case.expectation_dpr, |
| preferences.ShouldSend(mojom::WebClientHintsType::kDpr)); |
| EXPECT_EQ( |
| test_case.expectation_viewport_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth)); |
| |
| // Calling UpdateFromAcceptClientHintsHeader with an invalid header should |
| // have no impact on client hint preferences. |
| preferences.UpdateFromAcceptClientHintsHeader("foobar", kurl, nullptr); |
| EXPECT_EQ( |
| test_case.expectation_resource_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_EQ(test_case.expectation_dpr, |
| preferences.ShouldSend(mojom::WebClientHintsType::kDpr)); |
| EXPECT_EQ( |
| test_case.expectation_viewport_width, |
| preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth)); |
| } |
| } |
| |
| // Verify that the set of enabled client hints is updated every time Update*() |
| // methods are called. |
| TEST_F(ClientHintsPreferencesTest, SecureEnabledTypesAreUpdated) { |
| ClientHintsPreferences preferences; |
| const KURL kurl(String::FromUTF8("https://www.google.com/")); |
| preferences.UpdateFromAcceptClientHintsHeader("rtt, downlink", kurl, nullptr); |
| |
| EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration()); |
| EXPECT_FALSE( |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kDpr)); |
| EXPECT_FALSE( |
| preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kLang)); |
| |
| // Calling UpdateFromAcceptClientHintsHeader with empty header should have |
| // no impact on client hint preferences. |
| preferences.UpdateFromAcceptClientHintsHeader("", kurl, nullptr); |
| EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration()); |
| EXPECT_FALSE( |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kLang)); |
| |
| // Calling UpdateFromAcceptClientHintsHeader with an invalid header should |
| // have no impact on client hint preferences. |
| preferences.UpdateFromAcceptClientHintsHeader("foobar", kurl, nullptr); |
| EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration()); |
| EXPECT_FALSE( |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kLang)); |
| |
| // Calling UpdateFromAcceptClientHintsHeader with "width" header should |
| // have no impact on already enabled client hint preferences. |
| preferences.UpdateFromAcceptClientHintsHeader("width", kurl, nullptr); |
| EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration()); |
| EXPECT_TRUE( |
| preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt)); |
| EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct)); |
| EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kLang)); |
| |
| preferences.UpdateFromAcceptClientHintsLifetimeHeader("1000", kurl, nullptr); |
| EXPECT_EQ(base::TimeDelta::FromSeconds(1000), |
| preferences.GetPersistDuration()); |
| } |
| |
| TEST_F(ClientHintsPreferencesTest, Insecure) { |
| for (const auto& use_secure_url : {false, true}) { |
| ClientHintsPreferences preferences; |
| const KURL kurl = use_secure_url |
| ? KURL(String::FromUTF8("https://www.google.com/")) |
| : KURL(String::FromUTF8("http://www.google.com/")); |
| preferences.UpdateFromAcceptClientHintsHeader("dpr", kurl, nullptr); |
| EXPECT_EQ(use_secure_url, |
| preferences.ShouldSend(mojom::WebClientHintsType::kDpr)); |
| } |
| } |
| |
| // Verify that the client hints header and the lifetime header is parsed |
| // correctly. |
| TEST_F(ClientHintsPreferencesTest, ParseHeaders) { |
| struct TestCase { |
| const char* accept_ch_header_value; |
| const char* accept_lifetime_header_value; |
| int64_t expect_persist_duration_seconds; |
| bool expect_device_memory; |
| bool expect_width; |
| bool expect_dpr; |
| bool expect_viewport_width; |
| bool expect_rtt; |
| bool expect_downlink; |
| bool expect_ect; |
| bool expect_lang; |
| } test_cases[] = { |
| {"width, dpr, viewportWidth, lang", "", 0, false, true, true, false, |
| false, false, false, true}, |
| {"width, dpr, viewportWidth", "-1000", 0, false, true, true, false, false, |
| false, false, false}, |
| {"width, dpr, viewportWidth", "1000s", 0, false, true, true, false, false, |
| false, false, false}, |
| {"width, dpr, viewportWidth", "1000.5", 0, false, true, true, false, |
| false, false, false, false}, |
| {"width, dpr, rtt, downlink, ect", "1000", 1000, false, true, true, false, |
| true, true, true, false}, |
| {"device-memory", "-1000", 0, true, false, false, false, false, false, |
| false, false}, |
| {"dpr rtt", "1000", 1000, false, false, false, false, false, false, false, |
| false}, |
| }; |
| |
| for (const auto& test : test_cases) { |
| ClientHintsPreferences preferences; |
| WebEnabledClientHints enabled_types = |
| preferences.GetWebEnabledClientHints(); |
| EXPECT_FALSE( |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory)); |
| EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr)); |
| EXPECT_FALSE( |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_FALSE( |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth)); |
| EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt)); |
| EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kEct)); |
| EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kLang)); |
| TimeDelta persist_duration = preferences.GetPersistDuration(); |
| EXPECT_EQ(base::TimeDelta(), persist_duration); |
| |
| const KURL kurl(String::FromUTF8("https://www.google.com/")); |
| preferences.UpdateFromAcceptClientHintsHeader(test.accept_ch_header_value, |
| kurl, nullptr); |
| preferences.UpdateFromAcceptClientHintsLifetimeHeader( |
| test.accept_lifetime_header_value, kurl, nullptr); |
| |
| enabled_types = preferences.GetWebEnabledClientHints(); |
| persist_duration = preferences.GetPersistDuration(); |
| |
| EXPECT_EQ(test.expect_persist_duration_seconds, |
| persist_duration.InSeconds()); |
| |
| EXPECT_EQ( |
| test.expect_device_memory, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory)); |
| EXPECT_EQ(test.expect_dpr, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr)); |
| EXPECT_EQ( |
| test.expect_width, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth)); |
| EXPECT_EQ( |
| test.expect_viewport_width, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth)); |
| EXPECT_EQ(test.expect_rtt, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt)); |
| EXPECT_EQ(test.expect_downlink, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink)); |
| EXPECT_EQ(test.expect_ect, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kEct)); |
| EXPECT_EQ(test.expect_lang, |
| enabled_types.IsEnabled(mojom::WebClientHintsType::kLang)); |
| } |
| } |
| |
| } // namespace blink |