0

Delete obsolete IDNA metrics code

The switch to non-transitional IDNA fully launched. We no longer need
metrics or console logging code.

A followup CL will remove remaining code from blink::KURL and other
places.

Bug: 40882787
Change-Id: I2c2ca9b24ca79074abb5484c1626bbc4d4f04698
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6020762
Reviewed-by: Christian Xu <christianxu@chromium.org>
Commit-Queue: Mustafa Emre Acer <meacer@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1390529}
This commit is contained in:
Mustafa Emre Acer
2024-12-02 20:02:35 +00:00
committed by Chromium LUCI CQ
parent 78e4db079c
commit f2e4e401d0
36 changed files with 41 additions and 520 deletions

@ -3411,7 +3411,7 @@ IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest,
http_url, nullptr, WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::URL_WHAT_YOU_TYPED,
base::TimeTicks(), false, true, std::u16string(), AutocompleteMatch(),
AutocompleteMatch(), IDNA2008DeviationCharacter::kNone);
AutocompleteMatch());
nav_observer.Wait();
if (IsHttpsFirstModePrefEnabled() || IsIncognito()) {
@ -3446,7 +3446,7 @@ IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest,
http_url, nullptr, WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::NAVSUGGEST,
base::TimeTicks(), false, false, std::u16string(), AutocompleteMatch(),
AutocompleteMatch(), IDNA2008DeviationCharacter::kNone);
AutocompleteMatch());
nav_observer.Wait();
EXPECT_EQ(https_url, contents->GetLastCommittedURL());
@ -3482,7 +3482,7 @@ IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest,
http_url, nullptr, WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::URL_WHAT_YOU_TYPED,
base::TimeTicks(), false, true, std::u16string(), AutocompleteMatch(),
AutocompleteMatch(), IDNA2008DeviationCharacter::kNone);
AutocompleteMatch());
nav_observer.Wait();
// URL should not have been upgraded, and site should now be in the allowlist.

@ -703,7 +703,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NavigateFromOmniboxIntoNewTab) {
url2, nullptr, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::URL_WHAT_YOU_TYPED,
base::TimeTicks(), false, false, std::u16string(), AutocompleteMatch(),
AutocompleteMatch(), IDNA2008DeviationCharacter::kNone);
AutocompleteMatch());
// Make sure the second tab is selected.
EXPECT_EQ(1, browser()->tab_strip_model()->active_index());

@ -516,8 +516,7 @@ void ChromeOmniboxClient::OnAutocompleteAccept(
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
const AutocompleteMatch& alternative_nav_match) {
TRACE_EVENT("omnibox", "ChromeOmniboxClient::OnAutocompleteAccept", "text",
text, "match", match, "alternative_nav_match",
alternative_nav_match);
@ -532,17 +531,6 @@ void ChromeOmniboxClient::OnAutocompleteAccept(
auto navigation = chrome::OpenCurrentURL(browser_);
ChromeOmniboxNavigationObserver::Create(navigation.get(), profile_, text,
match, alternative_nav_match);
// If this navigation was typed by the user and the hostname contained an
// IDNA 2008 deviation character, record a UKM. See idn_spoof_checker.h
// for details about deviation characters.
if (deviation_char_in_hostname != IDNA2008DeviationCharacter::kNone) {
ukm::SourceId source_id = ukm::ConvertToSourceId(
navigation->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID);
ukm::builders::Navigation_IDNA2008Transition(source_id)
.SetCharacter(static_cast<int>(deviation_char_in_hostname))
.Record(ukm::UkmRecorder::Get());
}
}
#if BUILDFLAG(ENABLE_EXTENSIONS)

@ -113,8 +113,7 @@ class ChromeOmniboxClient final : public OmniboxClient {
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) override;
const AutocompleteMatch& alternative_nav_match) override;
void OnInputInProgress(bool in_progress) override;
void OnPopupVisibilityChanged(bool popup_is_open) override;
void OpenIphLink(GURL gurl) override;

@ -56,19 +56,17 @@ class OmniboxPedalImplementationsTest : public testing::Test {
InitPedals();
}
void OnAutocompleteAccept(
const GURL& destination_url,
TemplateURLRef::PostContent* post_content,
WindowOpenDisposition disposition,
ui::PageTransition transition,
AutocompleteMatchType::Type match_type,
base::TimeTicks match_selection_timestamp,
bool destination_url_entered_without_scheme,
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
void OnAutocompleteAccept(const GURL& destination_url,
TemplateURLRef::PostContent* post_content,
WindowOpenDisposition disposition,
ui::PageTransition transition,
AutocompleteMatchType::Type match_type,
base::TimeTicks match_selection_timestamp,
bool destination_url_entered_without_scheme,
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match) {
last_destination_url_ = destination_url;
}

@ -120,8 +120,7 @@ class RealboxOmniboxClient final : public OmniboxClient {
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) override;
const AutocompleteMatch& alternative_nav_match) override;
base::WeakPtr<OmniboxClient> AsWeakPtr() override;
void SetLensSearchboxClientForTesting( // IN-TEST
@ -299,8 +298,7 @@ void RealboxOmniboxClient::OnAutocompleteAccept(
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
const AutocompleteMatch& alternative_nav_match) {
if (lens_searchbox_client_) {
lens_searchbox_client_->OnSuggestionAccepted(
destination_url, match.type,

@ -10,22 +10,17 @@
#include "components/navigation_metrics/navigation_metrics.h"
#include <iterator>
#include <string>
#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/profile_metrics/browser_profile_type.h"
#include "components/url_formatter/url_formatter.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "url/url_features.h"
namespace navigation_metrics {
@ -71,68 +66,6 @@ const char* const kSchemeNames[] = {
static_assert(std::size(kSchemeNames) == static_cast<int>(Scheme::COUNT),
"kSchemeNames should have Scheme::COUNT elements");
// Returns the eTLD+1 of `hostname16`. Excludes private registries such as
// blogspot.com so that test.blogspot.com returns blogspot.com.
std::u16string GetEtldPlusOne16(const std::u16string& hostname16) {
std::string hostname = base::UTF16ToUTF8(hostname16);
DCHECK(!hostname.empty());
std::string etld_plus_one =
net::registry_controlled_domains::GetDomainAndRegistry(
hostname,
net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
if (etld_plus_one.empty()) {
etld_plus_one = hostname;
}
if (hostname == etld_plus_one) {
return hostname16;
}
// etld_plus_one is normalized and doesn't contain deviation characters so
// we can't use it for computations. Instead, manually extract the eTLD+1 from
// hostname16 using the same number of domain labels as etld_plus_one.
size_t label_count =
base::ranges::count(etld_plus_one.begin(), etld_plus_one.end(), '.') + 1;
// Replace non-standard separators with "." (U002E). Sometimes users may input
// non-standard separators, causing issues when splitting labels based on ".".
// This follows the Unicode IDNA spec:
// https://www.unicode.org/reports/tr46/#TableDerivationStep1
std::u16string separator_replaced_hostname;
base::ReplaceChars(hostname16, u"\uff0e\u3002\uff61", u".",
&separator_replaced_hostname);
// Keeping empty labels is necessary if there is a trailing dot, to make sure
// `label_count` matches the `labels16` vector. See crbug.com/1362507.
std::vector<std::u16string> labels16 =
base::SplitString(separator_replaced_hostname, u".",
base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
// If the canonicalized eTLD+1 has *more* labels than the full
// noncanonicalized hostname, then there are some unexpected characters in the
// noncanonicalized hostname (such as a user inputting %-encoded separators).
// For simplicity (there are limits on how many edge cases it is worth
// accounting for), just drop these cases and return early.
if (label_count > labels16.size()) {
return std::u16string();
}
size_t extra_label_count = labels16.size() - label_count;
labels16.erase(labels16.begin(), labels16.begin() + extra_label_count);
std::u16string noncanon_etld_plus_one = base::JoinString(labels16, u".");
// If the extracted non-canonicalized eTLD+1 doesn't match the canonicalized
// eTLD+1, then something is odd (e.g., mixed "." and "%2e" separators). Drop
// these cases to avoid emitting potentially incorrect metrics.
url::CanonHostInfo host_info;
if (net::CanonicalizeHost(base::UTF16ToUTF8(noncanon_etld_plus_one),
&host_info) != etld_plus_one) {
return std::u16string();
}
return noncanon_etld_plus_one;
}
} // namespace
Scheme GetScheme(const GURL& url) {
@ -183,26 +116,4 @@ void RecordOmniboxURLNavigation(const GURL& url) {
Scheme::COUNT);
}
IDNA2008DeviationCharacter RecordIDNA2008Metrics(
const std::u16string& hostname16) {
if (!url::IsRecordingIDNA2008Metrics()) {
return IDNA2008DeviationCharacter::kNone;
}
if (hostname16.empty()) {
return IDNA2008DeviationCharacter::kNone;
}
if (net::IsHostnameNonUnique(base::UTF16ToUTF8(hostname16))) {
return IDNA2008DeviationCharacter::kNone;
}
std::u16string etld_plus_one = GetEtldPlusOne16(hostname16);
if (etld_plus_one.empty()) {
return IDNA2008DeviationCharacter::kNone;
}
IDNA2008DeviationCharacter c =
url_formatter::GetDeviationCharacter(etld_plus_one);
UMA_HISTOGRAM_BOOLEAN("Navigation.HostnameHasDeviationCharacters",
c != IDNA2008DeviationCharacter::kNone);
return c;
}
} // namespace navigation_metrics

@ -5,10 +5,6 @@
#ifndef COMPONENTS_NAVIGATION_METRICS_NAVIGATION_METRICS_H_
#define COMPONENTS_NAVIGATION_METRICS_NAVIGATION_METRICS_H_
#include <string>
#include "components/url_formatter/spoof_checks/idna_metrics.h"
class GURL;
namespace profile_metrics {
@ -66,11 +62,6 @@ void RecordPrimaryMainFrameNavigation(
void RecordOmniboxURLNavigation(const GURL& url);
// Records metrics about deviation characters in `hostname`. `hostname` can
// be punycode or unicode and can have subdomains.
IDNA2008DeviationCharacter RecordIDNA2008Metrics(
const std::u16string& hostname);
} // namespace navigation_metrics
#endif // COMPONENTS_NAVIGATION_METRICS_NAVIGATION_METRICS_H_

@ -158,90 +158,4 @@ TEST(NavigationMetrics, MainFrameSameDocumentHasRTLDomainTrue) {
test.ExpectUniqueSample(kMainFrameHasRTLDomain, 1 /* true */, 1);
}
TEST(NavigationMetrics, RecordIDNA2008Metrics) {
static constexpr char kHistogram[] =
"Navigation.HostnameHasDeviationCharacters";
base::HistogramTester histograms;
// Shouldn't record metrics for non-unique hostnames.
RecordIDNA2008Metrics(u"faß.local");
histograms.ExpectTotalCount(kHistogram, 0);
// Shouldn't record deviation characters in subdomains.
RecordIDNA2008Metrics(u"faß.example.de");
histograms.ExpectTotalCount(kHistogram, 1);
histograms.ExpectBucketCount(kHistogram, false, 1);
histograms.ExpectBucketCount(kHistogram, true, 0);
// Shouldn't record deviation characters in subdomains of private registries.
RecordIDNA2008Metrics(u"faß.blogspot.com");
histograms.ExpectTotalCount(kHistogram, 2);
histograms.ExpectBucketCount(kHistogram, false, 2);
histograms.ExpectBucketCount(kHistogram, true, 0);
// Positive tests.
RecordIDNA2008Metrics(u"faß.de");
histograms.ExpectTotalCount(kHistogram, 3);
histograms.ExpectBucketCount(kHistogram, false, 2);
histograms.ExpectBucketCount(kHistogram, true, 1);
RecordIDNA2008Metrics(u"subdomain.faß.de");
histograms.ExpectTotalCount(kHistogram, 4);
histograms.ExpectBucketCount(kHistogram, false, 2);
histograms.ExpectBucketCount(kHistogram, true, 2);
// Should work well with non-standard separators
RecordIDNA2008Metrics(u"example。com");
histograms.ExpectTotalCount(kHistogram, 5);
histograms.ExpectBucketCount(kHistogram, false, 3);
histograms.ExpectBucketCount(kHistogram, true, 2);
RecordIDNA2008Metrics(u"subdomain。faß。de");
histograms.ExpectTotalCount(kHistogram, 6);
histograms.ExpectBucketCount(kHistogram, false, 3);
histograms.ExpectBucketCount(kHistogram, true, 3);
// Should drop edge cases like %-encoded separators (%2e is ".") and not
// record metrics.
RecordIDNA2008Metrics(u"subdomain%2efaß%2ede");
histograms.ExpectTotalCount(kHistogram, 6);
// Should drop edge cases where the label count check passes but the
// canonicalized eTLD+1 and non-canonicalized eTLD+1 have diverged. (This case
// should be rare and shouldn't cause crashes, but will result in potentially
// junk metrics being collected.)
RecordIDNA2008Metrics(u"abc.def.faß.example%2ecom");
histograms.ExpectTotalCount(kHistogram, 6);
}
// Regression test for crbug.com/1362507. Tests that the IDNA2008 metrics code
// correctly handles hostnames with trailing dots.
TEST(NavigationMetrics, RecordIDNA2008MetricsTrailingDots) {
static constexpr char kHistogram[] =
"Navigation.HostnameHasDeviationCharacters";
base::HistogramTester histograms;
// This would previously trigger the DCHECK in GetEtldPlusOne16(), or cause
// a crash in the std::vector::erase() call later in that function, because
// the canonicalized hostname has two dots and so the logic would calculate
// this as having three labels, but the noncanonicalized labels vector would
// only have two elements due to dropping the final empty string after the
// trailing dot.
RecordIDNA2008Metrics(u"googlé.com.");
histograms.ExpectTotalCount(kHistogram, 1);
// GetDomainAndRegistry() should return the empty string for this hostname,
// so no metrics will be recorded.
RecordIDNA2008Metrics(u"googlé.com..");
histograms.ExpectTotalCount(kHistogram, 1);
// Should be treated the same as the "googlé.com" case.
RecordIDNA2008Metrics(u".googlé.com");
histograms.ExpectTotalCount(kHistogram, 2);
// Should be treated the same as the "googlé.com." case.
RecordIDNA2008Metrics(u".googlé.com.");
histograms.ExpectTotalCount(kHistogram, 3);
}
} // namespace navigation_metrics

@ -142,6 +142,5 @@ void OmniboxAction::OpenURL(OmniboxAction::ExecutionContext& context,
context.match_selection_timestamp_,
/*destination_url_entered_without_scheme=*/false,
/*destination_url_entered_with_http_scheme=*/false, u"",
AutocompleteMatch(), AutocompleteMatch(),
IDNA2008DeviationCharacter::kNone);
AutocompleteMatch(), AutocompleteMatch());
}

@ -16,7 +16,6 @@
#include "components/omnibox/browser/autocomplete_match_type.h"
#include "components/omnibox/browser/buildflags.h"
#include "components/search_engines/template_url.h"
#include "components/url_formatter/spoof_checks/idna_metrics.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/color_utils.h"
@ -121,8 +120,7 @@ class OmniboxAction : public base::RefCountedThreadSafe<OmniboxAction> {
bool destination_url_entered_with_http_scheme,
const std::u16string&,
const AutocompleteMatch&,
const AutocompleteMatch&,
IDNA2008DeviationCharacter)>;
const AutocompleteMatch&)>;
ExecutionContext(Client& client,
OpenUrlCallback callback,

@ -16,7 +16,6 @@
#include "components/omnibox/browser/omnibox_navigation_observer.h"
#include "components/omnibox/common/omnibox_focus_state.h"
#include "components/security_state/core/security_state.h"
#include "components/url_formatter/spoof_checks/idna_metrics.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/page_transition_types.h"
@ -257,8 +256,7 @@ class OmniboxClient {
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) = 0;
const AutocompleteMatch& alternative_nav_match) = 0;
// Called when the input is accepted with a thumbnail and no user text. This
// is required because there is no verbatim match when the input is just an

@ -2571,8 +2571,6 @@ void OmniboxEditModel::OpenMatch(OmniboxPopupSelection selection,
now - last_omnibox_focus_);
}
IDNA2008DeviationCharacter deviation_char_in_hostname =
IDNA2008DeviationCharacter::kNone;
TemplateURLService* service = controller_->client()->GetTemplateURLService();
TemplateURL* template_url = match.GetTemplateURL(service, false);
if (template_url) {
@ -2626,24 +2624,6 @@ void OmniboxEditModel::OpenMatch(OmniboxPopupSelection selection,
ui::PageTransitionTypeIncludingQualifiersIs(match.transition,
ui::PAGE_TRANSITION_LINK)) {
net::cookie_util::RecordCookiePortOmniboxHistograms(destination_url);
if (destination_url.SchemeIsHTTPOrHTTPS()) {
// Extract the typed hostname from autocomplete input for IDNA 2008
// metrics. We can't use GURL here as it removes the deviation
// characters that we want to measure.
size_t hostname_begin = input_.parts().host.begin;
if (input_.added_default_scheme_to_typed_url() && hostname_begin > 0) {
// If the omnibox upgrades a navigation to https, it offsets
// components by one to the right due to the added "s" to http. Adjust
// the offset again. Ideally, hostname_begin should always be non-zero
// in that case, but we check it for safety.
--hostname_begin;
}
std::u16string hostname(input_.text(), hostname_begin,
static_cast<size_t>(input_.parts().host.len));
deviation_char_in_hostname =
navigation_metrics::RecordIDNA2008Metrics(hostname);
}
}
}
@ -2697,8 +2677,7 @@ void OmniboxEditModel::OpenMatch(OmniboxPopupSelection selection,
VerbatimMatchForInput(
autocomplete_controller()->history_url_provider(),
autocomplete_controller()->autocomplete_provider_client(),
alternate_input, alternate_nav_url, false),
deviation_char_in_hostname);
alternate_input, alternate_nav_url, false));
}
}
}

@ -391,7 +391,7 @@ TEST_F(OmniboxEditModelTest, AlternateNavHasHTTP) {
AutocompleteMatch alternate_nav_match;
EXPECT_CALL(*omnibox_client_,
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _, _))
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _))
.WillOnce(SaveArg<10>(&alternate_nav_match));
model()->OnSetFocus(false); // Avoids DCHECK in OpenMatch().
@ -402,7 +402,7 @@ TEST_F(OmniboxEditModelTest, AlternateNavHasHTTP) {
AutocompleteInput::HasHTTPScheme(alternate_nav_match.fill_into_edit));
EXPECT_CALL(*omnibox_client_,
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _, _))
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _))
.WillOnce(SaveArg<10>(&alternate_nav_match));
model()->SetUserText(u"abcd");
@ -1436,7 +1436,7 @@ TEST_F(OmniboxEditModelTest, OpenTabMatch) {
WindowOpenDisposition disposition;
EXPECT_CALL(*omnibox_client_,
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _, _))
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _))
.WillOnce(SaveArg<2>(&disposition));
model()->OnSetFocus(false); // Avoids DCHECK in OpenMatch().
@ -1446,7 +1446,7 @@ TEST_F(OmniboxEditModelTest, OpenTabMatch) {
EXPECT_EQ(disposition, WindowOpenDisposition::SWITCH_TO_TAB);
EXPECT_CALL(*omnibox_client_,
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _, _))
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _))
.WillOnce(SaveArg<2>(&disposition));
// Suggestions not from the Open Tab Provider or not from keyword mode should
@ -1457,7 +1457,7 @@ TEST_F(OmniboxEditModelTest, OpenTabMatch) {
EXPECT_EQ(disposition, WindowOpenDisposition::CURRENT_TAB);
EXPECT_CALL(*omnibox_client_,
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _, _))
OnAutocompleteAccept(_, _, _, _, _, _, _, _, _, _, _))
.WillOnce(SaveArg<2>(&disposition));
match.provider = controller()->autocomplete_controller()->search_provider();

@ -75,8 +75,7 @@ class TestOmniboxClient final : public testing::NiceMock<OmniboxClient> {
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname));
const AutocompleteMatch& alternative_nav_match));
MOCK_METHOD(bookmarks::BookmarkModel*, GetBookmarkModel, ());
MOCK_METHOD(PrefService*, GetPrefs, (), (override));
MOCK_METHOD(const PrefService*, GetPrefs, (), (const, override));

@ -110,8 +110,7 @@ class LensOmniboxClient final : public OmniboxClient {
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) override;
const AutocompleteMatch& alternative_nav_match) override;
void OnThumbnailOnlyAccept() override;
base::WeakPtr<OmniboxClient> AsWeakPtr() override;

@ -245,8 +245,7 @@ void LensOmniboxClient::OnAutocompleteAccept(
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
const AutocompleteMatch& alternative_nav_match) {
[delegate_ omniboxDidAcceptText:match.fill_into_edit
destinationURL:destination_url
textClobbered:text_clobbered_in_session_];

@ -60,8 +60,7 @@ class LensOmniboxClientTest : public PlatformTest {
lens_omnibox_client_->OnAutocompleteAccept(
match.destination_url, match.post_content.get(),
WindowOpenDisposition::CURRENT_TAB, match.transition, match.type,
base::TimeTicks(), false, false, input_text, match, match,
IDNA2008DeviationCharacter::kNone);
base::TimeTicks(), false, false, input_text, match, match);
}
protected:

@ -95,8 +95,7 @@ class ChromeOmniboxClientIOS final : public OmniboxClient,
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) override;
const AutocompleteMatch& alternative_nav_match) override;
base::WeakPtr<OmniboxClient> AsWeakPtr() override;
// web::WebStateObserver.

@ -280,8 +280,7 @@ void ChromeOmniboxClientIOS::OnAutocompleteAccept(
bool destination_url_entered_with_http_scheme,
const std::u16string& text,
const AutocompleteMatch& match,
const AutocompleteMatch& alternative_nav_match,
IDNA2008DeviationCharacter deviation_char_in_hostname) {
const AutocompleteMatch& alternative_nav_match) {
if (location_bar_->GetWebState()) {
web::WebState* web_state = location_bar_->GetWebState();
const int32_t web_state_id = web_state->GetUniqueIdentifier().identifier();

@ -132,8 +132,7 @@ void ChromeOmniboxClientIOSTest::UseAutocompleteMatch(
chrome_omnibox_client_ios_->OnAutocompleteAccept(
match.destination_url, match.post_content.get(),
WindowOpenDisposition::CURRENT_TAB, match.transition, match.type,
base::TimeTicks(), false, false, input_text, match, match,
IDNA2008DeviationCharacter::kNone);
base::TimeTicks(), false, false, input_text, match, match);
}
void ChromeOmniboxClientIOSTest::FinishCurrentNavigationSuccessfully() {

@ -3771,8 +3771,8 @@ enum WebFeature {
kFedCmUserInfo = 4426,
// The items above roughly this point are available in the M110 branch.
kIDNA2008DeviationCharacterInHostnameOfSubresource = 4427,
kIDNA2008DeviationCharacterInHostnameOfIFrame = 4428,
kOBSOLETE_IDNA2008DeviationCharacterInHostnameOfSubresource = 4427,
kOBSOLETE_IDNA2008DeviationCharacterInHostnameOfIFrame = 4428,
kWindowOpenPopupOnMobile = 4429,
kWindowOpenedAsPopupOnMobile = 4430,
kOBSOLETE_PrivateNetworkAccessIgnoredCrossOriginPreflightError = 4431,

@ -17,7 +17,6 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h"
#include "third_party/blink/renderer/core/loader/idna_util.h"
#include "third_party/blink/renderer/core/loader/subresource_filter.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@ -320,24 +319,6 @@ BaseFetchContext::CanRequestInternal(
}
}
// Warn if the resource URL's hostname contains IDNA deviation characters.
// Only warn if the resource URL's origin is different than its requestor
// (we don't want to warn for <img src="faß.de/image.img"> on faß.de).
// TODO(crbug.com/1396475): Remove once Non-Transitional mode is shipped.
if (url.HasIDNA2008DeviationCharacter() &&
!resource_request.RequestorOrigin()->IsSameOriginWith(
SecurityOrigin::Create(url).get())) {
String message = GetConsoleWarningForIDNADeviationCharacters(url);
if (!message.empty()) {
console_logger_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kWarning, message));
UseCounter::Count(
GetExecutionContext(),
WebFeature::kIDNA2008DeviationCharacterInHostnameOfSubresource);
}
}
return std::nullopt;
}

@ -11,8 +11,6 @@ blink_core_sources_loader = [
"back_forward_cache_loader_helper_impl.h",
"base_fetch_context.cc",
"base_fetch_context.h",
"idna_util.h",
"idna_util.cc",
"beacon_data.cc",
"beacon_data.h",
"cookie_jar.cc",

@ -94,7 +94,6 @@
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/loader/idleness_detector.h"
#include "third_party/blink/renderer/core/loader/idna_util.h"
#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
#include "third_party/blink/renderer/core/loader/navigation_policy.h"
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
@ -891,25 +890,6 @@ void FrameLoader::StartNavigation(FrameLoadRequest& request,
? CSPDisposition::DO_NOT_CHECK
: CSPDisposition::CHECK;
// Warn if the resource URL's hostname contains IDNA deviation characters.
// Only warn if the resource URL's origin is different than its requestor
// (we don't want to warn for <img src="faß.de/image.img"> on faß.de).
// TODO(crbug.com/1396475): Remove once Non-Transitional mode is shipped.
if (url.HasIDNA2008DeviationCharacter() &&
resource_request.RequestorOrigin() &&
!resource_request.RequestorOrigin()->IsSameOriginWith(
SecurityOrigin::Create(url).get())) {
String message = GetConsoleWarningForIDNADeviationCharacters(url);
if (!message.empty()) {
request.GetOriginWindow()->AddConsoleMessage(
MakeGarbageCollected<ConsoleMessage>(
mojom::ConsoleMessageSource::kSecurity,
mojom::ConsoleMessageLevel::kWarning, message));
origin_window->CountUse(
WebFeature::kIDNA2008DeviationCharacterInHostnameOfIFrame);
}
}
Client()->BeginNavigation(
resource_request, request.GetRequestorBaseURL(), request.GetFrameType(),
origin_window, nullptr /* document_loader */, navigation_type,

@ -1,95 +0,0 @@
// Copyright 2022 The Chromium Authors
// 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/core/loader/idna_util.h"
#include <unicode/idna.h>
#include "base/strings/utf_string_conversions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "url/url_features.h"
namespace {
// RFC5321 says the maximum total length of a domain name is 255 octets.
constexpr int32_t kMaximumDomainNameLengthForIDNADecoding = 255;
// Unsafely decodes a punycode hostname to unicode (e.g. xn--fa-hia.de to
// faß.de). Only used for logging. Doesn't do any spoof checks on the output,
// so the output MUST NOT be used for anything else.
String UnsafeASCIIToIDNA(const StringView& hostname_ascii) {
static UIDNA* uidna = [] {
UErrorCode err = U_ZERO_ERROR;
UIDNA* value =
uidna_openUTS46(UIDNA_CHECK_BIDI | UIDNA_NONTRANSITIONAL_TO_ASCII |
UIDNA_NONTRANSITIONAL_TO_UNICODE,
&err);
if (U_FAILURE(err)) {
value = nullptr;
}
return value;
}();
if (!uidna) {
return String();
}
DCHECK(hostname_ascii.ContainsOnlyASCIIOrEmpty());
UErrorCode status = U_ZERO_ERROR;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
Vector<char> output_utf8(
static_cast<wtf_size_t>(kMaximumDomainNameLengthForIDNADecoding), '\0');
StringUTF8Adaptor hostname(hostname_ascii);
// This returns the actual length required. If processing fails, info.errors
// will be nonzero. `status` indicates an error only in exceptional cases,
// such as a U_MEMORY_ALLOCATION_ERROR.
int32_t output_utf8_length = uidna_nameToUnicodeUTF8(
uidna, hostname.data(), static_cast<int32_t>(hostname.size()),
output_utf8.data(), output_utf8.size(), &info, &status);
if (U_FAILURE(status) || info.errors != 0 ||
output_utf8_length > kMaximumDomainNameLengthForIDNADecoding) {
return String();
}
return String::FromUTF8(
base::as_byte_span(output_utf8)
.first(base::checked_cast<size_t>(output_utf8_length)));
}
} // namespace
namespace blink {
String GetConsoleWarningForIDNADeviationCharacters(const KURL& url) {
if (!url::IsRecordingIDNA2008Metrics()) {
return String();
}
// `url` is canonicalized to ASCII (i.e. punycode). First decode it to unicode
// then check for deviation characters.
String host = UnsafeASCIIToIDNA(url.Host());
if (!host.Contains(u"\u00DF") && // Sharp-s
!host.Contains(u"\u03C2") && // Greek final sigma
!host.Contains(u"\u200D") && // Zero width joiner
!host.Contains(u"\u200C")) { // Zero width non-joiner
return String();
}
String elided = url.ElidedString().replace(
url.HostStart(), url.HostEnd() - url.HostStart(), host);
StringBuilder message;
message.Append("The resource at ");
message.Append(elided);
message.Append(
" contains IDNA Deviation Characters. The hostname for this URL (");
message.Append(host);
message.Append(
") might point to a different IP address after "
"https://chromestatus.com/feature/5105856067141632. Make sure you are "
"using the correct host name.");
return message.ToString();
}
} // namespace blink

@ -1,19 +0,0 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDNA_UTIL_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDNA_UTIL_H_
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
// Returns a console message if the hostname of `url` contains IDNA 2008
// deviation characters. Returns empty string otherwise.
String GetConsoleWarningForIDNADeviationCharacters(const KURL& url);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDNA_UTIL_H_

@ -1,9 +0,0 @@
CONSOLE WARNING: The resource at http://faß.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://βόλος.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://ශ්‍රී.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (ශ්‍රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://نامه‌ای.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (نامه‌ای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://faß.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://βόλος.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://ශ්‍රී.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (ශ්‍රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://نامه‌ای.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (نامه‌ای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
t

@ -1,5 +0,0 @@
CONSOLE WARNING: The resource at http://faß.test/ contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://βόλος.test/ contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://ශ්‍රී.test/ contains IDNA Deviation Characters. The hostname for this URL (ශ්‍රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.
CONSOLE WARNING: The resource at http://نامه‌ای.test/ contains IDNA Deviation Characters. The hostname for this URL (نامه‌ای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name.

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<script>
if (window.testRunner)
testRunner.dumpAsText();
</script>
</head>
<body>
<!-- Frame with a non-ASCII hostname -->
<iframe src="http://èxample.test/"></iframe>
<!-- Frame with a hostname containing IDNA 2008 deviation character (Sharp-s) -->
<iframe src="http://faß.test"></iframe>
<!-- Frame with a hostname containing IDNA 2008 deviation character (Greek Final Sigma). -->
<iframe src="http://βόλος.test"></iframe>
<!-- Frame with a hostname containing IDNA 2008 deviation character (Zero Width Joiner) -->
<iframe src="http://ශ්‍රී.test"></iframe>
<!-- Frame with a hostname containing IDNA 2008 deviation character (Zero Width Non-Joiner) -->
<iframe src="http://نامه‌ای.test"></iframe>
</body>
</html>

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<script>
if (window.testRunner)
testRunner.dumpAsText();
</script>
</head>
<body>
<!-- Image with a non-ASCII hostname -->
<img src="http://èxample.test/image.jpg">
<!-- Image with a hostname containing IDNA 2008 deviation character (Sharp-s) -->
<img src="http://faß.test/image.jpg">
<!-- Image with a hostname containing IDNA 2008 deviation character (Greek Final Sigma). -->
<img src="http://βόλος.test/image.jpg">
<!-- Image with a hostname containing IDNA 2008 deviation character (Zero Width Joiner) -->
<img src="http://ශ්‍රී.test/image.jpg">
<!-- Image with a hostname containing IDNA 2008 deviation character (Zero Width Non-Joiner) -->
<img src="http://نامه‌ای.test/image.jpg">
</body>
</html>t

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<script>
if (window.testRunner)
testRunner.dumpAsText();
</script>
</head>
<body>
<!-- An image containing IDNA 2008 deviation character in the path. -->
<img src="http://example.test/faß.jpg">
</body>
</html>

@ -10039,8 +10039,10 @@ Called by update_use_counter_feature_enum.py.-->
label="OBSOLETE_DialogCloseWatcherCloseSignalClosedMultiple"/>
<int value="4425" label="NoVarySearch"/>
<int value="4426" label="FedCmUserInfo"/>
<int value="4427" label="IDNA2008DeviationCharacterInHostnameOfSubresource"/>
<int value="4428" label="IDNA2008DeviationCharacterInHostnameOfIFrame"/>
<int value="4427"
label="OBSOLETE_IDNA2008DeviationCharacterInHostnameOfSubresource"/>
<int value="4428"
label="OBSOLETE_IDNA2008DeviationCharacterInHostnameOfIFrame"/>
<int value="4429" label="WindowOpenPopupOnMobile"/>
<int value="4430" label="WindowOpenedAsPopupOnMobile"/>
<int value="4431"

@ -11,11 +11,6 @@ BASE_FEATURE(kUseIDNA2008NonTransitional,
"UseIDNA2008NonTransitional",
base::FEATURE_ENABLED_BY_DEFAULT);
// Kill switch for crbug.com/1362507.
BASE_FEATURE(kRecordIDNA2008Metrics,
"RecordIDNA2008Metrics",
base::FEATURE_ENABLED_BY_DEFAULT);
// Kill switch for crbug.com/1416006.
BASE_FEATURE(kStandardCompliantNonSpecialSchemeURLParsing,
"StandardCompliantNonSpecialSchemeURLParsing",
@ -47,10 +42,6 @@ bool IsUsingStandardCompliantNonSpecialSchemeURLParsing() {
kStandardCompliantNonSpecialSchemeURLParsing);
}
bool IsRecordingIDNA2008Metrics() {
return base::FeatureList::IsEnabled(kRecordIDNA2008Metrics);
}
bool IsDisallowingSpaceCharacterInURLHostParsing() {
// If the FeatureList isn't available yet, fall back to the feature's default
// state. This may happen during early startup, see crbug.com/1441956.

@ -20,9 +20,6 @@ COMPONENT_EXPORT(URL) BASE_DECLARE_FEATURE(kUseIDNA2008NonTransitional);
// Returns true if Chrome is using IDNA 2008 in Non-Transitional mode.
COMPONENT_EXPORT(URL) bool IsUsingIDNA2008NonTransitional();
// Returns true if Chrome is recording IDNA 2008 related metrics.
COMPONENT_EXPORT(URL) bool IsRecordingIDNA2008Metrics();
// Returns true if kStandardCompliantNonSpecialSchemeURLParsing feature is
// enabled. See url::kStandardCompliantNonSpecialSchemeURLParsing for details.
COMPONENT_EXPORT(URL) bool IsUsingStandardCompliantNonSpecialSchemeURLParsing();