| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/preloading/preview/preview_navigation_throttle.h" |
| |
| #include <string_view> |
| |
| #include "base/command_line.h" |
| #include "base/memory/ptr_util.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "components/error_page/common/error.h" |
| #include "components/error_page/common/localized_error.h" |
| #include "components/grit/components_resources.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/preview_cancel_reason.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/browser/web_contents_delegate.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/base/webui/web_ui_util.h" |
| #include "url/gurl.h" |
| |
| // static |
| void PreviewNavigationThrottle::MaybeCreateAndAdd( |
| content::NavigationThrottleRegistry& registry) { |
| auto* web_contents = content::WebContents::FromFrameTreeNodeId( |
| registry.GetNavigationHandle().GetFrameTreeNodeId()); |
| CHECK(web_contents); |
| if (web_contents->IsInPreviewMode()) { |
| registry.AddThrottle( |
| base::WrapUnique(new PreviewNavigationThrottle(registry))); |
| } |
| } |
| |
| PreviewNavigationThrottle::PreviewNavigationThrottle( |
| content::NavigationThrottleRegistry& registry) |
| : content::NavigationThrottle(registry) {} |
| |
| PreviewNavigationThrottle::~PreviewNavigationThrottle() = default; |
| |
| const char* PreviewNavigationThrottle::GetNameForLogging() { |
| return "PreviewNavigationThrottle"; |
| } |
| |
| std::string MakeErrorPage(content::NavigationHandle& navigation_handle, |
| error_page::LinkPreviewErrorCode error_code) { |
| const auto error = error_page::Error::LinkPreviewError( |
| navigation_handle.GetURL(), error_code); |
| base::Value::Dict error_page_params; |
| error_page::LocalizedError::PageState page_state = |
| error_page::LocalizedError::GetPageState( |
| error.reason(), error.domain(), error.url(), |
| navigation_handle.IsPost(), |
| /*is_secure_dns_network_error=*/false, |
| /*stale_copy_in_cache=*/false, |
| /*can_show_network_diagnostics_dialog=*/false, |
| /*is_incognito=*/ |
| Profile::FromBrowserContext( |
| navigation_handle.GetWebContents()->GetBrowserContext()) |
| ->IsIncognitoProfile(), |
| /*auto_fetch_feature_enabled=*/false, |
| /*is_kiosk_mode=*/ |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kForceAppMode), |
| /*locale=*/g_browser_process->GetApplicationLocale(), |
| /*is_blocked_by_extension=*/false, &error_page_params); |
| |
| std::string extracted_string = |
| ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( |
| IDR_NET_ERROR_HTML); |
| std::string_view template_html(extracted_string.data(), |
| extracted_string.size()); |
| CHECK(!template_html.empty()) << "unable to load template."; |
| return webui::GetLocalizedHtml(template_html, page_state.strings); |
| } |
| |
| content::NavigationThrottle::ThrottleCheckResult Cancel( |
| content::NavigationHandle& navigation_handle, |
| content::PreviewCancelReason reason, |
| error_page::LinkPreviewErrorCode error_code) { |
| auto* web_contents = content::WebContents::FromFrameTreeNodeId( |
| navigation_handle.GetFrameTreeNodeId()); |
| if (web_contents->GetDelegate()) { |
| web_contents->GetDelegate()->CancelPreview(std::move(reason)); |
| } |
| |
| return content::NavigationThrottle::ThrottleCheckResult( |
| content::NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT, |
| MakeErrorPage(navigation_handle, error_code)); |
| } |
| |
| content::NavigationThrottle::ThrottleCheckResult |
| PreviewNavigationThrottle::WillStartRequest() { |
| return WillStartRequestOrRedirect(); |
| } |
| |
| content::NavigationThrottle::ThrottleCheckResult |
| PreviewNavigationThrottle::WillRedirectRequest() { |
| return WillStartRequestOrRedirect(); |
| } |
| |
| content::NavigationThrottle::ThrottleCheckResult |
| PreviewNavigationThrottle::WillStartRequestOrRedirect() { |
| if (!navigation_handle()->GetURL().SchemeIs(url::kHttpsScheme)) { |
| return Cancel(*navigation_handle(), |
| content::PreviewCancelReason::Build( |
| content::PreviewFinalStatus::kBlockedByNonHttps), |
| error_page::LinkPreviewErrorCode::kNonHttpsForbidden); |
| } |
| |
| return content::NavigationThrottle::ThrottleAction::PROCEED; |
| } |