blob: a4a59c254733f283e29f9508263a2383802a0d03 [file] [log] [blame]
// Copyright 2019 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/blocked_interception_blocking_page.h"
#include "chrome/browser/interstitials/chrome_metrics_helper.h"
#include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
#include "chrome/browser/ssl/ssl_error_controller_client.h"
#include "components/security_interstitials/content/cert_report_helper.h"
#include "components/security_interstitials/content/ssl_cert_reporter.h"
#include "components/security_interstitials/core/metrics_helper.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/mojom/renderer_preferences.mojom.h"
using content::InterstitialPageDelegate;
using content::NavigationController;
using content::NavigationEntry;
// static
const InterstitialPageDelegate::TypeID
BlockedInterceptionBlockingPage::kTypeForTesting =
&BlockedInterceptionBlockingPage::kTypeForTesting;
namespace {
const char kBlockedInterceptionMetricsName[] = "blocked_interception";
std::unique_ptr<ChromeMetricsHelper> CreateBlockedInterceptionMetricsHelper(
content::WebContents* web_contents,
const GURL& request_url) {
// Set up the metrics helper for the BlockedInterceptionUI.
security_interstitials::MetricsHelper::ReportDetails reporting_info;
reporting_info.metric_prefix = kBlockedInterceptionMetricsName;
std::unique_ptr<ChromeMetricsHelper> metrics_helper =
std::make_unique<ChromeMetricsHelper>(web_contents, request_url,
reporting_info);
metrics_helper.get()->StartRecordingCaptivePortalMetrics(false);
return metrics_helper;
}
} // namespace
// Note that we always create a navigation entry with SSL errors.
// No error happening loading a sub-resource triggers an interstitial so far.
// Creating an interstitial without showing (e.g. from chrome://interstitials)
// it leaks memory, so don't create it here.
BlockedInterceptionBlockingPage::BlockedInterceptionBlockingPage(
content::WebContents* web_contents,
int cert_error,
const GURL& request_url,
std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
const net::SSLInfo& ssl_info)
: SSLBlockingPageBase(
web_contents,
CertificateErrorReport::INTERSTITIAL_BLOCKED_INTERCEPTION,
ssl_info,
request_url,
std::move(ssl_cert_reporter),
true /* overridable */,
base::Time::Now(),
std::make_unique<SSLErrorControllerClient>(
web_contents,
ssl_info,
cert_error,
request_url,
CreateBlockedInterceptionMetricsHelper(web_contents,
request_url))),
ssl_info_(ssl_info),
blocked_interception_ui_(
new security_interstitials::BlockedInterceptionUI(request_url,
cert_error,
ssl_info,
controller())) {
ChromeSecurityBlockingPageFactory::DoChromeSpecificSetup(this);
}
BlockedInterceptionBlockingPage::~BlockedInterceptionBlockingPage() = default;
bool BlockedInterceptionBlockingPage::ShouldCreateNewNavigation() const {
return true;
}
InterstitialPageDelegate::TypeID
BlockedInterceptionBlockingPage::GetTypeForTesting() {
return BlockedInterceptionBlockingPage::kTypeForTesting;
}
void BlockedInterceptionBlockingPage::PopulateInterstitialStrings(
base::DictionaryValue* load_time_data) {
blocked_interception_ui_->PopulateStringsForHTML(load_time_data);
cert_report_helper()->PopulateExtendedReportingOption(load_time_data);
}
void BlockedInterceptionBlockingPage::OverrideEntry(NavigationEntry* entry) {
entry->GetSSL() = content::SSLStatus(ssl_info_);
}
// This handles the commands sent from the interstitial JavaScript.
void BlockedInterceptionBlockingPage::CommandReceived(
const std::string& command) {
if (command == "\"pageLoadComplete\"") {
// content::WaitForRenderFrameReady sends this message when the page
// load completes. Ignore it.
return;
}
int cmd = 0;
bool retval = base::StringToInt(command, &cmd);
DCHECK(retval);
// Let the CertReportHelper handle commands first, This allows it to get set
// up to send reports, so that the report is populated properly if
// BlockedInterceptionUI's command handling triggers a report to be sent.
cert_report_helper()->HandleReportingCommands(
static_cast<security_interstitials::SecurityInterstitialCommand>(cmd),
controller()->GetPrefService());
blocked_interception_ui_->HandleCommand(
static_cast<security_interstitials::SecurityInterstitialCommand>(cmd));
}