From 403eaca951ca14a7b1504ec6eea77c9c204e1771 Mon Sep 17 00:00:00 2001 From: Carlos IL Date: Tue, 30 May 2023 18:10:43 +0000 Subject: [PATCH] Opt-out URLs typed with http scheme from https upgrades. This only opts out cases where the full http url was typed (e.g. typing http://examp and then choosing example.com from the suggestions will still result in an upgrade, as will navigating to an http url via an http bookmark). Plumbing for the new flag is somewhat duplicated with added_default_scheme_to_typed_url. This was on purpose (rather than adding a multi-state flag) since schemeless typed navigations upgrades (and thus the added_default_scheme_to_typed_url) will be obsolete when https upgrades fully launch. Change-Id: I86c4f487b79aa3b4705f2345ddc25ca22a8b4eb4 (cherry picked from commit 67cf5a9109bdc385e81e4e17ea91e8850d78d244) Bug: 1447921 Change-Id: I86c4f487b79aa3b4705f2345ddc25ca22a8b4eb4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4549863 Reviewed-by: Robbie Gibson Reviewed-by: Tommy Nyquist Reviewed-by: Tommy Li Reviewed-by: Chris Thompson Commit-Queue: Carlos IL Cr-Original-Commit-Position: refs/heads/main@{#1149342} Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4575041 Auto-Submit: Carlos IL Commit-Queue: Tommy Li Reviewed-by: Avi Drissman Cr-Commit-Position: refs/branch-heads/5790@{#138} Cr-Branched-From: 1d71a337b1f6e707a13ae074dca1e2c34905eb9f-refs/heads/main@{#1148114} --- .../browser/chrome_content_browser_client.cc | 3 +- .../chrome_navigation_ui_data.cc | 6 +- .../renderer_host/chrome_navigation_ui_data.h | 11 ++- .../browser/ssl/https_upgrades_browsertest.cc | 68 +++++++++++++++++++ .../browser/ssl/https_upgrades_interceptor.cc | 26 +++++-- .../browser/ssl/https_upgrades_interceptor.h | 9 ++- chrome/browser/ui/browser_commands.cc | 2 + chrome/browser/ui/browser_focus_uitest.cc | 2 +- chrome/browser/ui/browser_navigator.cc | 3 +- chrome/browser/ui/browser_navigator_params.h | 4 ++ chrome/browser/ui/location_bar/location_bar.h | 1 + .../chrome_omnibox_edit_model_delegate.cc | 3 + .../chrome_omnibox_edit_model_delegate.h | 1 + .../views/location_bar/location_bar_view.cc | 4 ++ .../ui/views/location_bar/location_bar_view.h | 1 + .../ui/webui/realbox/realbox_handler.cc | 3 + .../ui/webui/realbox/realbox_handler.h | 1 + chrome/test/base/test_browser_window.cc | 4 ++ chrome/test/base/test_browser_window.h | 1 + .../omnibox/browser/actions/omnibox_action.cc | 3 +- .../omnibox/browser/actions/omnibox_action.h | 1 + .../omnibox/browser/autocomplete_input.cc | 8 ++- .../omnibox/browser/autocomplete_input.h | 5 +- .../browser/autocomplete_input_unittest.cc | 38 +++++++++++ .../omnibox/browser/omnibox_edit_model.cc | 5 +- .../browser/omnibox_edit_model_delegate.h | 7 +- .../test_omnibox_edit_model_delegate.cc | 3 + .../test_omnibox_edit_model_delegate.h | 1 + .../web_omnibox_edit_model_delegate_impl.h | 1 + .../web_omnibox_edit_model_delegate_impl.mm | 1 + 30 files changed, 209 insertions(+), 17 deletions(-) diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 1b9db89f8dce3..dc9912b1dda9d 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -6006,7 +6006,8 @@ ChromeContentBrowserClient::WillCreateURLLoaderRequestInterceptors( if (base::FeatureList::IsEnabled(features::kHttpsFirstModeV2)) { auto https_upgrades_interceptor = - HttpsUpgradesInterceptor::MaybeCreateInterceptor(frame_tree_node_id); + HttpsUpgradesInterceptor::MaybeCreateInterceptor(frame_tree_node_id, + navigation_ui_data); if (https_upgrades_interceptor) { interceptors.push_back(std::move(https_upgrades_interceptor)); } diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc index d42f16620a11f..918c35b78ef61 100644 --- a/chrome/browser/renderer_host/chrome_navigation_ui_data.cc +++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.cc @@ -53,11 +53,14 @@ std::unique_ptr ChromeNavigationUIData::CreateForMainFrameNavigation( content::WebContents* web_contents, WindowOpenDisposition disposition, - bool is_using_https_as_default_scheme) { + bool is_using_https_as_default_scheme, + bool url_is_typed_with_http_scheme) { auto navigation_ui_data = std::make_unique(); navigation_ui_data->disposition_ = disposition; navigation_ui_data->is_using_https_as_default_scheme_ = is_using_https_as_default_scheme; + navigation_ui_data->url_is_typed_with_http_scheme_ = + url_is_typed_with_http_scheme; #if BUILDFLAG(ENABLE_EXTENSIONS) int tab_id = extension_misc::kUnknownTabId; @@ -81,6 +84,7 @@ std::unique_ptr ChromeNavigationUIData::Clone() { copy->disposition_ = disposition_; copy->is_using_https_as_default_scheme_ = is_using_https_as_default_scheme_; + copy->url_is_typed_with_http_scheme_ = url_is_typed_with_http_scheme_; #if BUILDFLAG(ENABLE_EXTENSIONS) if (extension_data_) diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.h b/chrome/browser/renderer_host/chrome_navigation_ui_data.h index 9b1e3b6664b2b..26a3b54de11eb 100644 --- a/chrome/browser/renderer_host/chrome_navigation_ui_data.h +++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.h @@ -49,7 +49,8 @@ class ChromeNavigationUIData : public content::NavigationUIData { static std::unique_ptr CreateForMainFrameNavigation( content::WebContents* web_contents, WindowOpenDisposition disposition, - bool is_using_https_as_default_scheme); + bool is_using_https_as_default_scheme, + bool url_is_typed_with_http_scheme); // Creates a new ChromeNavigationUIData that is a deep copy of the original. // Any changes to the original after the clone is created will not be @@ -83,6 +84,9 @@ class ChromeNavigationUIData : public content::NavigationUIData { bool is_using_https_as_default_scheme() const { return is_using_https_as_default_scheme_; } + bool url_is_typed_with_http_scheme() const { + return url_is_typed_with_http_scheme_; + } absl::optional bookmark_id() { return bookmark_id_; } void set_bookmark_id(absl::optional id) { bookmark_id_ = id; } @@ -109,6 +113,11 @@ class ChromeNavigationUIData : public content::NavigationUIData { // observed and fall back to using http scheme if necessary. bool is_using_https_as_default_scheme_ = false; + // True if the navigation was initiated by typing in the omnibox, and the + // typed text had an explicit http scheme. This is used to opt-out of https + // upgrades. + bool url_is_typed_with_http_scheme_ = false; + // Id of the bookmark which started this navigation. absl::optional bookmark_id_ = absl::nullopt; }; diff --git a/chrome/browser/ssl/https_upgrades_browsertest.cc b/chrome/browser/ssl/https_upgrades_browsertest.cc index 32d0ea51dfd77..0a240a51ad9cd 100644 --- a/chrome/browser/ssl/https_upgrades_browsertest.cc +++ b/chrome/browser/ssl/https_upgrades_browsertest.cc @@ -20,10 +20,15 @@ #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/omnibox/browser/omnibox_edit_model.h" +#include "components/omnibox/browser/omnibox_edit_model_delegate.h" +#include "components/omnibox/browser/omnibox_view.h" #include "components/prefs/pref_service.h" #include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h" #include "components/security_interstitials/core/https_only_mode_metrics.h" @@ -1990,6 +1995,69 @@ IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest, contents)); } +// Tests that URLs typed with an explicit http:// scheme are opted out from +// upgrades. +IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest, + URLsTypedWithHttpSchemeNoUpgrades) { + if (!IsHttpUpgradingEnabled()) { + return; + } + GURL http_url = http_server()->GetURL("foo.com", "/simple.html"); + GURL https_url = https_server()->GetURL("foo.com", "/simple.html"); + auto* contents = browser()->tab_strip_model()->GetActiveWebContents(); + OmniboxEditModelDelegate* edit_model_delegate = browser() + ->window() + ->GetLocationBar() + ->GetOmniboxView() + ->model() + ->delegate(); + + // Simulate the full URL was typed with an http scheme. + content::TestNavigationObserver nav_observer(contents, 1); + edit_model_delegate->OnAutocompleteAccept( + 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); + nav_observer.Wait(); + + if (IsHttpsFirstModePrefEnabled()) { + // Typed http URLs don't opt out of upgrades in HFM. + EXPECT_EQ(https_url, contents->GetLastCommittedURL()); + } else { + EXPECT_EQ(http_url, contents->GetLastCommittedURL()); + } +} + +// Tests that URLs with an explicit http:// scheme are upgraded if they were +// autocompleted. +IN_PROC_BROWSER_TEST_P(HttpsUpgradesBrowserTest, + URLsAutocompletedWithHttpSchemeAreUpgraded) { + if (!IsHttpUpgradingEnabled()) { + return; + } + GURL http_url = http_server()->GetURL("foo.com", "/simple.html"); + GURL https_url = https_server()->GetURL("foo.com", "/simple.html"); + auto* contents = browser()->tab_strip_model()->GetActiveWebContents(); + OmniboxEditModelDelegate* edit_model_delegate = browser() + ->window() + ->GetLocationBar() + ->GetOmniboxView() + ->model() + ->delegate(); + + // Simulate the full URL was autocompleted with an http scheme. + content::TestNavigationObserver nav_observer(contents, 1); + edit_model_delegate->OnAutocompleteAccept( + http_url, nullptr, WindowOpenDisposition::CURRENT_TAB, + ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::NAVSUGGEST, + base::TimeTicks(), false, false, std::u16string(), AutocompleteMatch(), + AutocompleteMatch(), IDNA2008DeviationCharacter::kNone); + nav_observer.Wait(); + + EXPECT_EQ(https_url, contents->GetLastCommittedURL()); +} + // A simple test fixture that ensures the kHttpsFirstModeV2 feature is enabled // and constructs a HistogramTester (so that it gets initialized before browser // startup). Used for testing pref tracking logic. diff --git a/chrome/browser/ssl/https_upgrades_interceptor.cc b/chrome/browser/ssl/https_upgrades_interceptor.cc index c5df6e8fbad07..a6f19379f66f4 100644 --- a/chrome/browser/ssl/https_upgrades_interceptor.cc +++ b/chrome/browser/ssl/https_upgrades_interceptor.cc @@ -11,6 +11,7 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" #include "chrome/browser/ssl/https_only_mode_tab_helper.h" #include "chrome/browser/ssl/https_upgrades_util.h" #include "chrome/common/chrome_features.h" @@ -157,7 +158,9 @@ using security_interstitials::https_only_mode::NavigationRequestSecurityLevel; // static std::unique_ptr -HttpsUpgradesInterceptor::MaybeCreateInterceptor(int frame_tree_node_id) { +HttpsUpgradesInterceptor::MaybeCreateInterceptor( + int frame_tree_node_id, + content::NavigationUIData* navigation_ui_data) { auto* web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); // Could be null if the FrameTreeNode's RenderFrameHost is shutting down. @@ -175,15 +178,17 @@ HttpsUpgradesInterceptor::MaybeCreateInterceptor(int frame_tree_node_id) { bool https_first_mode_enabled = base::FeatureList::IsEnabled(features::kHttpsFirstModeV2) && prefs && prefs->GetBoolean(prefs::kHttpsOnlyModeEnabled); - return std::make_unique(frame_tree_node_id, - https_first_mode_enabled); + return std::make_unique( + frame_tree_node_id, https_first_mode_enabled, navigation_ui_data); } HttpsUpgradesInterceptor::HttpsUpgradesInterceptor( int frame_tree_node_id, - bool http_interstitial_enabled_by_pref) + bool http_interstitial_enabled_by_pref, + content::NavigationUIData* navigation_ui_data) : frame_tree_node_id_(frame_tree_node_id), - http_interstitial_enabled_by_pref_(http_interstitial_enabled_by_pref) {} + http_interstitial_enabled_by_pref_(http_interstitial_enabled_by_pref), + navigation_ui_data_(navigation_ui_data) {} HttpsUpgradesInterceptor::~HttpsUpgradesInterceptor() = default; @@ -286,6 +291,17 @@ void HttpsUpgradesInterceptor::MaybeCreateLoader( } } + // If the URL was typed with an explicit http:// URL, it is opted-out from + // upgrades. + ChromeNavigationUIData* chrome_navigation_ui_data = + static_cast(navigation_ui_data_); + if (chrome_navigation_ui_data && + chrome_navigation_ui_data->url_is_typed_with_http_scheme() && + !IsInterstitialEnabled(*interstitial_state_)) { + std::move(callback).Run({}); + return; + } + // Check whether this host would be upgraded to HTTPS by HSTS. This requires a // Mojo call to the network service, so set up a callback to continue the rest // of the MaybeCreateLoader() logic (passing along the necessary state). The diff --git a/chrome/browser/ssl/https_upgrades_interceptor.h b/chrome/browser/ssl/https_upgrades_interceptor.h index 3c665817d2aed..9d3a4a9a01b3b 100644 --- a/chrome/browser/ssl/https_upgrades_interceptor.h +++ b/chrome/browser/ssl/https_upgrades_interceptor.h @@ -30,6 +30,7 @@ class ThrottlingURLLoader; namespace content { class BrowserContext; +class NavigationUIData; class WebContents; } // namespace content @@ -47,10 +48,12 @@ class HttpsUpgradesInterceptor : public content::URLLoaderRequestInterceptor, public network::mojom::URLLoader { public: static std::unique_ptr MaybeCreateInterceptor( - int frame_tree_node_id); + int frame_tree_node_id, + content::NavigationUIData* navigation_ui_data_); HttpsUpgradesInterceptor(int frame_tree_node_id, - bool http_interstitial_enabled); + bool http_interstitial_enabled, + content::NavigationUIData* navigation_ui_data_); ~HttpsUpgradesInterceptor() override; HttpsUpgradesInterceptor(const HttpsUpgradesInterceptor&) = delete; @@ -142,6 +145,8 @@ class HttpsUpgradesInterceptor : public content::URLLoaderRequestInterceptor, // The owning client. Used for serving redirects. mojo::Remote client_; + // Owned by NavigationURLLoaderImpl, which should outlive the interceptor. + raw_ptr navigation_ui_data_; SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory weak_factory_{this}; diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index ff56bd10a2328..d6f9d1afb5a44 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc @@ -774,6 +774,8 @@ base::WeakPtr OpenCurrentURL(Browser* browser) { params.input_start = location_bar->GetMatchSelectionTimestamp(); params.is_using_https_as_default_scheme = location_bar->IsInputTypedUrlWithoutScheme(); + params.url_typed_with_http_scheme = + location_bar->IsInputTypedUrlWithHttpScheme(); auto result = Navigate(¶ms); #if BUILDFLAG(ENABLE_EXTENSIONS) diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc index 738b36225daf0..53594bb157007 100644 --- a/chrome/browser/ui/browser_focus_uitest.cc +++ b/chrome/browser/ui/browser_focus_uitest.cc @@ -637,7 +637,7 @@ IN_PROC_BROWSER_TEST_F(BrowserFocusTest, NavigateFromOmniboxIntoNewTab) { edit_model_delegate->OnAutocompleteAccept( url2, nullptr, WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_TYPED, AutocompleteMatchType::URL_WHAT_YOU_TYPED, - base::TimeTicks(), false, std::u16string(), AutocompleteMatch(), + base::TimeTicks(), false, false, std::u16string(), AutocompleteMatch(), AutocompleteMatch(), IDNA2008DeviationCharacter::kNone); // Make sure the second tab is selected. diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index edf4d8c7933e9..a45328dab1538 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc @@ -472,7 +472,8 @@ base::WeakPtr LoadURLInContents( load_url_params.navigation_ui_data = ChromeNavigationUIData::CreateForMainFrameNavigation( target_contents, params->disposition, - params->is_using_https_as_default_scheme); + params->is_using_https_as_default_scheme, + params->url_typed_with_http_scheme); } if (params->post_data) { diff --git a/chrome/browser/ui/browser_navigator_params.h b/chrome/browser/ui/browser_navigator_params.h index 86fb3e8eb6cf4..a2b9bd421ba76 100644 --- a/chrome/browser/ui/browser_navigator_params.h +++ b/chrome/browser/ui/browser_navigator_params.h @@ -340,6 +340,10 @@ struct NavigateParams { // observed and fall back to using http scheme if necessary. bool is_using_https_as_default_scheme = false; + // True if the navigation was initiated by typing in the omnibox and the typed + // text had an explicit http scheme. + bool url_typed_with_http_scheme = false; + // Indicates if the page load occurs during a non-optimal performance state. // This value is only suggested based upon the load context, and can be // overridden by other factors. diff --git a/chrome/browser/ui/location_bar/location_bar.h b/chrome/browser/ui/location_bar/location_bar.h index 23299773c7548..4cf26ec5f1900 100644 --- a/chrome/browser/ui/location_bar/location_bar.h +++ b/chrome/browser/ui/location_bar/location_bar.h @@ -32,6 +32,7 @@ class LocationBar { virtual ui::PageTransition GetPageTransition() const = 0; virtual base::TimeTicks GetMatchSelectionTimestamp() const = 0; virtual bool IsInputTypedUrlWithoutScheme() const = 0; + virtual bool IsInputTypedUrlWithHttpScheme() const = 0; // Focuses the location bar. User-initiated focuses (like pressing Ctrl+L) // should have |is_user_initiated| set to true. In those cases, we want to diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.cc b/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.cc index d31a48f124317..4ea8cc4ce0447 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.cc @@ -41,6 +41,7 @@ void ChromeOmniboxEditModelDelegate::OnAutocompleteAccept( 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, @@ -56,6 +57,8 @@ void ChromeOmniboxEditModelDelegate::OnAutocompleteAccept( match_selection_timestamp_ = match_selection_timestamp; destination_url_entered_without_scheme_ = destination_url_entered_without_scheme; + destination_url_entered_with_http_scheme_ = + destination_url_entered_with_http_scheme; if (browser_) { auto navigation = chrome::OpenCurrentURL(browser_); diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.h b/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.h index aeb404b7c7737..56e4fcfb4d212 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.h +++ b/chrome/browser/ui/omnibox/chrome_omnibox_edit_model_delegate.h @@ -37,6 +37,7 @@ class ChromeOmniboxEditModelDelegate : public OmniboxEditModelDelegate { AutocompleteMatchType::Type 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, diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 7679dc35c4265..fd23e864d0df4 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc @@ -1162,6 +1162,10 @@ bool LocationBarView::IsInputTypedUrlWithoutScheme() const { return destination_url_entered_without_scheme(); } +bool LocationBarView::IsInputTypedUrlWithHttpScheme() const { + return destination_url_entered_with_http_scheme(); +} + WindowOpenDisposition LocationBarView::GetWindowOpenDisposition() const { return disposition(); } diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index 5817354f6efbb..609ce268ada17 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h @@ -319,6 +319,7 @@ class LocationBarView : public LocationBar, // LocationBar: GURL GetDestinationURL() const override; bool IsInputTypedUrlWithoutScheme() const override; + bool IsInputTypedUrlWithHttpScheme() const override; WindowOpenDisposition GetWindowOpenDisposition() const override; ui::PageTransition GetPageTransition() const override; base::TimeTicks GetMatchSelectionTimestamp() const override; diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.cc b/chrome/browser/ui/webui/realbox/realbox_handler.cc index b78a671fee759..636d09a06c891 100644 --- a/chrome/browser/ui/webui/realbox/realbox_handler.cc +++ b/chrome/browser/ui/webui/realbox/realbox_handler.cc @@ -882,6 +882,7 @@ void RealboxHandler::OnAutocompleteAccept( 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, @@ -893,6 +894,8 @@ void RealboxHandler::OnAutocompleteAccept( match_selection_timestamp_ = match_selection_timestamp; destination_url_entered_without_scheme_ = destination_url_entered_without_scheme; + destination_url_entered_with_http_scheme_ = + destination_url_entered_with_http_scheme; web_contents_->OpenURL(content::OpenURLParams( destination_url_, content::Referrer(), disposition_, transition_, false)); diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.h b/chrome/browser/ui/webui/realbox/realbox_handler.h index 9e4100eb6b2bb..e2aa1e201d7d4 100644 --- a/chrome/browser/ui/webui/realbox/realbox_handler.h +++ b/chrome/browser/ui/webui/realbox/realbox_handler.h @@ -112,6 +112,7 @@ class RealboxHandler : public omnibox::mojom::PageHandler, 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, diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc index d2cf8b3961b5e..0c70708b9e1cc 100644 --- a/chrome/test/base/test_browser_window.cc +++ b/chrome/test/base/test_browser_window.cc @@ -73,6 +73,10 @@ bool TestBrowserWindow::TestLocationBar::IsInputTypedUrlWithoutScheme() const { return false; } +bool TestBrowserWindow::TestLocationBar::IsInputTypedUrlWithHttpScheme() const { + return false; +} + // TestBrowserWindow ---------------------------------------------------------- TestBrowserWindow::TestBrowserWindow() {} diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 270bf5617405d..3d67e3f58da6b 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -289,6 +289,7 @@ class TestBrowserWindow : public BrowserWindow { // LocationBar: GURL GetDestinationURL() const override; bool IsInputTypedUrlWithoutScheme() const override; + bool IsInputTypedUrlWithHttpScheme() const override; WindowOpenDisposition GetWindowOpenDisposition() const override; ui::PageTransition GetPageTransition() const override; base::TimeTicks GetMatchSelectionTimestamp() const override; diff --git a/components/omnibox/browser/actions/omnibox_action.cc b/components/omnibox/browser/actions/omnibox_action.cc index 0bb1aa36de66b..0a518a59eee3f 100644 --- a/components/omnibox/browser/actions/omnibox_action.cc +++ b/components/omnibox/browser/actions/omnibox_action.cc @@ -131,7 +131,8 @@ void OmniboxAction::OpenURL(OmniboxAction::ExecutionContext& context, .Run(url, nullptr, context.disposition_, ui::PAGE_TRANSITION_GENERATED, /*match_type=*/AutocompleteMatchType::URL_WHAT_YOU_TYPED, context.match_selection_timestamp_, - /*destination_url_entered_without_scheme=*/false, u"", + /*destination_url_entered_without_scheme=*/false, + /*destination_url_entered_with_http_scheme=*/false, u"", AutocompleteMatch(), AutocompleteMatch(), IDNA2008DeviationCharacter::kNone); } diff --git a/components/omnibox/browser/actions/omnibox_action.h b/components/omnibox/browser/actions/omnibox_action.h index ec9f8b5b3ff04..89afc68827e57 100644 --- a/components/omnibox/browser/actions/omnibox_action.h +++ b/components/omnibox/browser/actions/omnibox_action.h @@ -115,6 +115,7 @@ class OmniboxAction : public base::RefCounted { 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&, const AutocompleteMatch&, const AutocompleteMatch&, diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc index 759495f7e3494..3900b74d4b95c 100644 --- a/components/omnibox/browser/autocomplete_input.cc +++ b/components/omnibox/browser/autocomplete_input.cc @@ -7,6 +7,7 @@ #include #include "base/logging.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" @@ -183,7 +184,12 @@ void AutocompleteInput::Init( PopulateTermsPrefixedByHttpOrHttps(text_, &terms_prefixed_by_http_or_https_); DCHECK(!added_default_scheme_to_typed_url_); - + typed_url_had_http_scheme_ = + base::StartsWith(text, + base::ASCIIToUTF16(base::StrCat( + {url::kHttpScheme, url::kStandardSchemeSeparator})), + base::CompareCase::INSENSITIVE_ASCII) && + canonicalized_url.SchemeIs(url::kHttpScheme); GURL upgraded_url; if (should_use_https_as_default_scheme_ && type_ == metrics::OmniboxInputType::URL && diff --git a/components/omnibox/browser/autocomplete_input.h b/components/omnibox/browser/autocomplete_input.h index 364c7fc06782a..58ead1cbf4b0f 100644 --- a/components/omnibox/browser/autocomplete_input.h +++ b/components/omnibox/browser/autocomplete_input.h @@ -294,6 +294,8 @@ class AutocompleteInput { return added_default_scheme_to_typed_url_; } + bool typed_url_had_http_scheme() const { return typed_url_had_http_scheme_; } + void WriteIntoTrace(perfetto::TracedValue context) const; // Returns true if in zero prefix input state. @@ -334,7 +336,8 @@ class AutocompleteInput { // Flags for OmniboxDefaultNavigationsToHttps feature. bool should_use_https_as_default_scheme_; - bool added_default_scheme_to_typed_url_; + bool added_default_scheme_to_typed_url_ = false; + bool typed_url_had_http_scheme_ = false; // Port used by the embedded https server in tests. This is used to determine // the correct port while upgrading URLs to https if the original URL has a // non-default port. diff --git a/components/omnibox/browser/autocomplete_input_unittest.cc b/components/omnibox/browser/autocomplete_input_unittest.cc index 06d07f8d1a9c8..ef2a613185aa0 100644 --- a/components/omnibox/browser/autocomplete_input_unittest.cc +++ b/components/omnibox/browser/autocomplete_input_unittest.cc @@ -473,3 +473,41 @@ TEST(AutocompleteInputTest, UpgradeTypedNavigationsToHttps) { EXPECT_TRUE(fake_http_input.added_default_scheme_to_typed_url()); #endif } + +TEST(AutocompleteInputTest, TypedURLHadHTTPSchemeTest) { + struct TestData { + const std::u16string input; + bool expected_typed_url_had_http_scheme; + }; + + const TestData test_cases[] = { + {u"example.com", false}, + {u"example.com:80", false}, + {u"example.com:8080", false}, + {u"example query", false}, + {u"http example query", false}, + {u"127.0.0.1", false}, + {u"127.0.0.1:80", false}, + {u"127.0.0.1:8080", false}, + {u"http://127.0.0.1:8080", true}, + {u"https://127.0.0.1:8080", false}, + {u"dotlesshostname/", false}, + {u"http://dotlesshostname/", true}, + {u"https://dotlesshostname/", false}, + {u"http://example.com", true}, + {u"HTTP://EXAMPLE.COM", true}, + {u"http://example.com:80", true}, + {u"HTTP://EXAMPLE.COM:80", true}, + {u"http://example.com:8080", true}, + {u"HTTP://EXAMPLE.COM:8080", true}, + {u"HTTPS://EXAMPLE.COM", false}, + }; + for (const TestData& test_case : test_cases) { + AutocompleteInput input(test_case.input, std::u16string::npos, + metrics::OmniboxEventProto::OTHER, + TestSchemeClassifier(), + /*should_use_https_as_default_scheme=*/true); + EXPECT_EQ(test_case.expected_typed_url_had_http_scheme, + input.typed_url_had_http_scheme()); + } +} diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index 7a0ce1ec2f87b..c980693ec4a5b 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc @@ -2553,7 +2553,10 @@ void OmniboxEditModel::OpenMatch(AutocompleteMatch match, ui::PageTransitionFromInt(match.transition | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR), match.type, match_selection_timestamp, - input_.added_default_scheme_to_typed_url(), input_text, match, + input_.added_default_scheme_to_typed_url(), + input_.typed_url_had_http_scheme() && + match.type == AutocompleteMatchType::URL_WHAT_YOU_TYPED, + input_text, match, VerbatimMatchForInput( autocomplete_controller()->history_url_provider(), autocomplete_controller()->autocomplete_provider_client(), diff --git a/components/omnibox/browser/omnibox_edit_model_delegate.h b/components/omnibox/browser/omnibox_edit_model_delegate.h index 153bd7d3307c1..a4cffd855d72e 100644 --- a/components/omnibox/browser/omnibox_edit_model_delegate.h +++ b/components/omnibox/browser/omnibox_edit_model_delegate.h @@ -33,6 +33,7 @@ class OmniboxEditModelDelegate 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, @@ -61,6 +62,9 @@ class OmniboxEditModelDelegate bool destination_url_entered_without_scheme() const { return destination_url_entered_without_scheme_; } + bool destination_url_entered_with_http_scheme() const { + return destination_url_entered_with_http_scheme_; + } protected: // The details necessary to open the user's desired omnibox match. @@ -70,7 +74,8 @@ class OmniboxEditModelDelegate ui::PageTransition transition_{ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR}; base::TimeTicks match_selection_timestamp_; - bool destination_url_entered_without_scheme_; + bool destination_url_entered_without_scheme_ = false; + bool destination_url_entered_with_http_scheme_ = false; }; #endif // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_EDIT_MODEL_DELEGATE_H_ diff --git a/components/omnibox/browser/test_omnibox_edit_model_delegate.cc b/components/omnibox/browser/test_omnibox_edit_model_delegate.cc index 9c69817d4c234..fb9fe9d7ae090 100644 --- a/components/omnibox/browser/test_omnibox_edit_model_delegate.cc +++ b/components/omnibox/browser/test_omnibox_edit_model_delegate.cc @@ -21,6 +21,7 @@ void TestOmniboxEditModelDelegate::OnAutocompleteAccept( 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, @@ -32,5 +33,7 @@ void TestOmniboxEditModelDelegate::OnAutocompleteAccept( match_selection_timestamp_ = match_selection_timestamp; destination_url_entered_without_scheme_ = destination_url_entered_without_scheme; + destination_url_entered_with_http_scheme_ = + destination_url_entered_with_http_scheme; alternate_nav_match_ = alternative_nav_match; } diff --git a/components/omnibox/browser/test_omnibox_edit_model_delegate.h b/components/omnibox/browser/test_omnibox_edit_model_delegate.h index 6e44eed184cf6..4bf3c02eebf80 100644 --- a/components/omnibox/browser/test_omnibox_edit_model_delegate.h +++ b/components/omnibox/browser/test_omnibox_edit_model_delegate.h @@ -28,6 +28,7 @@ class TestOmniboxEditModelDelegate : public OmniboxEditModelDelegate { 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, diff --git a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.h b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.h index 596656b628b7b..ab2ed7b8f0346 100644 --- a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.h +++ b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.h @@ -40,6 +40,7 @@ class WebOmniboxEditModelDelegateImpl : public WebOmniboxEditModelDelegate { 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, diff --git a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.mm b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.mm index e80b404ef1235..c94fc51f2de5a 100644 --- a/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.mm +++ b/ios/chrome/browser/ui/omnibox/web_omnibox_edit_model_delegate_impl.mm @@ -41,6 +41,7 @@ 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,