Give names to all utility processes.
[chromium-blink-merge.git] / chrome / browser / ssl / ssl_blocking_page.cc
blobe83e6d05a37a726f33d8ffe4bf26baf66abd46bd
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ssl/ssl_blocking_page.h"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/build_time.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/i18n/rtl.h"
13 #include "base/i18n/time_formatting.h"
14 #include "base/metrics/field_trial.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/process/launch.h"
18 #include "base/rand_util.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_piece.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/time/time.h"
25 #include "base/values.h"
26 #include "chrome/browser/browser_process.h"
27 #include "chrome/browser/chrome_notification_types.h"
28 #include "chrome/browser/interstitials/security_interstitial_metrics_helper.h"
29 #include "chrome/browser/profiles/profile.h"
30 #include "chrome/browser/renderer_preferences_util.h"
31 #include "chrome/browser/safe_browsing/ui_manager.h"
32 #include "chrome/browser/ssl/ssl_error_classification.h"
33 #include "chrome/browser/ssl/ssl_error_info.h"
34 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/grit/chromium_strings.h"
37 #include "chrome/grit/generated_resources.h"
38 #include "components/google/core/browser/google_util.h"
39 #include "components/variations/variations_associated_data.h"
40 #include "content/public/browser/browser_thread.h"
41 #include "content/public/browser/cert_store.h"
42 #include "content/public/browser/interstitial_page.h"
43 #include "content/public/browser/interstitial_page_delegate.h"
44 #include "content/public/browser/navigation_controller.h"
45 #include "content/public/browser/navigation_entry.h"
46 #include "content/public/browser/notification_service.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/render_process_host.h"
49 #include "content/public/browser/render_view_host.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/common/renderer_preferences.h"
52 #include "content/public/common/ssl_status.h"
53 #include "grit/browser_resources.h"
54 #include "net/base/hash_value.h"
55 #include "net/base/net_errors.h"
56 #include "net/base/net_util.h"
57 #include "ui/base/l10n/l10n_util.h"
59 #if defined(OS_WIN)
60 #include "base/base_paths_win.h"
61 #include "base/path_service.h"
62 #include "base/strings/string16.h"
63 #include "base/win/windows_version.h"
64 #endif
66 #if defined(OS_ANDROID)
67 #include "chrome/browser/android/intent_helper.h"
68 #endif
70 #if defined(OS_CHROMEOS)
71 #include "chrome/browser/profiles/profile_manager.h"
72 #include "chrome/browser/ui/chrome_pages.h"
73 #include "chrome/common/url_constants.h"
74 #endif
76 using base::ASCIIToUTF16;
77 using base::TimeTicks;
78 using content::InterstitialPage;
79 using content::InterstitialPageDelegate;
80 using content::NavigationController;
81 using content::NavigationEntry;
83 // Constants for the HTTPSErrorReporter Finch experiment
84 const char kHTTPSErrorReporterFinchExperimentName[] = "ReportCertificateErrors";
85 const char kHTTPSErrorReporterFinchGroupShowPossiblySend[] =
86 "ShowAndPossiblySend";
87 const char kHTTPSErrorReporterFinchParamName[] = "sendingThreshold";
89 namespace {
91 // URL for help page.
92 const char kHelpURL[] = "https://support.google.com/chrome/answer/4454607";
94 // Constants for the Experience Sampling instrumentation.
95 const char kEventNameBase[] = "ssl_interstitial_";
96 const char kEventNotOverridable[] = "notoverridable_";
97 const char kEventOverridable[] = "overridable_";
99 // Events for UMA. Do not reorder or change!
100 enum SSLExpirationAndDecision {
101 EXPIRED_AND_PROCEED,
102 EXPIRED_AND_DO_NOT_PROCEED,
103 NOT_EXPIRED_AND_PROCEED,
104 NOT_EXPIRED_AND_DO_NOT_PROCEED,
105 END_OF_SSL_EXPIRATION_AND_DECISION,
108 // Rappor prefix
109 const char kSSLRapporPrefix[] = "ssl";
111 // Check whether to show the certificate reporter checkbox
112 bool ShouldShowCertificateReporterCheckbox(bool in_incognito) {
113 // Only show the checkbox iff the user is part of the respective Finch group
114 // and the window is not incognito.
115 return base::FieldTrialList::FindFullName(
116 kHTTPSErrorReporterFinchExperimentName) ==
117 kHTTPSErrorReporterFinchGroupShowPossiblySend &&
118 !in_incognito;
121 // Check whether to report certificate verification errors to Google
122 bool ShouldReportCertificateErrors(bool in_incognito) {
123 DCHECK(ShouldShowCertificateReporterCheckbox(in_incognito));
124 // Even in case the checkbox was shown, we don't send error reports
125 // for all of these users. Check the Finch configuration for a sending
126 // threshold and only send reports in case the threshold isn't exceeded.
127 const std::string param =
128 variations::GetVariationParamValue(kHTTPSErrorReporterFinchExperimentName,
129 kHTTPSErrorReporterFinchParamName);
130 if (!param.empty()) {
131 double sendingThreshold;
132 if (base::StringToDouble(param, &sendingThreshold)) {
133 if (sendingThreshold >= 0.0 && sendingThreshold <= 1.0)
134 return base::RandDouble() <= sendingThreshold;
137 return false;
140 void RecordSSLExpirationPageEventState(bool expired_but_previously_allowed,
141 bool proceed,
142 bool overridable) {
143 SSLExpirationAndDecision event;
144 if (expired_but_previously_allowed && proceed)
145 event = EXPIRED_AND_PROCEED;
146 else if (expired_but_previously_allowed && !proceed)
147 event = EXPIRED_AND_DO_NOT_PROCEED;
148 else if (!expired_but_previously_allowed && proceed)
149 event = NOT_EXPIRED_AND_PROCEED;
150 else
151 event = NOT_EXPIRED_AND_DO_NOT_PROCEED;
153 if (overridable) {
154 UMA_HISTOGRAM_ENUMERATION(
155 "interstitial.ssl.expiration_and_decision.overridable",
156 event,
157 END_OF_SSL_EXPIRATION_AND_DECISION);
158 } else {
159 UMA_HISTOGRAM_ENUMERATION(
160 "interstitial.ssl.expiration_and_decision.nonoverridable",
161 event,
162 END_OF_SSL_EXPIRATION_AND_DECISION);
166 void LaunchDateAndTimeSettings() {
167 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
168 // The code for each OS is completely separate, in order to avoid bugs like
169 // https://crbug.com/430877 .
170 #if defined(OS_ANDROID)
171 chrome::android::OpenDateAndTimeSettings();
173 #elif defined(OS_CHROMEOS)
174 std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
175 l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME);
176 chrome::ShowSettingsSubPageForProfile(
177 ProfileManager::GetActiveUserProfile(), sub_page);
179 #elif defined(OS_IOS)
180 // iOS does not have a way to launch the date and time settings.
181 NOTREACHED();
183 #elif defined(OS_LINUX)
184 struct ClockCommand {
185 const char* pathname;
186 const char* argument;
188 static const ClockCommand kClockCommands[] = {
189 // Unity
190 { "/usr/bin/unity-control-center", "datetime" },
191 // GNOME
193 // NOTE: On old Ubuntu, naming control panels doesn't work, so it
194 // opens the overview. This will have to be good enough.
195 { "/usr/bin/gnome-control-center", "datetime" },
196 { "/usr/local/bin/gnome-control-center", "datetime" },
197 { "/opt/bin/gnome-control-center", "datetime" },
198 // KDE
199 { "/usr/bin/kcmshell4", "clock" },
200 { "/usr/local/bin/kcmshell4", "clock" },
201 { "/opt/bin/kcmshell4", "clock" },
204 base::CommandLine command(base::FilePath(""));
205 for (size_t i = 0; i < arraysize(kClockCommands); ++i) {
206 base::FilePath pathname(kClockCommands[i].pathname);
207 if (base::PathExists(pathname)) {
208 command.SetProgram(pathname);
209 command.AppendArg(kClockCommands[i].argument);
210 break;
213 if (command.GetProgram().empty()) {
214 // Alas, there is nothing we can do.
215 return;
218 base::LaunchOptions options;
219 options.wait = false;
220 options.allow_new_privs = true;
221 base::LaunchProcess(command, options);
223 #elif defined(OS_MACOSX)
224 base::CommandLine command(base::FilePath("/usr/bin/open"));
225 command.AppendArg("/System/Library/PreferencePanes/DateAndTime.prefPane");
227 base::LaunchOptions options;
228 options.wait = false;
229 base::LaunchProcess(command, options);
231 #elif defined(OS_WIN)
232 base::FilePath path;
233 PathService::Get(base::DIR_SYSTEM, &path);
234 static const base::char16 kControlPanelExe[] = L"control.exe";
235 path = path.Append(base::string16(kControlPanelExe));
236 base::CommandLine command(path);
237 command.AppendArg(std::string("/name"));
238 command.AppendArg(std::string("Microsoft.DateAndTime"));
240 base::LaunchOptions options;
241 options.wait = false;
242 base::LaunchProcess(command, options);
244 #else
245 NOTREACHED();
247 #endif
248 // Don't add code here! (See the comment at the beginning of the function.)
251 bool IsErrorDueToBadClock(const base::Time& now, int error) {
252 if (SSLErrorInfo::NetErrorToErrorType(error) !=
253 SSLErrorInfo::CERT_DATE_INVALID) {
254 return false;
256 return SSLErrorClassification::IsUserClockInThePast(now) ||
257 SSLErrorClassification::IsUserClockInTheFuture(now);
260 } // namespace
262 // static
263 InterstitialPageDelegate::TypeID SSLBlockingPage::kTypeForTesting =
264 &SSLBlockingPage::kTypeForTesting;
266 // Note that we always create a navigation entry with SSL errors.
267 // No error happening loading a sub-resource triggers an interstitial so far.
268 SSLBlockingPage::SSLBlockingPage(
269 content::WebContents* web_contents,
270 int cert_error,
271 const net::SSLInfo& ssl_info,
272 const GURL& request_url,
273 int options_mask,
274 const base::Time& time_triggered,
275 SafeBrowsingUIManager* safe_browsing_ui_manager,
276 const base::Callback<void(bool)>& callback)
277 : SecurityInterstitialPage(web_contents, request_url),
278 callback_(callback),
279 cert_error_(cert_error),
280 ssl_info_(ssl_info),
281 overridable_(IsOptionsOverridable(options_mask)),
282 danger_overridable_(true),
283 strict_enforcement_((options_mask & STRICT_ENFORCEMENT) != 0),
284 expired_but_previously_allowed_(
285 (options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0),
286 time_triggered_(time_triggered),
287 safe_browsing_ui_manager_(safe_browsing_ui_manager) {
288 interstitial_reason_ =
289 IsErrorDueToBadClock(time_triggered_, cert_error_) ?
290 SSL_REASON_BAD_CLOCK : SSL_REASON_SSL;
292 // We collapse the Rappor metric name to just "ssl" so we don't leak
293 // the "overridable" bit. We skip Rappor altogether for bad clocks.
294 // This must be done after calculating |interstitial_reason_| above.
295 set_metrics_helper(new SecurityInterstitialMetricsHelper(
296 web_contents, request_url, GetUmaHistogramPrefix(), kSSLRapporPrefix,
297 (interstitial_reason_ == SSL_REASON_BAD_CLOCK
298 ? SecurityInterstitialMetricsHelper::SKIP_RAPPOR
299 : SecurityInterstitialMetricsHelper::REPORT_RAPPOR),
300 GetSamplingEventName()));
302 metrics_helper()->RecordUserDecision(SecurityInterstitialMetricsHelper::SHOW);
303 metrics_helper()->RecordUserInteraction(
304 SecurityInterstitialMetricsHelper::TOTAL_VISITS);
306 ssl_error_classification_.reset(new SSLErrorClassification(
307 web_contents,
308 time_triggered_,
309 request_url,
310 cert_error_,
311 *ssl_info_.cert.get()));
312 ssl_error_classification_->RecordUMAStatistics(overridable_);
314 // Creating an interstitial without showing (e.g. from chrome://interstitials)
315 // it leaks memory, so don't create it here.
318 bool SSLBlockingPage::ShouldCreateNewNavigation() const {
319 return true;
322 InterstitialPageDelegate::TypeID SSLBlockingPage::GetTypeForTesting() const {
323 return SSLBlockingPage::kTypeForTesting;
326 SSLBlockingPage::~SSLBlockingPage() {
327 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
328 // Captive portal detection results can arrive anytime during the interstitial
329 // is being displayed, so record it when the interstitial is going away.
330 ssl_error_classification_->RecordCaptivePortalUMAStatistics(overridable_);
331 #endif
332 if (!callback_.is_null()) {
333 // The page is closed without the user having chosen what to do, default to
334 // deny.
335 metrics_helper()->RecordUserDecision(
336 SecurityInterstitialMetricsHelper::DONT_PROCEED);
337 RecordSSLExpirationPageEventState(
338 expired_but_previously_allowed_, false, overridable_);
339 NotifyDenyCertificate();
343 void SSLBlockingPage::PopulateInterstitialStrings(
344 base::DictionaryValue* load_time_data) {
345 CHECK(load_time_data);
346 base::string16 url(GetFormattedHostName());
347 // Shared values for both the overridable and non-overridable versions.
348 load_time_data->SetString("type", "SSL");
350 // Shared UI configuration for all SSL interstitials.
351 load_time_data->SetString("errorCode", net::ErrorToString(cert_error_));
352 load_time_data->SetString(
353 "openDetails",
354 l10n_util::GetStringUTF16(IDS_SSL_V2_OPEN_DETAILS_BUTTON));
355 load_time_data->SetString(
356 "closeDetails",
357 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOSE_DETAILS_BUTTON));
359 // Conditional UI configuration.
360 if (interstitial_reason_ == SSL_REASON_BAD_CLOCK) {
361 load_time_data->SetBoolean("bad_clock", true);
362 load_time_data->SetBoolean("overridable", false);
364 #if defined(OS_IOS)
365 load_time_data->SetBoolean("hide_primary_button", true);
366 #else
367 load_time_data->SetBoolean("hide_primary_button", false);
368 #endif
370 // We're showing the SSL clock warning to be helpful, but we haven't warned
371 // them about the risks. (And there might still be an SSL error after they
372 // fix their clock.) Thus, we don't allow the "danger" override in this
373 // case.
374 danger_overridable_ = false;
376 int heading_string =
377 SSLErrorClassification::IsUserClockInTheFuture(time_triggered_) ?
378 IDS_SSL_V2_CLOCK_AHEAD_HEADING :
379 IDS_SSL_V2_CLOCK_BEHIND_HEADING;
381 load_time_data->SetString(
382 "tabTitle",
383 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOCK_TITLE));
384 load_time_data->SetString(
385 "heading",
386 l10n_util::GetStringUTF16(heading_string));
387 load_time_data->SetString(
388 "primaryParagraph",
389 l10n_util::GetStringFUTF16(
390 IDS_SSL_V2_CLOCK_PRIMARY_PARAGRAPH,
391 url,
392 base::TimeFormatFriendlyDateAndTime(time_triggered_)));
394 load_time_data->SetString(
395 "primaryButtonText",
396 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOCK_UPDATE_DATE_AND_TIME));
397 load_time_data->SetString(
398 "explanationParagraph",
399 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOCK_EXPLANATION));
401 // The interstitial template expects this string, but we're not using it. So
402 // we send a blank string for now.
403 load_time_data->SetString("finalParagraph", std::string());
404 } else {
405 load_time_data->SetBoolean("bad_clock", false);
407 load_time_data->SetString(
408 "tabTitle", l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE));
409 load_time_data->SetString(
410 "heading", l10n_util::GetStringUTF16(IDS_SSL_V2_HEADING));
411 load_time_data->SetString(
412 "primaryParagraph",
413 l10n_util::GetStringFUTF16(IDS_SSL_V2_PRIMARY_PARAGRAPH, url));
415 if (overridable_) {
416 load_time_data->SetBoolean("overridable", true);
418 SSLErrorInfo error_info =
419 SSLErrorInfo::CreateError(
420 SSLErrorInfo::NetErrorToErrorType(cert_error_),
421 ssl_info_.cert.get(),
422 request_url());
423 load_time_data->SetString("explanationParagraph", error_info.details());
424 load_time_data->SetString(
425 "primaryButtonText",
426 l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON));
427 load_time_data->SetString(
428 "finalParagraph",
429 l10n_util::GetStringFUTF16(IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH,
430 url));
431 } else {
432 load_time_data->SetBoolean("overridable", false);
434 SSLErrorInfo::ErrorType type =
435 SSLErrorInfo::NetErrorToErrorType(cert_error_);
436 if (type == SSLErrorInfo::CERT_INVALID && SSLErrorClassification::
437 MaybeWindowsLacksSHA256Support()) {
438 load_time_data->SetString(
439 "explanationParagraph",
440 l10n_util::GetStringFUTF16(
441 IDS_SSL_NONOVERRIDABLE_MORE_INVALID_SP3, url));
442 } else {
443 load_time_data->SetString("explanationParagraph",
444 l10n_util::GetStringFUTF16(
445 IDS_SSL_NONOVERRIDABLE_MORE, url));
447 load_time_data->SetString(
448 "primaryButtonText",
449 l10n_util::GetStringUTF16(IDS_SSL_RELOAD));
450 // Customize the help link depending on the specific error type.
451 // Only mark as HSTS if none of the more specific error types apply,
452 // and use INVALID as a fallback if no other string is appropriate.
453 load_time_data->SetInteger("errorType", type);
454 int help_string = IDS_SSL_NONOVERRIDABLE_INVALID;
455 switch (type) {
456 case SSLErrorInfo::CERT_REVOKED:
457 help_string = IDS_SSL_NONOVERRIDABLE_REVOKED;
458 break;
459 case SSLErrorInfo::CERT_PINNED_KEY_MISSING:
460 help_string = IDS_SSL_NONOVERRIDABLE_PINNED;
461 break;
462 case SSLErrorInfo::CERT_INVALID:
463 help_string = IDS_SSL_NONOVERRIDABLE_INVALID;
464 break;
465 default:
466 if (strict_enforcement_)
467 help_string = IDS_SSL_NONOVERRIDABLE_HSTS;
469 load_time_data->SetString(
470 "finalParagraph", l10n_util::GetStringFUTF16(help_string, url));
474 // Set debugging information at the bottom of the warning.
475 load_time_data->SetString(
476 "subject", ssl_info_.cert->subject().GetDisplayName());
477 load_time_data->SetString(
478 "issuer", ssl_info_.cert->issuer().GetDisplayName());
479 load_time_data->SetString(
480 "expirationDate",
481 base::TimeFormatShortDate(ssl_info_.cert->valid_expiry()));
482 load_time_data->SetString(
483 "currentDate", base::TimeFormatShortDate(time_triggered_));
484 std::vector<std::string> encoded_chain;
485 ssl_info_.cert->GetPEMEncodedChain(
486 &encoded_chain);
487 load_time_data->SetString(
488 "pem", JoinString(encoded_chain, std::string()));
490 PopulateExtendedReportingOption(load_time_data);
493 void SSLBlockingPage::PopulateExtendedReportingOption(
494 base::DictionaryValue* load_time_data) {
495 // Only show the checkbox if not off-the-record and if this client is
496 // part of the respective Finch group.
497 const bool show = ShouldShowCertificateReporterCheckbox(
498 web_contents()->GetBrowserContext()->IsOffTheRecord());
500 load_time_data->SetBoolean(interstitials::kDisplayCheckBox, show);
501 if (!show)
502 return;
504 load_time_data->SetBoolean(
505 interstitials::kBoxChecked,
506 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled));
508 const std::string privacy_link = base::StringPrintf(
509 interstitials::kPrivacyLinkHtml, CMD_OPEN_REPORTING_PRIVACY,
510 l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str());
512 load_time_data->SetString(
513 interstitials::kOptInLink,
514 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE,
515 base::UTF8ToUTF16(privacy_link)));
518 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) {
519 int cert_id = content::CertStore::GetInstance()->StoreCert(
520 ssl_info_.cert.get(), web_contents()->GetRenderProcessHost()->GetID());
521 DCHECK(cert_id);
523 entry->GetSSL().security_style =
524 content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
525 entry->GetSSL().cert_id = cert_id;
526 entry->GetSSL().cert_status = ssl_info_.cert_status;
527 entry->GetSSL().security_bits = ssl_info_.security_bits;
530 void SSLBlockingPage::SetCertificateReportCallbackForTesting(
531 const base::Closure& callback) {
532 certificate_report_callback_for_testing_ = callback;
535 // This handles the commands sent from the interstitial JavaScript.
536 // DO NOT reorder or change this logic without also changing the JavaScript!
537 void SSLBlockingPage::CommandReceived(const std::string& command) {
538 if (command == "\"pageLoadComplete\"") {
539 // content::WaitForRenderFrameReady sends this message when the page
540 // load completes. Ignore it.
541 return;
544 int cmd = 0;
545 bool retval = base::StringToInt(command, &cmd);
546 DCHECK(retval);
547 switch (cmd) {
548 case CMD_DONT_PROCEED: {
549 interstitial_page()->DontProceed();
550 break;
552 case CMD_PROCEED: {
553 if (danger_overridable_) {
554 interstitial_page()->Proceed();
556 break;
558 case CMD_DO_REPORT: {
559 SetReportingPreference(true);
560 break;
562 case CMD_DONT_REPORT: {
563 SetReportingPreference(false);
564 break;
566 case CMD_SHOW_MORE_SECTION: {
567 metrics_helper()->RecordUserInteraction(
568 SecurityInterstitialMetricsHelper::SHOW_ADVANCED);
569 break;
571 case CMD_OPEN_HELP_CENTER: {
572 metrics_helper()->RecordUserInteraction(
573 SecurityInterstitialMetricsHelper::SHOW_LEARN_MORE);
574 content::NavigationController::LoadURLParams help_page_params(
575 google_util::AppendGoogleLocaleParam(
576 GURL(kHelpURL), g_browser_process->GetApplicationLocale()));
577 web_contents()->GetController().LoadURLWithParams(help_page_params);
578 break;
580 case CMD_RELOAD: {
581 metrics_helper()->RecordUserInteraction(
582 SecurityInterstitialMetricsHelper::RELOAD);
583 // The interstitial can't refresh itself.
584 web_contents()->GetController().Reload(true);
585 break;
587 case CMD_OPEN_DATE_SETTINGS: {
588 metrics_helper()->RecordUserInteraction(
589 SecurityInterstitialMetricsHelper::OPEN_TIME_SETTINGS);
590 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
591 base::Bind(&LaunchDateAndTimeSettings));
592 break;
594 case CMD_OPEN_REPORTING_PRIVACY:
595 OpenExtendedReportingPrivacyPolicy();
596 break;
597 case CMD_OPEN_DIAGNOSTIC:
598 // Google doesn't currently have a transparency report for SSL.
599 NOTREACHED() << "Unexpected command: " << command;
603 void SSLBlockingPage::OverrideRendererPrefs(
604 content::RendererPreferences* prefs) {
605 Profile* profile = Profile::FromBrowserContext(
606 web_contents()->GetBrowserContext());
607 renderer_preferences_util::UpdateFromSystemSettings(
608 prefs, profile, web_contents());
611 void SSLBlockingPage::OnProceed() {
612 metrics_helper()->RecordUserDecision(
613 SecurityInterstitialMetricsHelper::PROCEED);
615 // Finish collecting information about invalid certificates, if the
616 // user opted in to.
617 FinishCertCollection();
619 RecordSSLExpirationPageEventState(
620 expired_but_previously_allowed_, true, overridable_);
621 // Accepting the certificate resumes the loading of the page.
622 NotifyAllowCertificate();
625 void SSLBlockingPage::OnDontProceed() {
626 metrics_helper()->RecordUserDecision(
627 SecurityInterstitialMetricsHelper::DONT_PROCEED);
629 // Finish collecting information about invalid certificates, if the
630 // user opted in to.
631 FinishCertCollection();
633 RecordSSLExpirationPageEventState(
634 expired_but_previously_allowed_, false, overridable_);
635 NotifyDenyCertificate();
638 void SSLBlockingPage::NotifyDenyCertificate() {
639 // It's possible that callback_ may not exist if the user clicks "Proceed"
640 // followed by pressing the back button before the interstitial is hidden.
641 // In that case the certificate will still be treated as allowed.
642 if (callback_.is_null())
643 return;
645 callback_.Run(false);
646 callback_.Reset();
649 void SSLBlockingPage::NotifyAllowCertificate() {
650 DCHECK(!callback_.is_null());
652 callback_.Run(true);
653 callback_.Reset();
656 std::string SSLBlockingPage::GetUmaHistogramPrefix() const {
657 switch (interstitial_reason_) {
658 case SSL_REASON_SSL:
659 if (overridable_)
660 return "ssl_overridable";
661 else
662 return "ssl_nonoverridable";
663 case SSL_REASON_BAD_CLOCK:
664 return "bad_clock";
666 NOTREACHED();
667 return std::string();
670 std::string SSLBlockingPage::GetSamplingEventName() const {
671 std::string event_name(kEventNameBase);
672 if (overridable_)
673 event_name.append(kEventOverridable);
674 else
675 event_name.append(kEventNotOverridable);
676 event_name.append(net::ErrorToString(cert_error_));
677 return event_name;
680 void SSLBlockingPage::FinishCertCollection() {
681 base::ScopedClosureRunner scoped_callback(
682 certificate_report_callback_for_testing_);
684 if (!ShouldShowCertificateReporterCheckbox(
685 web_contents()->GetBrowserContext()->IsOffTheRecord())) {
686 return;
689 const bool enabled =
690 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled);
692 if (!enabled)
693 return;
695 metrics_helper()->RecordUserInteraction(
696 SecurityInterstitialMetricsHelper::EXTENDED_REPORTING_IS_ENABLED);
698 if (ShouldReportCertificateErrors(
699 web_contents()->GetBrowserContext()->IsOffTheRecord())) {
700 if (certificate_report_callback_for_testing_.is_null())
701 scoped_callback.Reset(base::Bind(&base::DoNothing));
702 safe_browsing_ui_manager_->ReportInvalidCertificateChain(
703 request_url().host(), ssl_info_, scoped_callback.Release());
707 // static
708 bool SSLBlockingPage::IsOptionsOverridable(int options_mask) {
709 return (options_mask & SSLBlockingPage::OVERRIDABLE) &&
710 !(options_mask & SSLBlockingPage::STRICT_ENFORCEMENT);