| Index: chrome/browser/ssl/ssl_blocking_page.cc
|
| diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
|
| index 55f465cec8653e47513f03329ca00802498e6bfc..e6083f8768ecf1a12308fb8d693f8b38bc584562 100644
|
| --- a/chrome/browser/ssl/ssl_blocking_page.cc
|
| +++ b/chrome/browser/ssl/ssl_blocking_page.cc
|
| @@ -4,12 +4,16 @@
|
|
|
| #include "chrome/browser/ssl/ssl_blocking_page.h"
|
|
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| #include "base/build_time.h"
|
| +#include "base/callback_helpers.h"
|
| #include "base/command_line.h"
|
| #include "base/i18n/rtl.h"
|
| #include "base/i18n/time_formatting.h"
|
| #include "base/metrics/field_trial.h"
|
| #include "base/metrics/histogram.h"
|
| +#include "base/prefs/pref_service.h"
|
| #include "base/process/launch.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/strings/string_piece.h"
|
| @@ -20,11 +24,14 @@
|
| #include "base/values.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| +#include "chrome/browser/interstitials/security_interstitial_metrics_helper.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/renderer_preferences_util.h"
|
| +#include "chrome/browser/safe_browsing/ui_manager.h"
|
| #include "chrome/browser/ssl/ssl_error_classification.h"
|
| #include "chrome/browser/ssl/ssl_error_info.h"
|
| #include "chrome/common/chrome_switches.h"
|
| +#include "chrome/common/pref_names.h"
|
| #include "chrome/grit/chromium_strings.h"
|
| #include "chrome/grit/generated_resources.h"
|
| #include "components/google/core/browser/google_util.h"
|
| @@ -221,13 +228,15 @@ InterstitialPageDelegate::TypeID SSLBlockingPage::kTypeForTesting =
|
|
|
| // Note that we always create a navigation entry with SSL errors.
|
| // No error happening loading a sub-resource triggers an interstitial so far.
|
| -SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
|
| - int cert_error,
|
| - const net::SSLInfo& ssl_info,
|
| - const GURL& request_url,
|
| - int options_mask,
|
| - const base::Time& time_triggered,
|
| - const base::Callback<void(bool)>& callback)
|
| +SSLBlockingPage::SSLBlockingPage(
|
| + content::WebContents* web_contents,
|
| + int cert_error,
|
| + const net::SSLInfo& ssl_info,
|
| + const GURL& request_url,
|
| + int options_mask,
|
| + const base::Time& time_triggered,
|
| + SafeBrowsingUIManager* safe_browsing_ui_manager,
|
| + const base::Callback<void(bool)>& callback)
|
| : SecurityInterstitialPage(web_contents, request_url),
|
| callback_(callback),
|
| cert_error_(cert_error),
|
| @@ -237,7 +246,8 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
|
| strict_enforcement_((options_mask & STRICT_ENFORCEMENT) != 0),
|
| expired_but_previously_allowed_(
|
| (options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0),
|
| - time_triggered_(time_triggered) {
|
| + time_triggered_(time_triggered),
|
| + safe_browsing_ui_manager_(safe_browsing_ui_manager) {
|
| interstitial_reason_ =
|
| IsErrorDueToBadClock(time_triggered_, cert_error_) ?
|
| SSL_REASON_BAD_CLOCK : SSL_REASON_SSL;
|
| @@ -245,15 +255,15 @@ SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents,
|
| // We collapse the Rappor metric name to just "ssl" so we don't leak
|
| // the "overridable" bit. We skip Rappor altogether for bad clocks.
|
| // This must be done after calculating |interstitial_reason_| above.
|
| - metrics_helper_.reset(new SecurityInterstitialMetricsHelper(
|
| + set_metrics_helper(new SecurityInterstitialMetricsHelper(
|
| web_contents, request_url, GetUmaHistogramPrefix(), kSSLRapporPrefix,
|
| (interstitial_reason_ == SSL_REASON_BAD_CLOCK
|
| ? SecurityInterstitialMetricsHelper::SKIP_RAPPOR
|
| : SecurityInterstitialMetricsHelper::REPORT_RAPPOR),
|
| GetSamplingEventName()));
|
|
|
| - metrics_helper_->RecordUserDecision(SecurityInterstitialMetricsHelper::SHOW);
|
| - metrics_helper_->RecordUserInteraction(
|
| + metrics_helper()->RecordUserDecision(SecurityInterstitialMetricsHelper::SHOW);
|
| + metrics_helper()->RecordUserInteraction(
|
| SecurityInterstitialMetricsHelper::TOTAL_VISITS);
|
|
|
| ssl_error_classification_.reset(new SSLErrorClassification(
|
| @@ -285,7 +295,7 @@ SSLBlockingPage::~SSLBlockingPage() {
|
| if (!callback_.is_null()) {
|
| // The page is closed without the user having chosen what to do, default to
|
| // deny.
|
| - metrics_helper_->RecordUserDecision(
|
| + metrics_helper()->RecordUserDecision(
|
| SecurityInterstitialMetricsHelper::DONT_PROCEED);
|
| RecordSSLExpirationPageEventState(
|
| expired_but_previously_allowed_, false, overridable_);
|
| @@ -439,6 +449,34 @@ void SSLBlockingPage::PopulateInterstitialStrings(
|
| &encoded_chain);
|
| load_time_data->SetString(
|
| "pem", JoinString(encoded_chain, std::string()));
|
| +
|
| + PopulateExtendedReportingOption(load_time_data);
|
| +}
|
| +
|
| +void SSLBlockingPage::PopulateExtendedReportingOption(
|
| + base::DictionaryValue* load_time_data) {
|
| + // Only show the checkbox if not off-the-record and if the
|
| + // command-line option is set.
|
| + const bool show = !web_contents()->GetBrowserContext()->IsOffTheRecord() &&
|
| + base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableInvalidCertCollection);
|
| +
|
| + load_time_data->SetBoolean(interstitials::kDisplayCheckBox, show);
|
| + if (!show)
|
| + return;
|
| +
|
| + load_time_data->SetBoolean(
|
| + interstitials::kBoxChecked,
|
| + IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled));
|
| +
|
| + const std::string privacy_link = base::StringPrintf(
|
| + interstitials::kPrivacyLinkHtml, CMD_OPEN_REPORTING_PRIVACY,
|
| + l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
|
| +
|
| + load_time_data->SetString(
|
| + interstitials::kOptInLink,
|
| + l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
|
| + base::UTF8ToUTF16(privacy_link)));
|
| }
|
|
|
| void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) {
|
| @@ -453,6 +491,11 @@ void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) {
|
| entry->GetSSL().security_bits = ssl_info_.security_bits;
|
| }
|
|
|
| +void SSLBlockingPage::SetCertificateReportCallbackForTesting(
|
| + const base::Closure& callback) {
|
| + certificate_report_callback_for_testing_ = callback;
|
| +}
|
| +
|
| // This handles the commands sent from the interstitial JavaScript.
|
| // DO NOT reorder or change this logic without also changing the JavaScript!
|
| void SSLBlockingPage::CommandReceived(const std::string& command) {
|
| @@ -476,13 +519,21 @@ void SSLBlockingPage::CommandReceived(const std::string& command) {
|
| }
|
| break;
|
| }
|
| + case CMD_DO_REPORT: {
|
| + SetReportingPreference(true);
|
| + break;
|
| + }
|
| + case CMD_DONT_REPORT: {
|
| + SetReportingPreference(false);
|
| + break;
|
| + }
|
| case CMD_SHOW_MORE_SECTION: {
|
| - metrics_helper_->RecordUserInteraction(
|
| + metrics_helper()->RecordUserInteraction(
|
| SecurityInterstitialMetricsHelper::SHOW_ADVANCED);
|
| break;
|
| }
|
| case CMD_OPEN_HELP_CENTER: {
|
| - metrics_helper_->RecordUserInteraction(
|
| + metrics_helper()->RecordUserInteraction(
|
| SecurityInterstitialMetricsHelper::SHOW_LEARN_MORE);
|
| content::NavigationController::LoadURLParams help_page_params(
|
| google_util::AppendGoogleLocaleParam(
|
| @@ -491,25 +542,24 @@ void SSLBlockingPage::CommandReceived(const std::string& command) {
|
| break;
|
| }
|
| case CMD_RELOAD: {
|
| - metrics_helper_->RecordUserInteraction(
|
| + metrics_helper()->RecordUserInteraction(
|
| SecurityInterstitialMetricsHelper::RELOAD);
|
| // The interstitial can't refresh itself.
|
| web_contents()->GetController().Reload(true);
|
| break;
|
| }
|
| case CMD_OPEN_DATE_SETTINGS: {
|
| - metrics_helper_->RecordUserInteraction(
|
| + metrics_helper()->RecordUserInteraction(
|
| SecurityInterstitialMetricsHelper::OPEN_TIME_SETTINGS);
|
| content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
|
| base::Bind(&LaunchDateAndTimeSettings));
|
| break;
|
| }
|
| + case CMD_OPEN_REPORTING_PRIVACY:
|
| + OpenExtendedReportingPrivacyPolicy();
|
| + break;
|
| case CMD_OPEN_DIAGNOSTIC:
|
| // Google doesn't currently have a transparency report for SSL.
|
| - case CMD_DO_REPORT:
|
| - case CMD_DONT_REPORT:
|
| - case CMD_OPEN_REPORTING_PRIVACY:
|
| - // Chrome doesn't currently do Extended Reporting for SSL.
|
| NOTREACHED() << "Unexpected command: " << command;
|
| }
|
| }
|
| @@ -523,8 +573,13 @@ void SSLBlockingPage::OverrideRendererPrefs(
|
| }
|
|
|
| void SSLBlockingPage::OnProceed() {
|
| - metrics_helper_->RecordUserDecision(
|
| + metrics_helper()->RecordUserDecision(
|
| SecurityInterstitialMetricsHelper::PROCEED);
|
| +
|
| + // Finish collecting information about invalid certificates, if the
|
| + // user opted in to.
|
| + FinishCertCollection();
|
| +
|
| RecordSSLExpirationPageEventState(
|
| expired_but_previously_allowed_, true, overridable_);
|
| // Accepting the certificate resumes the loading of the page.
|
| @@ -532,8 +587,13 @@ void SSLBlockingPage::OnProceed() {
|
| }
|
|
|
| void SSLBlockingPage::OnDontProceed() {
|
| - metrics_helper_->RecordUserDecision(
|
| + metrics_helper()->RecordUserDecision(
|
| SecurityInterstitialMetricsHelper::DONT_PROCEED);
|
| +
|
| + // Finish collecting information about invalid certificates, if the
|
| + // user opted in to.
|
| + FinishCertCollection();
|
| +
|
| RecordSSLExpirationPageEventState(
|
| expired_but_previously_allowed_, false, overridable_);
|
| NotifyDenyCertificate();
|
| @@ -581,6 +641,32 @@ std::string SSLBlockingPage::GetSamplingEventName() const {
|
| return event_name;
|
| }
|
|
|
| +void SSLBlockingPage::FinishCertCollection() {
|
| + base::ScopedClosureRunner scoped_callback(
|
| + certificate_report_callback_for_testing_);
|
| +
|
| + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableInvalidCertCollection) ||
|
| + web_contents()->GetBrowserContext()->IsOffTheRecord()) {
|
| + return;
|
| + }
|
| +
|
| + const bool enabled =
|
| + IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled);
|
| +
|
| + if (!enabled)
|
| + return;
|
| +
|
| + metrics_helper()->RecordUserInteraction(
|
| + SecurityInterstitialMetricsHelper::EXTENDED_REPORTING_IS_ENABLED);
|
| +
|
| + if (certificate_report_callback_for_testing_.is_null())
|
| + scoped_callback.Reset(base::Bind(&base::DoNothing));
|
| +
|
| + safe_browsing_ui_manager_->ReportInvalidCertificateChain(
|
| + request_url().host(), ssl_info_, scoped_callback.Release());
|
| +}
|
| +
|
| // static
|
| bool SSLBlockingPage::IsOptionsOverridable(int options_mask) {
|
| return (options_mask & SSLBlockingPage::OVERRIDABLE) &&
|
|
|