blob: 4202e53951ffb64c4894b6feee02343547ae0880 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ssl/ssl_error_navigation_throttle.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/ssl/ssl_error_tab_helper.h"
#include "chrome/common/chrome_switches.h"
#include "components/security_interstitials/content/security_interstitial_page.h"
#include "content/public/browser/navigation_handle.h"
#include "net/cert/cert_status_flags.h"
SSLErrorNavigationThrottle::SSLErrorNavigationThrottle(
content::NavigationHandle* navigation_handle,
std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
SSLErrorNavigationThrottle::HandleSSLErrorCallback
handle_ssl_error_callback)
: content::NavigationThrottle(navigation_handle),
ssl_cert_reporter_(std::move(ssl_cert_reporter)),
handle_ssl_error_callback_(std::move(handle_ssl_error_callback)),
weak_ptr_factory_(this) {}
SSLErrorNavigationThrottle::~SSLErrorNavigationThrottle() {}
const char* SSLErrorNavigationThrottle::GetNameForLogging() {
return "SSLErrorNavigationThrottle";
}
content::NavigationThrottle::ThrottleCheckResult
SSLErrorNavigationThrottle::WillFailRequest() {
DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kCommittedInterstitials));
content::NavigationHandle* handle = navigation_handle();
// If there was no certificate error, SSLInfo will be empty.
int cert_status = handle->GetSSLInfo().cert_status;
if (!net::IsCertStatusError(cert_status) ||
net::IsCertStatusMinorError(cert_status)) {
return content::NavigationThrottle::PROCEED;
}
// We don't know whether SSLErrorHandler will call the ShowInterstitial()
// callback synchronously, so we post a task that will run after this function
// defers the navigation. This ensures that ShowInterstitial() can always
// safely call CancelDeferredNavigation().
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(handle_ssl_error_callback_), handle->GetWebContents(),
net::MapCertStatusToNetError(cert_status), handle->GetSSLInfo(),
handle->GetURL(), false, std::move(ssl_cert_reporter_),
base::Callback<void(content::CertificateRequestResultType)>(),
base::BindOnce(&SSLErrorNavigationThrottle::ShowInterstitial,
weak_ptr_factory_.GetWeakPtr())));
return content::NavigationThrottle::ThrottleCheckResult(
content::NavigationThrottle::DEFER);
}
void SSLErrorNavigationThrottle::ShowInterstitial(
std::unique_ptr<security_interstitials::SecurityInterstitialPage>
blocking_page) {
content::NavigationHandle* handle = navigation_handle();
int net_error =
net::MapCertStatusToNetError(handle->GetSSLInfo().cert_status);
// Get the error page content before giving up ownership of |blocking_page|.
std::string error_page_content = blocking_page->GetHTMLContents();
SSLErrorTabHelper::AssociateBlockingPage(handle->GetWebContents(),
handle->GetNavigationId(),
std::move(blocking_page));
CancelDeferredNavigation(content::NavigationThrottle::ThrottleCheckResult(
content::NavigationThrottle::CANCEL, static_cast<net::Error>(net_error),
error_page_content));
}