diff --git a/Libraries/LibHTTP/Cookie/Cookie.cpp b/Libraries/LibHTTP/Cookie/Cookie.cpp index 1f08c27e21..b4c6a26a0e 100644 --- a/Libraries/LibHTTP/Cookie/Cookie.cpp +++ b/Libraries/LibHTTP/Cookie/Cookie.cpp @@ -162,7 +162,7 @@ bool cookie_matches_url(Cookie const& cookie, URL::URL const& url, String const& // the cookie's domain. // - The cookie's domain is not a public suffix, for user agents configured to reject "public suffixes". bool is_not_host_only_and_domain_matches = (!cookie.host_only && domain_matches(retrieval_host_canonical, cookie.domain)) - && !URL::PublicSuffixData::is_matching_public_suffix(cookie.domain); + && !URL::PublicSuffixData::is_matching_public_suffix(cookie.domain, URL::PublicSuffixData::IncludeStarRule::No); if (!is_host_only_and_has_identical_domain && !is_not_host_only_and_domain_matches) return false; diff --git a/Libraries/LibURL/Host.cpp b/Libraries/LibURL/Host.cpp index 77edb85708..ff822e759b 100644 --- a/Libraries/LibURL/Host.cpp +++ b/Libraries/LibURL/Host.cpp @@ -184,85 +184,39 @@ Optional Host::public_suffix() const { // 1. If host is not a domain, then return null. if (!is_domain()) - return OptionalNone {}; - - auto const& host_string = m_value.get(); + return {}; // 2. Let trailingDot be "." if host ends with "."; otherwise the empty string. - auto trailing_dot = host_string.ends_with('.') ? "."sv : ""sv; - // 3. Let publicSuffix be the public suffix determined by running the Public Suffix List algorithm with host as domain. [PSL] - - // NB: The PSL algorithm maintains trailing dots, so we strip it here since step 4 expects no trailing dot. - auto host_without_trailing_dot = host_string.bytes_as_string_view(); - if (!trailing_dot.is_empty()) - host_without_trailing_dot = host_without_trailing_dot.substring_view(0, host_without_trailing_dot.length() - 1); - - // FIXME: Unify this logic with registrable domain. - auto public_suffix = PublicSuffixData::find_matching_public_suffix(host_without_trailing_dot); - if (!public_suffix.has_value()) { - auto last_dot = host_without_trailing_dot.find_last('.'); - if (last_dot.has_value()) - public_suffix = MUST(String::from_utf8(host_without_trailing_dot.substring_view(last_dot.value() + 1))); - else - public_suffix = MUST(String::from_utf8(host_without_trailing_dot)); - } + auto public_suffix = PublicSuffixData::find_matching_public_suffix(*this, PublicSuffixData::IncludeStarRule::Yes); + if (!public_suffix.has_value()) + return {}; // 4. Assert: publicSuffix is an ASCII string that does not end with ".". - VERIFY(public_suffix->is_ascii()); - VERIFY(!public_suffix->ends_with('.')); - // 5. Return publicSuffix and trailingDot concatenated. - return MUST(String::formatted("{}{}", public_suffix, trailing_dot)); + // NB: PublicSuffixData preserves the host's trailing dot, if any. + VERIFY(public_suffix->is_ascii()); + return public_suffix; } // https://url.spec.whatwg.org/#host-registrable-domain Optional Host::registrable_domain() const { // 1. If host’s public suffix is null or host’s public suffix equals host, then return null. - auto public_suffix = this->public_suffix(); - if (!public_suffix.has_value() || public_suffix == m_value.get()) - return OptionalNone {}; - - // NOTE: If we got here, we know this Host is a String. - auto const& host_string = m_value.get(); + if (!is_domain()) + return {}; // 2. Let trailingDot be "." if host ends with "."; otherwise the empty string. - auto trailing_dot = host_string.ends_with('.') ? "."sv : ""sv; - // 3. Let registrableDomain be the registrable domain determined by running the Public Suffix List algorithm with host as domain. [PSL] + auto registrable_domain = PublicSuffixData::find_matching_registrable_domain(*this, PublicSuffixData::IncludeStarRule::Yes); + if (!registrable_domain.has_value()) + return {}; - // NB: The PSL algorithm maintains trailing dots, so we strip it here since step 4 expects no trailing dot. - auto without_trailing_dot = [](StringView string) { - if (string.ends_with('.')) - return string.substring_view(0, string.length() - 1); - return string; - }; - - auto host_without_trailing_dot = without_trailing_dot(host_string.bytes_as_string_view()); - auto public_suffix_without_trailing_dot = without_trailing_dot(public_suffix->bytes_as_string_view()); - - if (!host_without_trailing_dot.ends_with(public_suffix_without_trailing_dot)) - return OptionalNone {}; - - auto subhost = host_without_trailing_dot.substring_view(0, host_without_trailing_dot.length() - public_suffix_without_trailing_dot.length()); - subhost = subhost.trim("."sv, TrimMode::Right); - - if (subhost.is_empty()) - return OptionalNone {}; - - size_t start_index = 0; - if (auto index = subhost.find_last('.'); index.has_value()) - start_index = *index + 1; - - auto registrable_domain = MUST(String::from_utf8(host_without_trailing_dot.substring_view(start_index))); - - // 4. Assert: registrableDomain is an ASCII string that does not end with ".". - VERIFY(registrable_domain.is_ascii()); - VERIFY(!registrable_domain.ends_with('.')); - - // 5. Return registrableDomain and trailingDot concatenated. - return MUST(String::formatted("{}{}", registrable_domain, trailing_dot)); + // 4. Assert: publicSuffix is an ASCII string that does not end with ".". + // 5. Return publicSuffix and trailingDot concatenated. + // NB: PublicSuffixData preserves the host's trailing dot, if any. + VERIFY(registrable_domain->is_ascii()); + return registrable_domain; } } diff --git a/Libraries/LibURL/PublicSuffixData.cpp b/Libraries/LibURL/PublicSuffixData.cpp index ffff33ef05..7dd5befcc6 100644 --- a/Libraries/LibURL/PublicSuffixData.cpp +++ b/Libraries/LibURL/PublicSuffixData.cpp @@ -21,7 +21,12 @@ static psl_ctx_t const* public_suffix_context() return context; } -static constexpr auto public_suffix_match_types = PSL_TYPE_ANY | PSL_TYPE_NO_STAR_RULE; +static constexpr auto public_suffix_match_types(PublicSuffixData::IncludeStarRule include_star_rule) +{ + if (include_star_rule == PublicSuffixData::IncludeStarRule::Yes) + return PSL_TYPE_ANY; + return PSL_TYPE_ANY | PSL_TYPE_NO_STAR_RULE; +} struct NormalizedDomain { StringView host; @@ -48,13 +53,13 @@ static Optional normalized_domain_for_host(Host const& host) return NormalizedDomain { domain, trailing_dot }; } -static bool is_matching_public_suffix_impl(StringView host) +static bool is_matching_public_suffix_impl(StringView host, PublicSuffixData::IncludeStarRule include_star_rule) { ByteString lookup_host { host }; - return psl_is_public_suffix2(public_suffix_context(), lookup_host.characters(), public_suffix_match_types); + return psl_is_public_suffix2(public_suffix_context(), lookup_host.characters(), public_suffix_match_types(include_star_rule)); } -bool PublicSuffixData::is_matching_public_suffix(StringView host) +bool PublicSuffixData::is_matching_public_suffix(StringView host, IncludeStarRule include_star_rule) { if (host.is_empty()) return false; @@ -63,23 +68,23 @@ bool PublicSuffixData::is_matching_public_suffix(StringView host) if (!parsed_host.has_value()) return false; - return is_matching_public_suffix(*parsed_host); + return is_matching_public_suffix(*parsed_host, include_star_rule); } -bool PublicSuffixData::is_matching_public_suffix(Host const& host) +bool PublicSuffixData::is_matching_public_suffix(Host const& host, IncludeStarRule include_star_rule) { auto normalized_domain = normalized_domain_for_host(host); if (!normalized_domain.has_value()) return false; - return is_matching_public_suffix_impl(normalized_domain->host); + return is_matching_public_suffix_impl(normalized_domain->host, include_star_rule); } -static Optional find_matching_public_suffix_impl(StringView host) +static Optional find_matching_public_suffix_impl(StringView host, PublicSuffixData::IncludeStarRule include_star_rule) { auto remaining_host = host; while (!remaining_host.is_empty()) { - if (is_matching_public_suffix_impl(remaining_host)) + if (is_matching_public_suffix_impl(remaining_host, include_star_rule)) return MUST(String::from_utf8(remaining_host)); auto next_label_separator = remaining_host.find('.'); @@ -92,7 +97,7 @@ static Optional find_matching_public_suffix_impl(StringView host) return OptionalNone {}; } -Optional PublicSuffixData::find_matching_public_suffix(StringView string) +Optional PublicSuffixData::find_matching_public_suffix(StringView string, IncludeStarRule include_star_rule) { if (string.is_empty()) return {}; @@ -101,26 +106,26 @@ Optional PublicSuffixData::find_matching_public_suffix(StringView string if (!parsed_host.has_value()) return {}; - return find_matching_public_suffix(*parsed_host); + return find_matching_public_suffix(*parsed_host, include_star_rule); } -Optional PublicSuffixData::find_matching_public_suffix(Host const& host) +Optional PublicSuffixData::find_matching_public_suffix(Host const& host, IncludeStarRule include_star_rule) { auto normalized_domain = normalized_domain_for_host(host); if (!normalized_domain.has_value()) return {}; - auto public_suffix = find_matching_public_suffix_impl(normalized_domain->host); + auto public_suffix = find_matching_public_suffix_impl(normalized_domain->host, include_star_rule); if (!public_suffix.has_value()) return {}; return MUST(String::formatted("{}{}", public_suffix.value(), normalized_domain->trailing_dot)); } -static Optional find_matching_registrable_domain_impl(StringView host) +static Optional find_matching_registrable_domain_impl(StringView host, PublicSuffixData::IncludeStarRule include_star_rule) { // find_matching_public_suffix_impl() always returns a tail of host, so it is by construction a suffix of it. - auto public_suffix = find_matching_public_suffix_impl(host); + auto public_suffix = find_matching_public_suffix_impl(host, include_star_rule); if (!public_suffix.has_value() || host == *public_suffix) return {}; @@ -137,7 +142,7 @@ static Optional find_matching_registrable_domain_impl(StringView host) return MUST(String::from_utf8(host.substring_view(start_index))); } -Optional PublicSuffixData::find_matching_registrable_domain(StringView string) +Optional PublicSuffixData::find_matching_registrable_domain(StringView string, IncludeStarRule include_star_rule) { if (string.is_empty()) return {}; @@ -146,16 +151,16 @@ Optional PublicSuffixData::find_matching_registrable_domain(StringView s if (!parsed_host.has_value()) return {}; - return find_matching_registrable_domain(*parsed_host); + return find_matching_registrable_domain(*parsed_host, include_star_rule); } -Optional PublicSuffixData::find_matching_registrable_domain(Host const& host) +Optional PublicSuffixData::find_matching_registrable_domain(Host const& host, IncludeStarRule include_star_rule) { auto normalized_domain = normalized_domain_for_host(host); if (!normalized_domain.has_value()) return {}; - auto registrable_domain = find_matching_registrable_domain_impl(normalized_domain->host); + auto registrable_domain = find_matching_registrable_domain_impl(normalized_domain->host, include_star_rule); if (!registrable_domain.has_value()) return {}; diff --git a/Libraries/LibURL/PublicSuffixData.h b/Libraries/LibURL/PublicSuffixData.h index 882f844e73..b18e199044 100644 --- a/Libraries/LibURL/PublicSuffixData.h +++ b/Libraries/LibURL/PublicSuffixData.h @@ -14,12 +14,17 @@ namespace URL { class PublicSuffixData { public: - static bool is_matching_public_suffix(StringView host); - static bool is_matching_public_suffix(Host const& host); - static Optional find_matching_public_suffix(StringView string); - static Optional find_matching_public_suffix(Host const& host); - static Optional find_matching_registrable_domain(StringView string); - static Optional find_matching_registrable_domain(Host const& host); + enum class IncludeStarRule { + No, + Yes, + }; + + static bool is_matching_public_suffix(StringView host, IncludeStarRule); + static bool is_matching_public_suffix(Host const& host, IncludeStarRule); + static Optional find_matching_public_suffix(StringView string, IncludeStarRule); + static Optional find_matching_public_suffix(Host const& host, IncludeStarRule); + static Optional find_matching_registrable_domain(StringView string, IncludeStarRule); + static Optional find_matching_registrable_domain(Host const& host, IncludeStarRule); }; } diff --git a/Libraries/LibWebView/CookieJar.cpp b/Libraries/LibWebView/CookieJar.cpp index 3963bfec65..854db1a623 100644 --- a/Libraries/LibWebView/CookieJar.cpp +++ b/Libraries/LibWebView/CookieJar.cpp @@ -228,7 +228,7 @@ ErrorOr CookieJar::set_cookie(URL::URL const& url, HTTP::Cookie::ParsedCoo return Error::from_string_literal("Cookie URL host cannot be canonicalized"); // 9. If the user agent is configured to reject "public suffixes" and the domain-attribute is a public suffix: - if (URL::PublicSuffixData::is_matching_public_suffix(domain_attribute)) { + if (URL::PublicSuffixData::is_matching_public_suffix(domain_attribute, URL::PublicSuffixData::IncludeStarRule::No)) { // 1. Let request-host-canonical be the canonicalized request-host. // 2. If request-host fails to be canonicalized then abort this algorithm and ignore the cookie entirely. diff --git a/Libraries/LibWebView/URL.cpp b/Libraries/LibWebView/URL.cpp index 540360511c..1ce176b3a7 100644 --- a/Libraries/LibWebView/URL.cpp +++ b/Libraries/LibWebView/URL.cpp @@ -63,7 +63,7 @@ Optional sanitize_url(StringView location, Optional cons if (any_of(RESERVED_TLDS, [&](StringView const& tld) { return domain.byte_count() > tld.length() && domain.ends_with_bytes(tld); })) return url; - auto public_suffix = URL::PublicSuffixData::find_matching_public_suffix(domain); + auto public_suffix = URL::PublicSuffixData::find_matching_public_suffix(domain, URL::PublicSuffixData::IncludeStarRule::No); if (!public_suffix.has_value() || *public_suffix == domain) { if (append_tld == AppendTLD::Yes) url->set_host(MUST(String::formatted("{}.com", domain))); @@ -248,7 +248,7 @@ static URLParts break_web_url_into_parts(URL::URL const& url, StringView url_str domain = url_without_scheme; } - auto public_suffix = URL::PublicSuffixData::find_matching_public_suffix(domain); + auto public_suffix = URL::PublicSuffixData::find_matching_public_suffix(domain, URL::PublicSuffixData::IncludeStarRule::No); if (!public_suffix.has_value() || !domain.ends_with(*public_suffix)) return { scheme, domain, remainder }; diff --git a/Tests/LibURL/TestPublicSuffix.cpp b/Tests/LibURL/TestPublicSuffix.cpp index 591b0fab45..aecb216441 100644 --- a/Tests/LibURL/TestPublicSuffix.cpp +++ b/Tests/LibURL/TestPublicSuffix.cpp @@ -50,15 +50,17 @@ TEST_CASE(public_suffix_matching_for_psl_rules) }; for (auto const& test_case : test_cases) { - EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(test_case.input), test_case.is_public_suffix); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(test_case.input), test_case.public_suffix); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(test_case.input), test_case.registrable_domain); + auto exclude_star_rule = URL::PublicSuffixData::IncludeStarRule::No; + + EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(test_case.input, exclude_star_rule), test_case.is_public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(test_case.input, exclude_star_rule), test_case.public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(test_case.input, exclude_star_rule), test_case.registrable_domain); auto host = URL::Parser::parse_host(test_case.input); VERIFY(host.has_value()); - EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(*host), test_case.is_public_suffix); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host), test_case.public_suffix); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host), test_case.registrable_domain); + EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(*host, exclude_star_rule), test_case.is_public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host, exclude_star_rule), test_case.public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host, exclude_star_rule), test_case.registrable_domain); EXPECT_EQ(host->public_suffix(), test_case.public_suffix); EXPECT_EQ(host->registrable_domain(), test_case.registrable_domain); } @@ -68,36 +70,46 @@ TEST_CASE(public_suffix_matching_without_psl_rule) { struct TestCase { StringView input; + bool is_public_suffix_with_star_rule; Optional host_public_suffix; Optional host_registrable_domain; }; TestCase test_cases[] { - { "foobar"sv, "foobar"sv, OptionalNone {} }, - { "foobar."sv, "foobar."sv, OptionalNone {} }, - { "not-a-public-suffix"sv, "not-a-public-suffix"sv, OptionalNone {} }, - { "a.example"sv, "example"sv, "a.example"sv }, - { "a.example."sv, "example."sv, "a.example."sv }, - { "b.b.example"sv, "example"sv, "b.example"sv }, - { "b.b.example."sv, "example."sv, "b.example."sv }, - { "foo.not-a-public-suffix"sv, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, - { "sub.foo.not-a-public-suffix"sv, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, - { "إختبار"sv, "xn--kgbechtv"sv, OptionalNone {} }, - { "example.إختبار"sv, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, - { "example.إختبار."sv, "xn--kgbechtv."sv, "example.xn--kgbechtv."sv }, - { "sub.example.إختبار"sv, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, + { "foobar"sv, true, "foobar"sv, OptionalNone {} }, + { "foobar."sv, true, "foobar."sv, OptionalNone {} }, + { "not-a-public-suffix"sv, true, "not-a-public-suffix"sv, OptionalNone {} }, + { "a.example"sv, false, "example"sv, "a.example"sv }, + { "a.example."sv, false, "example."sv, "a.example."sv }, + { "b.b.example"sv, false, "example"sv, "b.example"sv }, + { "b.b.example."sv, false, "example."sv, "b.example."sv }, + { "foo.not-a-public-suffix"sv, false, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, + { "sub.foo.not-a-public-suffix"sv, false, "not-a-public-suffix"sv, "foo.not-a-public-suffix"sv }, + { "إختبار"sv, true, "xn--kgbechtv"sv, OptionalNone {} }, + { "example.إختبار"sv, false, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, + { "example.إختبار."sv, false, "xn--kgbechtv."sv, "example.xn--kgbechtv."sv }, + { "sub.example.إختبار"sv, false, "xn--kgbechtv"sv, "example.xn--kgbechtv"sv }, }; for (auto const& test_case : test_cases) { - EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(test_case.input)); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(test_case.input), OptionalNone {}); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(test_case.input), OptionalNone {}); + auto exclude_star_rule = URL::PublicSuffixData::IncludeStarRule::No; + auto include_star_rule = URL::PublicSuffixData::IncludeStarRule::Yes; + + EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(test_case.input, exclude_star_rule)); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(test_case.input, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(test_case.input, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(test_case.input, include_star_rule), test_case.is_public_suffix_with_star_rule); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(test_case.input, include_star_rule), test_case.host_public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(test_case.input, include_star_rule), test_case.host_registrable_domain); auto host = URL::Parser::parse_host(test_case.input); VERIFY(host.has_value()); - EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(*host)); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host), OptionalNone {}); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host), OptionalNone {}); + EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(*host, exclude_star_rule)); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::is_matching_public_suffix(*host, include_star_rule), test_case.is_public_suffix_with_star_rule); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host, include_star_rule), test_case.host_public_suffix); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host, include_star_rule), test_case.host_registrable_domain); EXPECT_EQ(host->public_suffix(), test_case.host_public_suffix); EXPECT_EQ(host->registrable_domain(), test_case.host_registrable_domain); } @@ -116,11 +128,13 @@ TEST_CASE(invalid_hosts) // Above inputs are not valid hosts, so should not be able to be parsed or matched in the PSL. for (auto const& input : raw_invalid_inputs) { + auto exclude_star_rule = URL::PublicSuffixData::IncludeStarRule::No; + auto host = URL::Parser::parse_host(input); EXPECT(!host.has_value()); - EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(input)); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(input), OptionalNone {}); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(input), OptionalNone {}); + EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(input, exclude_star_rule)); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(input, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(input, exclude_star_rule), OptionalNone {}); } } @@ -132,15 +146,17 @@ TEST_CASE(public_suffix_matching_for_ip_addresses) }; for (auto const& input : test_cases) { - EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(input)); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(input), OptionalNone {}); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(input), OptionalNone {}); + auto exclude_star_rule = URL::PublicSuffixData::IncludeStarRule::No; + + EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(input, exclude_star_rule)); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(input, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(input, exclude_star_rule), OptionalNone {}); auto host = URL::Parser::parse_host(input); VERIFY(host.has_value()); - EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(*host)); - EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host), OptionalNone {}); - EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host), OptionalNone {}); + EXPECT(!URL::PublicSuffixData::is_matching_public_suffix(*host, exclude_star_rule)); + EXPECT_EQ(URL::PublicSuffixData::find_matching_public_suffix(*host, exclude_star_rule), OptionalNone {}); + EXPECT_EQ(URL::PublicSuffixData::find_matching_registrable_domain(*host, exclude_star_rule), OptionalNone {}); EXPECT_EQ(host->public_suffix(), OptionalNone {}); EXPECT_EQ(host->registrable_domain(), OptionalNone {}); }