Chromium Code Reviews| 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 c32e5a357cba2acf83dbf76cd9dd2e9ca03cd96f..70fad16bb51bdc231dab0881e5385d2af176b58f 100644 |
| --- a/chrome/browser/ssl/ssl_blocking_page.cc |
| +++ b/chrome/browser/ssl/ssl_blocking_page.cc |
| @@ -4,12 +4,17 @@ |
| #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/memory/ref_counted.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,14 +25,17 @@ |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chrome_notification_types.h" |
| +#include "chrome/browser/net/certificate_error_reporter.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/renderer_preferences_util.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" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/cert_store.h" |
| #include "content/public/browser/interstitial_page.h" |
| #include "content/public/browser/interstitial_page_delegate.h" |
| @@ -44,6 +52,8 @@ |
| #include "net/base/hash_value.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/net_util.h" |
| +#include "net/url_request/url_request_context.h" |
| +#include "net/url_request/url_request_context_getter.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #if defined(OS_WIN) |
| @@ -65,6 +75,8 @@ |
| using base::ASCIIToUTF16; |
| using base::TimeTicks; |
| +using chrome_browser_net::CertificateErrorReporter; |
| +using content::BrowserThread; |
| using content::InterstitialPage; |
| using content::InterstitialPageDelegate; |
| using content::NavigationController; |
| @@ -211,6 +223,20 @@ bool IsErrorDueToBadClock(const base::Time& now, int error) { |
| SSLErrorClassification::IsUserClockInTheFuture(now); |
| } |
| +// A helper function that actually sends the cert collection report over |
| +// the network. |
| +void FinishCertCollectionInternal( |
| + const scoped_refptr<CertificateErrorReporter>& reporter, |
| + const scoped_refptr<net::URLRequestContextGetter>& request_context_getter, |
| + const std::string& hostname, |
| + const net::SSLInfo& ssl_info) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| + DCHECK(reporter); |
| + reporter->SendReport(CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING, |
| + request_context_getter->GetURLRequestContext(), hostname, |
| + ssl_info); |
| +} |
| + |
| } // namespace |
| // static |
| @@ -219,13 +245,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, |
| + const scoped_refptr<CertificateErrorReporter>& certificate_error_reporter, |
| + const base::Callback<void(bool)>& callback) |
| : SecurityInterstitialPage(web_contents, request_url), |
| callback_(callback), |
| cert_error_(cert_error), |
| @@ -235,7 +263,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), |
| + certificate_error_reporter_(certificate_error_reporter) { |
| interstitial_reason_ = |
| IsErrorDueToBadClock(time_triggered_, cert_error_) ? |
| SSL_REASON_BAD_CLOCK : SSL_REASON_SSL; |
| @@ -306,7 +335,6 @@ void SSLBlockingPage::PopulateInterstitialStrings( |
| load_time_data->SetString( |
| "closeDetails", |
| l10n_util::GetStringUTF16(IDS_SSL_V2_CLOSE_DETAILS_BUTTON)); |
| - |
| // Conditional UI configuration. |
| if (interstitial_reason_ == SSL_REASON_BAD_CLOCK) { |
| load_time_data->SetBoolean("bad_clock", true); |
| @@ -432,11 +460,40 @@ void SSLBlockingPage::PopulateInterstitialStrings( |
| base::TimeFormatShortDate(ssl_info_.cert->valid_expiry())); |
| load_time_data->SetString( |
| "currentDate", base::TimeFormatShortDate(time_triggered_)); |
| + |
| std::vector<std::string> encoded_chain; |
| ssl_info_.cert->GetPEMEncodedChain( |
| &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, |
| + 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) { |
| @@ -451,6 +508,11 @@ void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { |
| entry->GetSSL().security_bits = ssl_info_.security_bits; |
| } |
| +void SSLBlockingPage::SetCertificateErrorReporterForTesting( |
| + const scoped_refptr<CertificateErrorReporter>& certificate_error_reporter) { |
| + certificate_error_reporter_ = certificate_error_reporter; |
| +} |
| + |
| // This handles the commands sent from the interstitial JavaScript. They are |
| // defined in chrome/browser/resources/ssl/ssl_errors_common.js. |
| // DO NOT reorder or change this logic without also changing the JavaScript! |
| @@ -469,6 +531,14 @@ void SSLBlockingPage::CommandReceived(const std::string& command) { |
| } |
| break; |
| } |
| + case CMD_DO_REPORT: { |
| + SetReportingPreference(true); |
| + break; |
| + } |
| + case CMD_DONT_REPORT: { |
| + SetReportingPreference(false); |
| + break; |
| + } |
| case CMD_MORE: { |
| metrics_helper_->RecordUserInteraction( |
| SecurityInterstitialMetricsHelper::SHOW_ADVANCED); |
| @@ -513,6 +583,11 @@ void SSLBlockingPage::OverrideRendererPrefs( |
| void SSLBlockingPage::OnProceed() { |
| metrics_helper_->RecordUserDecision( |
| SecurityInterstitialMetricsHelper::PROCEED); |
| + |
| + // Finish collection 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. |
| @@ -522,6 +597,11 @@ void SSLBlockingPage::OnProceed() { |
| void SSLBlockingPage::OnDontProceed() { |
| metrics_helper_->RecordUserDecision( |
| SecurityInterstitialMetricsHelper::DONT_PROCEED); |
| + |
| + // Finish collection information about invalid certificates, if the |
| + // user opted in to. |
| + FinishCertCollection(); |
| + |
| RecordSSLExpirationPageEventState( |
| expired_but_previously_allowed_, false, overridable_); |
| NotifyDenyCertificate(); |
| @@ -569,6 +649,36 @@ 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); |
| + UMA_HISTOGRAM_BOOLEAN("SB2.ExtendedReportingIsEnabled", enabled); |
| + |
| + if (!enabled || !certificate_error_reporter_) |
|
Ryan Sleevi
2015/03/14 03:09:42
If you go the callback, it'd be something like
if
estark
2015/03/16 23:40:52
What I ended up doing was just grabbing the report
|
| + return; |
| + |
| + scoped_refptr<net::URLRequestContextGetter> request_context_getter = |
| + web_contents()->GetBrowserContext()->GetRequestContext(); |
| + |
| + if (certificate_report_callback_for_testing_.is_null()) |
| + scoped_callback.Reset(base::Bind(&base::DoNothing)); |
| + |
| + BrowserThread::PostTaskAndReply( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(FinishCertCollectionInternal, certificate_error_reporter_, |
| + request_context_getter, request_url().host(), ssl_info_), |
| + scoped_callback.Release()); |
| +} |
| + |
| // static |
| bool SSLBlockingPage::IsOptionsOverridable(int options_mask) { |
| return (options_mask & SSLBlockingPage::OVERRIDABLE) && |