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. 4 5 #include "chrome/browser/ssl/ssl_blocking_page.h" 6 7 #include "base/build_time.h" 8 #include "base/command_line.h" 9 #include "base/i18n/rtl.h" 10 #include "base/i18n/time_formatting.h" 11 #include "base/metrics/field_trial.h" 12 #include "base/metrics/histogram.h" 13 #include "base/process/launch.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_piece.h" 16 #include "base/strings/string_util.h" 17 #include "base/strings/stringprintf.h" 18 #include "base/strings/utf_string_conversions.h" 19 #include "base/time/time.h" 20 #include "base/values.h" 21 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/chrome_notification_types.h" 23 #include "chrome/browser/history/history_service_factory.h" 24 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/renderer_preferences_util.h" 26 #include "chrome/browser/ssl/ssl_error_classification.h" 27 #include "chrome/browser/ssl/ssl_error_info.h" 28 #include "chrome/common/chrome_switches.h" 29 #include "chrome/grit/chromium_strings.h" 30 #include "chrome/grit/generated_resources.h" 31 #include "components/google/core/browser/google_util.h" 32 #include "content/public/browser/cert_store.h" 33 #include "content/public/browser/interstitial_page.h" 34 #include "content/public/browser/navigation_controller.h" 35 #include "content/public/browser/navigation_entry.h" 36 #include "content/public/browser/notification_service.h" 37 #include "content/public/browser/notification_types.h" 38 #include "content/public/browser/render_process_host.h" 39 #include "content/public/browser/render_view_host.h" 40 #include "content/public/browser/web_contents.h" 41 #include "content/public/common/ssl_status.h" 42 #include "grit/browser_resources.h" 43 #include "net/base/hash_value.h" 44 #include "net/base/net_errors.h" 45 #include "net/base/net_util.h" 46 #include "ui/base/l10n/l10n_util.h" 47 #include "ui/base/resource/resource_bundle.h" 48 #include "ui/base/webui/jstemplate_builder.h" 49 #include "ui/base/webui/web_ui_util.h" 50 51 #if defined(ENABLE_EXTENSIONS) 52 #include "chrome/browser/extensions/api/experience_sampling_private/experience_sampling.h" 53 #endif 54 55 #if defined(OS_WIN) 56 #include "base/base_paths_win.h" 57 #include "base/path_service.h" 58 #include "base/strings/string16.h" 59 #include "base/win/windows_version.h" 60 #endif 61 62 #if defined(OS_CHROMEOS) 63 #include "chrome/browser/profiles/profile_manager.h" 64 #include "chrome/browser/ui/chrome_pages.h" 65 #include "chrome/common/url_constants.h" 66 #endif 67 68 using base::ASCIIToUTF16; 69 using base::TimeTicks; 70 using content::InterstitialPage; 71 using content::NavigationController; 72 using content::NavigationEntry; 73 74 #if defined(ENABLE_EXTENSIONS) 75 using extensions::ExperienceSamplingEvent; 76 #endif 77 78 namespace { 79 80 // URL for help page. 81 const char kHelpURL[] = "https://support.google.com/chrome/answer/4454607"; 82 83 // Constants for the Experience Sampling instrumentation. 84 #if defined(ENABLE_EXTENSIONS) 85 const char kEventNameBase[] = "ssl_interstitial_"; 86 const char kEventNotOverridable[] = "notoverridable_"; 87 const char kEventOverridable[] = "overridable_"; 88 #endif 89 90 // Events for UMA. Do not reorder or change! 91 enum SSLBlockingPageEvent { 92 SHOW_ALL, 93 SHOW_OVERRIDABLE, 94 PROCEED_OVERRIDABLE, 95 PROCEED_NAME, 96 PROCEED_DATE, 97 PROCEED_AUTHORITY, 98 DONT_PROCEED_OVERRIDABLE, 99 DONT_PROCEED_NAME, 100 DONT_PROCEED_DATE, 101 DONT_PROCEED_AUTHORITY, 102 MORE, 103 SHOW_UNDERSTAND, // Used by the summer 2013 Finch trial. Deprecated. 104 SHOW_INTERNAL_HOSTNAME, 105 PROCEED_INTERNAL_HOSTNAME, 106 SHOW_NEW_SITE, 107 PROCEED_NEW_SITE, 108 PROCEED_MANUAL_NONOVERRIDABLE, 109 // Captive Portal errors moved to ssl_error_classification. 110 DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED, 111 DEPRECATED_CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE, 112 DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED, 113 DEPRECATED_CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE, 114 DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE, 115 DEPRECATED_CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE, 116 DEPRECATED_CAPTIVE_PORTAL_DETECTED, 117 DEPRECATED_CAPTIVE_PORTAL_DETECTED_OVERRIDABLE, 118 UNUSED_BLOCKING_PAGE_EVENT, 119 }; 120 121 // Events for UMA. Do not reorder or change! 122 enum SSLExpirationAndDecision { 123 EXPIRED_AND_PROCEED, 124 EXPIRED_AND_DO_NOT_PROCEED, 125 NOT_EXPIRED_AND_PROCEED, 126 NOT_EXPIRED_AND_DO_NOT_PROCEED, 127 END_OF_SSL_EXPIRATION_AND_DECISION, 128 }; 129 130 void RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event) { 131 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl", 132 event, 133 UNUSED_BLOCKING_PAGE_EVENT); 134 } 135 136 void RecordSSLExpirationPageEventState(bool expired_but_previously_allowed, 137 bool proceed, 138 bool overridable) { 139 SSLExpirationAndDecision event; 140 if (expired_but_previously_allowed && proceed) 141 event = EXPIRED_AND_PROCEED; 142 else if (expired_but_previously_allowed && !proceed) 143 event = EXPIRED_AND_DO_NOT_PROCEED; 144 else if (!expired_but_previously_allowed && proceed) 145 event = NOT_EXPIRED_AND_PROCEED; 146 else 147 event = NOT_EXPIRED_AND_DO_NOT_PROCEED; 148 149 if (overridable) { 150 UMA_HISTOGRAM_ENUMERATION( 151 "interstitial.ssl.expiration_and_decision.overridable", 152 event, 153 END_OF_SSL_EXPIRATION_AND_DECISION); 154 } else { 155 UMA_HISTOGRAM_ENUMERATION( 156 "interstitial.ssl.expiration_and_decision.nonoverridable", 157 event, 158 END_OF_SSL_EXPIRATION_AND_DECISION); 159 } 160 } 161 162 void RecordSSLBlockingPageDetailedStats(bool proceed, 163 int cert_error, 164 bool overridable, 165 bool internal, 166 int num_visits, 167 bool expired_but_previously_allowed) { 168 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", 169 SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM); 170 RecordSSLExpirationPageEventState( 171 expired_but_previously_allowed, proceed, overridable); 172 if (!overridable) { 173 if (proceed) { 174 RecordSSLBlockingPageEventStats(PROCEED_MANUAL_NONOVERRIDABLE); 175 } 176 // Overridable is false if the user didn't have any option except to turn 177 // back. If that's the case, don't record some of the metrics. 178 return; 179 } 180 if (num_visits == 0) 181 RecordSSLBlockingPageEventStats(SHOW_NEW_SITE); 182 if (proceed) { 183 RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE); 184 if (internal) 185 RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME); 186 if (num_visits == 0) 187 RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE); 188 } else if (!proceed) { 189 RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE); 190 } 191 SSLErrorInfo::ErrorType type = SSLErrorInfo::NetErrorToErrorType(cert_error); 192 switch (type) { 193 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: { 194 if (proceed) 195 RecordSSLBlockingPageEventStats(PROCEED_NAME); 196 else 197 RecordSSLBlockingPageEventStats(DONT_PROCEED_NAME); 198 break; 199 } 200 case SSLErrorInfo::CERT_DATE_INVALID: { 201 if (proceed) 202 RecordSSLBlockingPageEventStats(PROCEED_DATE); 203 else 204 RecordSSLBlockingPageEventStats(DONT_PROCEED_DATE); 205 break; 206 } 207 case SSLErrorInfo::CERT_AUTHORITY_INVALID: { 208 if (proceed) 209 RecordSSLBlockingPageEventStats(PROCEED_AUTHORITY); 210 else 211 RecordSSLBlockingPageEventStats(DONT_PROCEED_AUTHORITY); 212 break; 213 } 214 default: { 215 break; 216 } 217 } 218 } 219 220 void LaunchDateAndTimeSettings() { 221 #if defined(OS_CHROMEOS) 222 std::string sub_page = std::string(chrome::kSearchSubPage) + "#" + 223 l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME); 224 chrome::ShowSettingsSubPageForProfile( 225 ProfileManager::GetActiveUserProfile(), sub_page); 226 return; 227 #elif defined(OS_ANDROID) 228 CommandLine command(base::FilePath("/system/bin/am")); 229 command.AppendArg("start"); 230 command.AppendArg( 231 "'com.android.settings/.Settings$DateTimeSettingsActivity'"); 232 #elif defined(OS_IOS) 233 // Apparently, iOS really does not have a way to launch the date and time 234 // settings. Weird. TODO(palmer): Do something more graceful than ignoring 235 // the user's click! crbug.com/394993 236 return; 237 #elif defined(OS_LINUX) 238 struct ClockCommand { 239 const char* pathname; 240 const char* argument; 241 }; 242 static const ClockCommand kClockCommands[] = { 243 // GNOME 244 // 245 // NOTE: On old Ubuntu, naming control panels doesn't work, so it 246 // opens the overview. This will have to be good enough. 247 { "/usr/bin/gnome-control-center", "datetime" }, 248 { "/usr/local/bin/gnome-control-center", "datetime" }, 249 { "/opt/bin/gnome-control-center", "datetime" }, 250 // KDE 251 { "/usr/bin/kcmshell4", "clock" }, 252 { "/usr/local/bin/kcmshell4", "clock" }, 253 { "/opt/bin/kcmshell4", "clock" }, 254 }; 255 256 CommandLine command(base::FilePath("")); 257 for (size_t i = 0; i < arraysize(kClockCommands); ++i) { 258 base::FilePath pathname(kClockCommands[i].pathname); 259 if (base::PathExists(pathname)) { 260 command.SetProgram(pathname); 261 command.AppendArg(kClockCommands[i].argument); 262 break; 263 } 264 } 265 if (command.GetProgram().empty()) { 266 // Alas, there is nothing we can do. 267 return; 268 } 269 #elif defined(OS_MACOSX) 270 CommandLine command(base::FilePath("/usr/bin/open")); 271 command.AppendArg("/System/Library/PreferencePanes/DateAndTime.prefPane"); 272 #elif defined(OS_WIN) 273 base::FilePath path; 274 PathService::Get(base::DIR_SYSTEM, &path); 275 static const base::char16 kControlPanelExe[] = L"control.exe"; 276 path = path.Append(base::string16(kControlPanelExe)); 277 CommandLine command(path); 278 command.AppendArg(std::string("/name")); 279 command.AppendArg(std::string("Microsoft.DateAndTime")); 280 #else 281 return; 282 #endif 283 284 #if !defined(OS_CHROMEOS) 285 base::LaunchOptions options; 286 options.wait = false; 287 #if defined(OS_LINUX) 288 options.allow_new_privs = true; 289 #endif 290 base::LaunchProcess(command, options, NULL); 291 #endif 292 } 293 294 bool IsErrorDueToBadClock(const base::Time& now, int error) { 295 if (SSLErrorInfo::NetErrorToErrorType(error) != 296 SSLErrorInfo::CERT_DATE_INVALID) { 297 return false; 298 } 299 return SSLErrorClassification::IsUserClockInThePast(now) || 300 SSLErrorClassification::IsUserClockInTheFuture(now); 301 } 302 303 } // namespace 304 305 // Note that we always create a navigation entry with SSL errors. 306 // No error happening loading a sub-resource triggers an interstitial so far. 307 SSLBlockingPage::SSLBlockingPage(content::WebContents* web_contents, 308 int cert_error, 309 const net::SSLInfo& ssl_info, 310 const GURL& request_url, 311 int options_mask, 312 const base::Callback<void(bool)>& callback) 313 : callback_(callback), 314 web_contents_(web_contents), 315 cert_error_(cert_error), 316 ssl_info_(ssl_info), 317 request_url_(request_url), 318 overridable_(options_mask & OVERRIDABLE && 319 !(options_mask & STRICT_ENFORCEMENT)), 320 strict_enforcement_((options_mask & STRICT_ENFORCEMENT) != 0), 321 interstitial_page_(NULL), 322 internal_(false), 323 num_visits_(-1), 324 expired_but_previously_allowed_( 325 (options_mask & EXPIRED_BUT_PREVIOUSLY_ALLOWED) != 0) { 326 Profile* profile = Profile::FromBrowserContext( 327 web_contents->GetBrowserContext()); 328 // For UMA stats. 329 if (net::IsHostnameNonUnique(request_url_.HostNoBrackets())) 330 internal_ = true; 331 RecordSSLBlockingPageEventStats(SHOW_ALL); 332 if (overridable_) { 333 RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE); 334 if (internal_) 335 RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME); 336 HistoryService* history_service = HistoryServiceFactory::GetForProfile( 337 profile, Profile::EXPLICIT_ACCESS); 338 if (history_service) { 339 history_service->GetVisibleVisitCountToHost( 340 request_url_, 341 base::Bind(&SSLBlockingPage::OnGotHistoryCount, 342 base::Unretained(this)), 343 &request_tracker_); 344 } 345 } 346 347 ssl_error_classification_.reset(new SSLErrorClassification( 348 web_contents_, 349 base::Time::NowFromSystemTime(), 350 request_url_, 351 cert_error_, 352 *ssl_info_.cert.get())); 353 ssl_error_classification_->RecordUMAStatistics(overridable_); 354 355 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 356 ssl_error_classification_->RecordCaptivePortalUMAStatistics(overridable_); 357 #endif 358 359 #if defined(ENABLE_EXTENSIONS) 360 // ExperienceSampling: Set up new sampling event for this interstitial. 361 std::string event_name(kEventNameBase); 362 if (overridable_ && !strict_enforcement_) 363 event_name.append(kEventOverridable); 364 else 365 event_name.append(kEventNotOverridable); 366 event_name.append(net::ErrorToString(cert_error_)); 367 sampling_event_.reset(new ExperienceSamplingEvent( 368 event_name, 369 request_url_, 370 web_contents_->GetLastCommittedURL(), 371 web_contents_->GetBrowserContext())); 372 #endif 373 374 // Creating an interstitial without showing (e.g. from chrome://interstitials) 375 // it leaks memory, so don't create it here. 376 } 377 378 SSLBlockingPage::~SSLBlockingPage() { 379 // InvalidCommonNameSeverityScore() and InvalidDateSeverityScore() are in the 380 // destructor because they depend on knowing whether captive portal detection 381 // happened before the user made a decision. 382 SSLErrorInfo::ErrorType type = 383 SSLErrorInfo::NetErrorToErrorType(cert_error_); 384 switch (type) { 385 case SSLErrorInfo::CERT_DATE_INVALID: 386 ssl_error_classification_->InvalidDateSeverityScore(); 387 break; 388 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: 389 ssl_error_classification_->InvalidCommonNameSeverityScore(); 390 break; 391 default: 392 break; 393 } 394 if (!callback_.is_null()) { 395 RecordSSLBlockingPageDetailedStats(false, 396 cert_error_, 397 overridable_, 398 internal_, 399 num_visits_, 400 expired_but_previously_allowed_); 401 // The page is closed without the user having chosen what to do, default to 402 // deny. 403 NotifyDenyCertificate(); 404 } 405 } 406 407 void SSLBlockingPage::Show() { 408 DCHECK(!interstitial_page_); 409 interstitial_page_ = InterstitialPage::Create( 410 web_contents_, true, request_url_, this); 411 interstitial_page_->Show(); 412 } 413 414 std::string SSLBlockingPage::GetHTMLContents() { 415 base::DictionaryValue load_time_data; 416 base::string16 url(ASCIIToUTF16(request_url_.host())); 417 if (base::i18n::IsRTL()) 418 base::i18n::WrapStringWithLTRFormatting(&url); 419 webui::SetFontAndTextDirection(&load_time_data); 420 421 // Shared values for both the overridable and non-overridable versions. 422 load_time_data.SetBoolean("ssl", true); 423 load_time_data.SetBoolean("overridable", overridable_); 424 load_time_data.SetString( 425 "tabTitle", l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE)); 426 load_time_data.SetString( 427 "heading", l10n_util::GetStringUTF16(IDS_SSL_V2_HEADING)); 428 429 base::Time now = base::Time::NowFromSystemTime(); 430 bool bad_clock = IsErrorDueToBadClock(now, cert_error_); 431 if (bad_clock) { 432 load_time_data.SetString("primaryParagraph", 433 l10n_util::GetStringFUTF16( 434 IDS_SSL_CLOCK_ERROR, 435 url, 436 base::TimeFormatShortDate(now))); 437 } else { 438 load_time_data.SetString( 439 "primaryParagraph", 440 l10n_util::GetStringFUTF16(IDS_SSL_V2_PRIMARY_PARAGRAPH, url)); 441 } 442 443 load_time_data.SetString( 444 "openDetails", 445 l10n_util::GetStringUTF16(IDS_SSL_V2_OPEN_DETAILS_BUTTON)); 446 load_time_data.SetString( 447 "closeDetails", 448 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOSE_DETAILS_BUTTON)); 449 load_time_data.SetString("errorCode", net::ErrorToString(cert_error_)); 450 451 if (overridable_) { 452 SSLErrorInfo error_info = 453 SSLErrorInfo::CreateError( 454 SSLErrorInfo::NetErrorToErrorType(cert_error_), 455 ssl_info_.cert.get(), 456 request_url_); 457 if (bad_clock) { 458 load_time_data.SetString("explanationParagraph", 459 l10n_util::GetStringFUTF16( 460 IDS_SSL_CLOCK_ERROR_EXPLANATION, url)); 461 } else { 462 load_time_data.SetString("explanationParagraph", error_info.details()); 463 } 464 load_time_data.SetString( 465 "primaryButtonText", 466 l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON)); 467 load_time_data.SetString( 468 "finalParagraph", 469 l10n_util::GetStringFUTF16(IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH, 470 url)); 471 } else { 472 SSLErrorInfo::ErrorType type = 473 SSLErrorInfo::NetErrorToErrorType(cert_error_); 474 if (type == SSLErrorInfo::CERT_INVALID && SSLErrorClassification:: 475 MaybeWindowsLacksSHA256Support()) { 476 load_time_data.SetString( 477 "explanationParagraph", 478 l10n_util::GetStringFUTF16( 479 IDS_SSL_NONOVERRIDABLE_MORE_INVALID_SP3, url)); 480 } else if (bad_clock) { 481 load_time_data.SetString("explanationParagraph", 482 l10n_util::GetStringFUTF16( 483 IDS_SSL_CLOCK_ERROR_EXPLANATION, url)); 484 } else { 485 load_time_data.SetString("explanationParagraph", 486 l10n_util::GetStringFUTF16( 487 IDS_SSL_NONOVERRIDABLE_MORE, url)); 488 } 489 load_time_data.SetString( 490 "primaryButtonText", 491 l10n_util::GetStringUTF16(IDS_SSL_NONOVERRIDABLE_RELOAD_BUTTON)); 492 // Customize the help link depending on the specific error type. 493 // Only mark as HSTS if none of the more specific error types apply, and use 494 // INVALID as a fallback if no other string is appropriate. 495 load_time_data.SetInteger("errorType", type); 496 int help_string = IDS_SSL_NONOVERRIDABLE_INVALID; 497 switch (type) { 498 case SSLErrorInfo::CERT_REVOKED: 499 help_string = IDS_SSL_NONOVERRIDABLE_REVOKED; 500 break; 501 case SSLErrorInfo::CERT_PINNED_KEY_MISSING: 502 help_string = IDS_SSL_NONOVERRIDABLE_PINNED; 503 break; 504 case SSLErrorInfo::CERT_INVALID: 505 help_string = IDS_SSL_NONOVERRIDABLE_INVALID; 506 break; 507 default: 508 if (strict_enforcement_) 509 help_string = IDS_SSL_NONOVERRIDABLE_HSTS; 510 } 511 load_time_data.SetString( 512 "finalParagraph", l10n_util::GetStringFUTF16(help_string, url)); 513 } 514 515 // Set debugging information at the bottom of the warning. 516 load_time_data.SetString( 517 "subject", ssl_info_.cert->subject().GetDisplayName()); 518 load_time_data.SetString( 519 "issuer", ssl_info_.cert->issuer().GetDisplayName()); 520 load_time_data.SetString( 521 "expirationDate", 522 base::TimeFormatShortDate(ssl_info_.cert->valid_expiry())); 523 load_time_data.SetString( 524 "currentDate", base::TimeFormatShortDate(now)); 525 std::vector<std::string> encoded_chain; 526 ssl_info_.cert->GetPEMEncodedChain(&encoded_chain); 527 load_time_data.SetString("pem", JoinString(encoded_chain, std::string())); 528 529 base::StringPiece html( 530 ResourceBundle::GetSharedInstance().GetRawDataResource( 531 IRD_SECURITY_INTERSTITIAL_HTML)); 532 webui::UseVersion2 version; 533 return webui::GetI18nTemplateHtml(html, &load_time_data); 534 } 535 536 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { 537 int cert_id = content::CertStore::GetInstance()->StoreCert( 538 ssl_info_.cert.get(), web_contents_->GetRenderProcessHost()->GetID()); 539 DCHECK(cert_id); 540 541 entry->GetSSL().security_style = 542 content::SECURITY_STYLE_AUTHENTICATION_BROKEN; 543 entry->GetSSL().cert_id = cert_id; 544 entry->GetSSL().cert_status = ssl_info_.cert_status; 545 entry->GetSSL().security_bits = ssl_info_.security_bits; 546 } 547 548 // This handles the commands sent from the interstitial JavaScript. They are 549 // defined in chrome/browser/resources/ssl/ssl_errors_common.js. 550 // DO NOT reorder or change this logic without also changing the JavaScript! 551 void SSLBlockingPage::CommandReceived(const std::string& command) { 552 int cmd = 0; 553 bool retval = base::StringToInt(command, &cmd); 554 DCHECK(retval); 555 switch (cmd) { 556 case CMD_DONT_PROCEED: { 557 interstitial_page_->DontProceed(); 558 break; 559 } 560 case CMD_PROCEED: { 561 interstitial_page_->Proceed(); 562 break; 563 } 564 case CMD_MORE: { 565 RecordSSLBlockingPageEventStats(MORE); 566 #if defined(ENABLE_EXTENSIONS) 567 if (sampling_event_.get()) 568 sampling_event_->set_has_viewed_details(true); 569 #endif 570 break; 571 } 572 case CMD_RELOAD: { 573 // The interstitial can't refresh itself. 574 web_contents_->GetController().Reload(true); 575 break; 576 } 577 case CMD_HELP: { 578 content::NavigationController::LoadURLParams help_page_params( 579 google_util::AppendGoogleLocaleParam( 580 GURL(kHelpURL), g_browser_process->GetApplicationLocale())); 581 #if defined(ENABLE_EXTENSIONS) 582 if (sampling_event_.get()) 583 sampling_event_->set_has_viewed_learn_more(true); 584 #endif 585 web_contents_->GetController().LoadURLWithParams(help_page_params); 586 break; 587 } 588 case CMD_CLOCK: { 589 LaunchDateAndTimeSettings(); 590 break; 591 } 592 default: { 593 NOTREACHED(); 594 } 595 } 596 } 597 598 void SSLBlockingPage::OverrideRendererPrefs( 599 content::RendererPreferences* prefs) { 600 Profile* profile = Profile::FromBrowserContext( 601 web_contents_->GetBrowserContext()); 602 renderer_preferences_util::UpdateFromSystemSettings(prefs, profile); 603 } 604 605 void SSLBlockingPage::OnProceed() { 606 RecordSSLBlockingPageDetailedStats(true, 607 cert_error_, 608 overridable_, 609 internal_, 610 num_visits_, 611 expired_but_previously_allowed_); 612 #if defined(ENABLE_EXTENSIONS) 613 // ExperienceSampling: Notify that user decided to proceed. 614 if (sampling_event_.get()) 615 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kProceed); 616 #endif 617 618 // Accepting the certificate resumes the loading of the page. 619 NotifyAllowCertificate(); 620 } 621 622 void SSLBlockingPage::OnDontProceed() { 623 RecordSSLBlockingPageDetailedStats(false, 624 cert_error_, 625 overridable_, 626 internal_, 627 num_visits_, 628 expired_but_previously_allowed_); 629 #if defined(ENABLE_EXTENSIONS) 630 // ExperienceSampling: Notify that user decided to not proceed. 631 // This also occurs if the user navigates away or closes the tab. 632 if (sampling_event_.get()) 633 sampling_event_->CreateUserDecisionEvent(ExperienceSamplingEvent::kDeny); 634 #endif 635 NotifyDenyCertificate(); 636 } 637 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; 644 645 callback_.Run(false); 646 callback_.Reset(); 647 } 648 649 void SSLBlockingPage::NotifyAllowCertificate() { 650 DCHECK(!callback_.is_null()); 651 652 callback_.Run(true); 653 callback_.Reset(); 654 } 655 656 // static 657 void SSLBlockingPage::SetExtraInfo( 658 base::DictionaryValue* strings, 659 const std::vector<base::string16>& extra_info) { 660 DCHECK_LT(extra_info.size(), 5U); // We allow 5 paragraphs max. 661 const char* keys[5] = { 662 "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5" 663 }; 664 int i; 665 for (i = 0; i < static_cast<int>(extra_info.size()); i++) { 666 strings->SetString(keys[i], extra_info[i]); 667 } 668 for (; i < 5; i++) { 669 strings->SetString(keys[i], std::string()); 670 } 671 } 672 673 void SSLBlockingPage::OnGotHistoryCount(bool success, 674 int num_visits, 675 base::Time first_visit) { 676 num_visits_ = num_visits; 677 } 678