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,