OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ssl/ssl_blocking_page.h" | 5 #include "chrome/browser/ssl/ssl_blocking_page.h" |
6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
7 #include "base/build_time.h" | 9 #include "base/build_time.h" |
| 10 #include "base/callback_helpers.h" |
8 #include "base/command_line.h" | 11 #include "base/command_line.h" |
9 #include "base/i18n/rtl.h" | 12 #include "base/i18n/rtl.h" |
10 #include "base/i18n/time_formatting.h" | 13 #include "base/i18n/time_formatting.h" |
11 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" |
12 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/prefs/pref_service.h" |
13 #include "base/process/launch.h" | 17 #include "base/process/launch.h" |
14 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/string_piece.h" | 19 #include "base/strings/string_piece.h" |
16 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
17 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
18 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
19 #include "base/time/time.h" | 23 #include "base/time/time.h" |
20 #include "base/values.h" | 24 #include "base/values.h" |
21 #include "chrome/browser/browser_process.h" | 25 #include "chrome/browser/browser_process.h" |
22 #include "chrome/browser/chrome_notification_types.h" | 26 #include "chrome/browser/chrome_notification_types.h" |
| 27 #include "chrome/browser/net/certificate_error_reporter.h" |
23 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
| 29 #include "chrome/browser/profiles/profile_io_data.h" |
24 #include "chrome/browser/renderer_preferences_util.h" | 30 #include "chrome/browser/renderer_preferences_util.h" |
25 #include "chrome/browser/ssl/ssl_error_classification.h" | 31 #include "chrome/browser/ssl/ssl_error_classification.h" |
26 #include "chrome/browser/ssl/ssl_error_info.h" | 32 #include "chrome/browser/ssl/ssl_error_info.h" |
27 #include "chrome/common/chrome_switches.h" | 33 #include "chrome/common/chrome_switches.h" |
| 34 #include "chrome/common/pref_names.h" |
28 #include "chrome/grit/chromium_strings.h" | 35 #include "chrome/grit/chromium_strings.h" |
29 #include "chrome/grit/generated_resources.h" | 36 #include "chrome/grit/generated_resources.h" |
30 #include "components/google/core/browser/google_util.h" | 37 #include "components/google/core/browser/google_util.h" |
| 38 #include "content/public/browser/browser_thread.h" |
31 #include "content/public/browser/cert_store.h" | 39 #include "content/public/browser/cert_store.h" |
32 #include "content/public/browser/interstitial_page.h" | 40 #include "content/public/browser/interstitial_page.h" |
33 #include "content/public/browser/interstitial_page_delegate.h" | 41 #include "content/public/browser/interstitial_page_delegate.h" |
34 #include "content/public/browser/navigation_controller.h" | 42 #include "content/public/browser/navigation_controller.h" |
35 #include "content/public/browser/navigation_entry.h" | 43 #include "content/public/browser/navigation_entry.h" |
36 #include "content/public/browser/notification_service.h" | 44 #include "content/public/browser/notification_service.h" |
37 #include "content/public/browser/notification_types.h" | 45 #include "content/public/browser/notification_types.h" |
38 #include "content/public/browser/render_process_host.h" | 46 #include "content/public/browser/render_process_host.h" |
39 #include "content/public/browser/render_view_host.h" | 47 #include "content/public/browser/render_view_host.h" |
40 #include "content/public/browser/web_contents.h" | 48 #include "content/public/browser/web_contents.h" |
(...skipping 17 matching lines...) Expand all Loading... |
58 #endif | 66 #endif |
59 | 67 |
60 #if defined(OS_CHROMEOS) | 68 #if defined(OS_CHROMEOS) |
61 #include "chrome/browser/profiles/profile_manager.h" | 69 #include "chrome/browser/profiles/profile_manager.h" |
62 #include "chrome/browser/ui/chrome_pages.h" | 70 #include "chrome/browser/ui/chrome_pages.h" |
63 #include "chrome/common/url_constants.h" | 71 #include "chrome/common/url_constants.h" |
64 #endif | 72 #endif |
65 | 73 |
66 using base::ASCIIToUTF16; | 74 using base::ASCIIToUTF16; |
67 using base::TimeTicks; | 75 using base::TimeTicks; |
| 76 using chrome_browser_net::CertificateErrorReporter; |
| 77 using content::BrowserThread; |
68 using content::InterstitialPage; | 78 using content::InterstitialPage; |
69 using content::InterstitialPageDelegate; | 79 using content::InterstitialPageDelegate; |
70 using content::NavigationController; | 80 using content::NavigationController; |
71 using content::NavigationEntry; | 81 using content::NavigationEntry; |
72 | 82 |
73 namespace { | 83 namespace { |
74 | 84 |
75 // URL for help page. | 85 // URL for help page. |
76 const char kHelpURL[] = "https://support.google.com/chrome/answer/4454607"; | 86 const char kHelpURL[] = "https://support.google.com/chrome/answer/4454607"; |
77 | 87 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 214 |
205 bool IsErrorDueToBadClock(const base::Time& now, int error) { | 215 bool IsErrorDueToBadClock(const base::Time& now, int error) { |
206 if (SSLErrorInfo::NetErrorToErrorType(error) != | 216 if (SSLErrorInfo::NetErrorToErrorType(error) != |
207 SSLErrorInfo::CERT_DATE_INVALID) { | 217 SSLErrorInfo::CERT_DATE_INVALID) { |
208 return false; | 218 return false; |
209 } | 219 } |
210 return SSLErrorClassification::IsUserClockInThePast(now) || | 220 return SSLErrorClassification::IsUserClockInThePast(now) || |
211 SSLErrorClassification::IsUserClockInTheFuture(now); | 221 SSLErrorClassification::IsUserClockInTheFuture(now); |
212 } | 222 } |
213 | 223 |
| 224 // A helper function that actually sends the cert collection report over |
| 225 // the network. |
| 226 void FinishCertCollectionInternal( |
| 227 const base::WeakPtr<CertificateErrorReporter>& reporter, |
| 228 const std::string& hostname, |
| 229 const net::SSLInfo& ssl_info) { |
| 230 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 231 if (reporter) { |
| 232 reporter->SendReport( |
| 233 CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING, hostname, |
| 234 ssl_info); |
| 235 } |
| 236 } |
| 237 |
214 } // namespace | 238 } // namespace |
215 | 239 |
216 // static | 240 // static |
217 InterstitialPageDelegate::TypeID SSLBlockingPage::kTypeForTesting = | 241 InterstitialPageDelegate::TypeID SSLBlockingPage::kTypeForTesting = |
218 &SSLBlockingPage::kTypeForTesting; | 242 &SSLBlockingPage::kTypeForTesting; |
219 | 243 |
220 // Note that we always create a navigation entry with SSL errors. | 244 // Note that we always create a navigation entry with SSL errors. |
221 // No error happening loading a sub-resource triggers an interstitial so far. | 245 // No error happening loading a sub-resource triggers an interstitial so far. |
222 SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, | 246 SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, |
223 int cert_error, | 247 int cert_error, |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 load_time_data->SetString( | 454 load_time_data->SetString( |
431 "expirationDate", | 455 "expirationDate", |
432 base::TimeFormatShortDate(ssl_info_.cert->valid_expiry())); | 456 base::TimeFormatShortDate(ssl_info_.cert->valid_expiry())); |
433 load_time_data->SetString( | 457 load_time_data->SetString( |
434 "currentDate", base::TimeFormatShortDate(time_triggered_)); | 458 "currentDate", base::TimeFormatShortDate(time_triggered_)); |
435 std::vector<std::string> encoded_chain; | 459 std::vector<std::string> encoded_chain; |
436 ssl_info_.cert->GetPEMEncodedChain( | 460 ssl_info_.cert->GetPEMEncodedChain( |
437 &encoded_chain); | 461 &encoded_chain); |
438 load_time_data->SetString( | 462 load_time_data->SetString( |
439 "pem", JoinString(encoded_chain, std::string())); | 463 "pem", JoinString(encoded_chain, std::string())); |
| 464 |
| 465 PopulateExtendedReportingOption(load_time_data); |
| 466 } |
| 467 |
| 468 void SSLBlockingPage::PopulateExtendedReportingOption( |
| 469 base::DictionaryValue* load_time_data) { |
| 470 // Only show the checkbox if not off-the-record and if the |
| 471 // command-line option is set. |
| 472 const bool show = !web_contents()->GetBrowserContext()->IsOffTheRecord() && |
| 473 base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 474 switches::kEnableInvalidCertCollection); |
| 475 |
| 476 load_time_data->SetBoolean(interstitials::kDisplayCheckBox, show); |
| 477 if (!show) |
| 478 return; |
| 479 |
| 480 load_time_data->SetBoolean( |
| 481 interstitials::kBoxChecked, |
| 482 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled)); |
| 483 |
| 484 const std::string privacy_link = base::StringPrintf( |
| 485 interstitials::kPrivacyLinkHtml, CMD_OPEN_REPORTING_PRIVACY, |
| 486 l10n_util::GetStringUTF8(IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE).c_str()); |
| 487 |
| 488 load_time_data->SetString( |
| 489 interstitials::kOptInLink, |
| 490 l10n_util::GetStringFUTF16(IDS_SAFE_BROWSING_MALWARE_REPORTING_AGREE, |
| 491 base::UTF8ToUTF16(privacy_link))); |
440 } | 492 } |
441 | 493 |
442 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { | 494 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { |
443 int cert_id = content::CertStore::GetInstance()->StoreCert( | 495 int cert_id = content::CertStore::GetInstance()->StoreCert( |
444 ssl_info_.cert.get(), web_contents()->GetRenderProcessHost()->GetID()); | 496 ssl_info_.cert.get(), web_contents()->GetRenderProcessHost()->GetID()); |
445 DCHECK(cert_id); | 497 DCHECK(cert_id); |
446 | 498 |
447 entry->GetSSL().security_style = | 499 entry->GetSSL().security_style = |
448 content::SECURITY_STYLE_AUTHENTICATION_BROKEN; | 500 content::SECURITY_STYLE_AUTHENTICATION_BROKEN; |
449 entry->GetSSL().cert_id = cert_id; | 501 entry->GetSSL().cert_id = cert_id; |
(...skipping 11 matching lines...) Expand all Loading... |
461 case CMD_DONT_PROCEED: { | 513 case CMD_DONT_PROCEED: { |
462 interstitial_page()->DontProceed(); | 514 interstitial_page()->DontProceed(); |
463 break; | 515 break; |
464 } | 516 } |
465 case CMD_PROCEED: { | 517 case CMD_PROCEED: { |
466 if (danger_overridable_) { | 518 if (danger_overridable_) { |
467 interstitial_page()->Proceed(); | 519 interstitial_page()->Proceed(); |
468 } | 520 } |
469 break; | 521 break; |
470 } | 522 } |
| 523 case CMD_DO_REPORT: { |
| 524 SetReportingPreference(true); |
| 525 break; |
| 526 } |
| 527 case CMD_DONT_REPORT: { |
| 528 SetReportingPreference(false); |
| 529 break; |
| 530 } |
471 case CMD_SHOW_MORE_SECTION: { | 531 case CMD_SHOW_MORE_SECTION: { |
472 metrics_helper_->RecordUserInteraction( | 532 metrics_helper_->RecordUserInteraction( |
473 SecurityInterstitialMetricsHelper::SHOW_ADVANCED); | 533 SecurityInterstitialMetricsHelper::SHOW_ADVANCED); |
474 break; | 534 break; |
475 } | 535 } |
476 case CMD_OPEN_HELP_CENTER: { | 536 case CMD_OPEN_HELP_CENTER: { |
477 metrics_helper_->RecordUserInteraction( | 537 metrics_helper_->RecordUserInteraction( |
478 SecurityInterstitialMetricsHelper::SHOW_LEARN_MORE); | 538 SecurityInterstitialMetricsHelper::SHOW_LEARN_MORE); |
479 content::NavigationController::LoadURLParams help_page_params( | 539 content::NavigationController::LoadURLParams help_page_params( |
480 google_util::AppendGoogleLocaleParam( | 540 google_util::AppendGoogleLocaleParam( |
481 GURL(kHelpURL), g_browser_process->GetApplicationLocale())); | 541 GURL(kHelpURL), g_browser_process->GetApplicationLocale())); |
482 web_contents()->GetController().LoadURLWithParams(help_page_params); | 542 web_contents()->GetController().LoadURLWithParams(help_page_params); |
483 break; | 543 break; |
484 } | 544 } |
485 case CMD_RELOAD: { | 545 case CMD_RELOAD: { |
486 metrics_helper_->RecordUserInteraction( | 546 metrics_helper_->RecordUserInteraction( |
487 SecurityInterstitialMetricsHelper::RELOAD); | 547 SecurityInterstitialMetricsHelper::RELOAD); |
488 // The interstitial can't refresh itself. | 548 // The interstitial can't refresh itself. |
489 web_contents()->GetController().Reload(true); | 549 web_contents()->GetController().Reload(true); |
490 break; | 550 break; |
491 } | 551 } |
492 case CMD_OPEN_DATE_SETTINGS: { | 552 case CMD_OPEN_DATE_SETTINGS: { |
493 metrics_helper_->RecordUserInteraction( | 553 metrics_helper_->RecordUserInteraction( |
494 SecurityInterstitialMetricsHelper::OPEN_TIME_SETTINGS); | 554 SecurityInterstitialMetricsHelper::OPEN_TIME_SETTINGS); |
495 LaunchDateAndTimeSettings(); | 555 LaunchDateAndTimeSettings(); |
496 break; | 556 break; |
497 } | 557 } |
| 558 case CMD_OPEN_REPORTING_PRIVACY: |
| 559 metrics_helper_->RecordUserInteraction( |
| 560 SecurityInterstitialMetricsHelper::SHOW_PRIVACY_POLICY); |
| 561 OpenExtendedReportingPrivacyPolicy(); |
| 562 break; |
498 case CMD_OPEN_DIAGNOSTIC: | 563 case CMD_OPEN_DIAGNOSTIC: |
499 // Google doesn't currently have a transparency report for SSL. | 564 // Google doesn't currently have a transparency report for SSL. |
500 case CMD_DO_REPORT: | |
501 case CMD_DONT_REPORT: | |
502 case CMD_OPEN_REPORTING_PRIVACY: | |
503 // Chrome doesn't currently do Extended Reporting for SSL. | |
504 NOTREACHED() << "Unexpected command: " << command; | 565 NOTREACHED() << "Unexpected command: " << command; |
505 } | 566 } |
506 } | 567 } |
507 | 568 |
508 void SSLBlockingPage::OverrideRendererPrefs( | 569 void SSLBlockingPage::OverrideRendererPrefs( |
509 content::RendererPreferences* prefs) { | 570 content::RendererPreferences* prefs) { |
510 Profile* profile = Profile::FromBrowserContext( | 571 Profile* profile = Profile::FromBrowserContext( |
511 web_contents()->GetBrowserContext()); | 572 web_contents()->GetBrowserContext()); |
512 renderer_preferences_util::UpdateFromSystemSettings( | 573 renderer_preferences_util::UpdateFromSystemSettings( |
513 prefs, profile, web_contents()); | 574 prefs, profile, web_contents()); |
514 } | 575 } |
515 | 576 |
516 void SSLBlockingPage::OnProceed() { | 577 void SSLBlockingPage::OnProceed() { |
517 metrics_helper_->RecordUserDecision( | 578 metrics_helper_->RecordUserDecision( |
518 SecurityInterstitialMetricsHelper::PROCEED); | 579 SecurityInterstitialMetricsHelper::PROCEED); |
| 580 |
| 581 // Finish collection information about invalid certificates, if the |
| 582 // user opted in to. |
| 583 FinishCertCollection(); |
| 584 |
519 RecordSSLExpirationPageEventState( | 585 RecordSSLExpirationPageEventState( |
520 expired_but_previously_allowed_, true, overridable_); | 586 expired_but_previously_allowed_, true, overridable_); |
521 // Accepting the certificate resumes the loading of the page. | 587 // Accepting the certificate resumes the loading of the page. |
522 NotifyAllowCertificate(); | 588 NotifyAllowCertificate(); |
523 } | 589 } |
524 | 590 |
525 void SSLBlockingPage::OnDontProceed() { | 591 void SSLBlockingPage::OnDontProceed() { |
526 metrics_helper_->RecordUserDecision( | 592 metrics_helper_->RecordUserDecision( |
527 SecurityInterstitialMetricsHelper::DONT_PROCEED); | 593 SecurityInterstitialMetricsHelper::DONT_PROCEED); |
| 594 |
| 595 // Finish collection information about invalid certificates, if the |
| 596 // user opted in to. |
| 597 FinishCertCollection(); |
| 598 |
528 RecordSSLExpirationPageEventState( | 599 RecordSSLExpirationPageEventState( |
529 expired_but_previously_allowed_, false, overridable_); | 600 expired_but_previously_allowed_, false, overridable_); |
530 NotifyDenyCertificate(); | 601 NotifyDenyCertificate(); |
531 } | 602 } |
532 | 603 |
533 void SSLBlockingPage::NotifyDenyCertificate() { | 604 void SSLBlockingPage::NotifyDenyCertificate() { |
534 // It's possible that callback_ may not exist if the user clicks "Proceed" | 605 // It's possible that callback_ may not exist if the user clicks "Proceed" |
535 // followed by pressing the back button before the interstitial is hidden. | 606 // followed by pressing the back button before the interstitial is hidden. |
536 // In that case the certificate will still be treated as allowed. | 607 // In that case the certificate will still be treated as allowed. |
537 if (callback_.is_null()) | 608 if (callback_.is_null()) |
(...skipping 27 matching lines...) Expand all Loading... |
565 std::string SSLBlockingPage::GetSamplingEventName() const { | 636 std::string SSLBlockingPage::GetSamplingEventName() const { |
566 std::string event_name(kEventNameBase); | 637 std::string event_name(kEventNameBase); |
567 if (overridable_) | 638 if (overridable_) |
568 event_name.append(kEventOverridable); | 639 event_name.append(kEventOverridable); |
569 else | 640 else |
570 event_name.append(kEventNotOverridable); | 641 event_name.append(kEventNotOverridable); |
571 event_name.append(net::ErrorToString(cert_error_)); | 642 event_name.append(net::ErrorToString(cert_error_)); |
572 return event_name; | 643 return event_name; |
573 } | 644 } |
574 | 645 |
| 646 void SSLBlockingPage::FinishCertCollection() { |
| 647 base::ScopedClosureRunner scoped_callback( |
| 648 certificate_report_callback_for_testing_); |
| 649 |
| 650 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 651 switches::kEnableInvalidCertCollection) || |
| 652 web_contents()->GetBrowserContext()->IsOffTheRecord()) { |
| 653 return; |
| 654 } |
| 655 |
| 656 const bool enabled = |
| 657 IsPrefEnabled(prefs::kSafeBrowsingExtendedReportingEnabled); |
| 658 UMA_HISTOGRAM_BOOLEAN("SB2.ExtendedReportingIsEnabled", enabled); |
| 659 |
| 660 if (!enabled) |
| 661 return; |
| 662 |
| 663 if (certificate_report_callback_for_testing_.is_null()) |
| 664 scoped_callback.Reset(base::Bind(&base::DoNothing)); |
| 665 |
| 666 base::WeakPtr<CertificateErrorReporter> reporter = |
| 667 ProfileIOData::FromResourceContext( |
| 668 web_contents()->GetBrowserContext()->GetResourceContext()) |
| 669 ->certificate_error_reporter(); |
| 670 |
| 671 BrowserThread::PostTaskAndReply( |
| 672 BrowserThread::IO, FROM_HERE, |
| 673 base::Bind(FinishCertCollectionInternal, reporter, request_url().host(), |
| 674 ssl_info_), |
| 675 scoped_callback.Release()); |
| 676 } |
| 677 |
575 // static | 678 // static |
576 bool SSLBlockingPage::IsOptionsOverridable(int options_mask) { | 679 bool SSLBlockingPage::IsOptionsOverridable(int options_mask) { |
577 return (options_mask & SSLBlockingPage::OVERRIDABLE) && | 680 return (options_mask & SSLBlockingPage::OVERRIDABLE) && |
578 !(options_mask & SSLBlockingPage::STRICT_ENFORCEMENT); | 681 !(options_mask & SSLBlockingPage::STRICT_ENFORCEMENT); |
579 } | 682 } |
OLD | NEW |