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/command_line.h" 8 #include "base/i18n/rtl.h" 9 #include "base/metrics/field_trial.h" 10 #include "base/metrics/histogram.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_piece.h" 13 #include "base/strings/stringprintf.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/values.h" 16 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/history/history_service_factory.h" 18 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/renderer_preferences_util.h" 20 #include "chrome/browser/ssl/ssl_error_info.h" 21 #include "chrome/common/chrome_switches.h" 22 #include "content/public/browser/cert_store.h" 23 #include "content/public/browser/interstitial_page.h" 24 #include "content/public/browser/navigation_controller.h" 25 #include "content/public/browser/navigation_entry.h" 26 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_types.h" 28 #include "content/public/browser/render_process_host.h" 29 #include "content/public/browser/render_view_host.h" 30 #include "content/public/browser/web_contents.h" 31 #include "content/public/common/ssl_status.h" 32 #include "grit/app_locale_settings.h" 33 #include "grit/browser_resources.h" 34 #include "grit/generated_resources.h" 35 #include "net/base/hash_value.h" 36 #include "net/base/net_errors.h" 37 #include "net/base/net_util.h" 38 #include "ui/base/l10n/l10n_util.h" 39 #include "ui/base/resource/resource_bundle.h" 40 #include "ui/base/webui/jstemplate_builder.h" 41 #include "ui/base/webui/web_ui_util.h" 42 43 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 44 #include "chrome/browser/captive_portal/captive_portal_service.h" 45 #include "chrome/browser/captive_portal/captive_portal_service_factory.h" 46 #endif 47 48 #if defined(OS_WIN) 49 #include "base/win/windows_version.h" 50 #endif 51 52 using base::ASCIIToUTF16; 53 using base::TimeTicks; 54 using content::InterstitialPage; 55 using content::NavigationController; 56 using content::NavigationEntry; 57 58 namespace { 59 60 // Events for UMA. Do not reorder or change! 61 enum SSLBlockingPageEvent { 62 SHOW_ALL, 63 SHOW_OVERRIDABLE, 64 PROCEED_OVERRIDABLE, 65 PROCEED_NAME, 66 PROCEED_DATE, 67 PROCEED_AUTHORITY, 68 DONT_PROCEED_OVERRIDABLE, 69 DONT_PROCEED_NAME, 70 DONT_PROCEED_DATE, 71 DONT_PROCEED_AUTHORITY, 72 MORE, 73 SHOW_UNDERSTAND, // Used by the summer 2013 Finch trial. Deprecated. 74 SHOW_INTERNAL_HOSTNAME, 75 PROCEED_INTERNAL_HOSTNAME, 76 SHOW_NEW_SITE, 77 PROCEED_NEW_SITE, 78 PROCEED_MANUAL_NONOVERRIDABLE, 79 CAPTIVE_PORTAL_DETECTION_ENABLED, 80 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE, 81 CAPTIVE_PORTAL_PROBE_COMPLETED, 82 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE, 83 CAPTIVE_PORTAL_NO_RESPONSE, 84 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE, 85 CAPTIVE_PORTAL_DETECTED, 86 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE, 87 UNUSED_BLOCKING_PAGE_EVENT, 88 }; 89 90 void RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event) { 91 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl", 92 event, 93 UNUSED_BLOCKING_PAGE_EVENT); 94 } 95 96 void RecordSSLBlockingPageDetailedStats( 97 bool proceed, 98 int cert_error, 99 bool overridable, 100 bool internal, 101 int num_visits, 102 bool captive_portal_detection_enabled, 103 bool captive_portal_probe_completed, 104 bool captive_portal_no_response, 105 bool captive_portal_detected) { 106 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type", 107 SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM); 108 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 109 if (captive_portal_detection_enabled) 110 RecordSSLBlockingPageEventStats( 111 overridable ? 112 CAPTIVE_PORTAL_DETECTION_ENABLED_OVERRIDABLE : 113 CAPTIVE_PORTAL_DETECTION_ENABLED); 114 if (captive_portal_probe_completed) 115 RecordSSLBlockingPageEventStats( 116 overridable ? 117 CAPTIVE_PORTAL_PROBE_COMPLETED_OVERRIDABLE : 118 CAPTIVE_PORTAL_PROBE_COMPLETED); 119 // Log only one of portal detected and no response results. 120 if (captive_portal_detected) 121 RecordSSLBlockingPageEventStats( 122 overridable ? 123 CAPTIVE_PORTAL_DETECTED_OVERRIDABLE : 124 CAPTIVE_PORTAL_DETECTED); 125 else if (captive_portal_no_response) 126 RecordSSLBlockingPageEventStats( 127 overridable ? 128 CAPTIVE_PORTAL_NO_RESPONSE_OVERRIDABLE : 129 CAPTIVE_PORTAL_NO_RESPONSE); 130 #endif 131 if (!overridable) { 132 if (proceed) { 133 RecordSSLBlockingPageEventStats(PROCEED_MANUAL_NONOVERRIDABLE); 134 } 135 // Overridable is false if the user didn't have any option except to turn 136 // back. If that's the case, don't record some of the metrics. 137 return; 138 } 139 if (num_visits == 0) 140 RecordSSLBlockingPageEventStats(SHOW_NEW_SITE); 141 if (proceed) { 142 RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE); 143 if (internal) 144 RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME); 145 if (num_visits == 0) 146 RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE); 147 } else if (!proceed) { 148 RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE); 149 } 150 SSLErrorInfo::ErrorType type = SSLErrorInfo::NetErrorToErrorType(cert_error); 151 switch (type) { 152 case SSLErrorInfo::CERT_COMMON_NAME_INVALID: { 153 if (proceed) 154 RecordSSLBlockingPageEventStats(PROCEED_NAME); 155 else 156 RecordSSLBlockingPageEventStats(DONT_PROCEED_NAME); 157 break; 158 } 159 case SSLErrorInfo::CERT_DATE_INVALID: { 160 if (proceed) 161 RecordSSLBlockingPageEventStats(PROCEED_DATE); 162 else 163 RecordSSLBlockingPageEventStats(DONT_PROCEED_DATE); 164 break; 165 } 166 case SSLErrorInfo::CERT_AUTHORITY_INVALID: { 167 if (proceed) 168 RecordSSLBlockingPageEventStats(PROCEED_AUTHORITY); 169 else 170 RecordSSLBlockingPageEventStats(DONT_PROCEED_AUTHORITY); 171 break; 172 } 173 default: { 174 break; 175 } 176 } 177 } 178 179 } // namespace 180 181 // Note that we always create a navigation entry with SSL errors. 182 // No error happening loading a sub-resource triggers an interstitial so far. 183 SSLBlockingPage::SSLBlockingPage( 184 content::WebContents* web_contents, 185 int cert_error, 186 const net::SSLInfo& ssl_info, 187 const GURL& request_url, 188 bool overridable, 189 bool strict_enforcement, 190 const base::Callback<void(bool)>& callback) 191 : callback_(callback), 192 web_contents_(web_contents), 193 cert_error_(cert_error), 194 ssl_info_(ssl_info), 195 request_url_(request_url), 196 overridable_(overridable), 197 strict_enforcement_(strict_enforcement), 198 internal_(false), 199 num_visits_(-1), 200 captive_portal_detection_enabled_(false), 201 captive_portal_probe_completed_(false), 202 captive_portal_no_response_(false), 203 captive_portal_detected_(false) { 204 Profile* profile = Profile::FromBrowserContext( 205 web_contents->GetBrowserContext()); 206 // For UMA stats. 207 if (net::IsHostnameNonUnique(request_url_.HostNoBrackets())) 208 internal_ = true; 209 RecordSSLBlockingPageEventStats(SHOW_ALL); 210 if (overridable_ && !strict_enforcement_) { 211 RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE); 212 if (internal_) 213 RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME); 214 HistoryService* history_service = HistoryServiceFactory::GetForProfile( 215 profile, Profile::EXPLICIT_ACCESS); 216 if (history_service) { 217 history_service->GetVisibleVisitCountToHost( 218 request_url_, 219 &request_consumer_, 220 base::Bind(&SSLBlockingPage::OnGotHistoryCount, 221 base::Unretained(this))); 222 } 223 } 224 225 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 226 CaptivePortalService* captive_portal_service = 227 CaptivePortalServiceFactory::GetForProfile(profile); 228 captive_portal_detection_enabled_ = captive_portal_service ->enabled(); 229 captive_portal_service ->DetectCaptivePortal(); 230 registrar_.Add(this, 231 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT, 232 content::Source<Profile>(profile)); 233 #endif 234 235 interstitial_page_ = InterstitialPage::Create( 236 web_contents_, true, request_url, this); 237 interstitial_page_->Show(); 238 } 239 240 SSLBlockingPage::~SSLBlockingPage() { 241 if (!callback_.is_null()) { 242 RecordSSLBlockingPageDetailedStats(false, 243 cert_error_, 244 overridable_ && !strict_enforcement_, 245 internal_, 246 num_visits_, 247 captive_portal_detection_enabled_, 248 captive_portal_probe_completed_, 249 captive_portal_no_response_, 250 captive_portal_detected_); 251 // The page is closed without the user having chosen what to do, default to 252 // deny. 253 NotifyDenyCertificate(); 254 } 255 } 256 257 std::string SSLBlockingPage::GetHTMLContents() { 258 if (CommandLine::ForCurrentProcess()->HasSwitch( 259 switches::kSSLInterstitialVersionV1) || 260 base::FieldTrialList::FindFullName("SSLInterstitialVersion") == "V1") { 261 return GetHTMLContentsV1(); 262 } 263 return GetHTMLContentsV2(); 264 } 265 266 std::string SSLBlockingPage::GetHTMLContentsV1() { 267 base::DictionaryValue strings; 268 int resource_id; 269 if (overridable_ && !strict_enforcement_) { 270 // Let's build the overridable error page. 271 SSLErrorInfo error_info = 272 SSLErrorInfo::CreateError( 273 SSLErrorInfo::NetErrorToErrorType(cert_error_), 274 ssl_info_.cert.get(), 275 request_url_); 276 277 resource_id = IDR_SSL_ROAD_BLOCK_HTML; 278 strings.SetString("headLine", error_info.title()); 279 strings.SetString("description", error_info.details()); 280 strings.SetString("moreInfoTitle", 281 l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_TITLE)); 282 SetExtraInfo(&strings, error_info.extra_information()); 283 284 strings.SetString( 285 "exit", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_EXIT)); 286 strings.SetString( 287 "title", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_TITLE)); 288 strings.SetString( 289 "proceed", l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_PAGE_PROCEED)); 290 strings.SetString( 291 "reasonForNotProceeding", l10n_util::GetStringUTF16( 292 IDS_SSL_OVERRIDABLE_PAGE_SHOULD_NOT_PROCEED)); 293 strings.SetString("errorType", "overridable"); 294 strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr"); 295 } else { 296 // Let's build the blocking error page. 297 resource_id = IDR_SSL_BLOCKING_HTML; 298 299 // Strings that are not dependent on the URL. 300 strings.SetString( 301 "title", l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TITLE)); 302 strings.SetString( 303 "reloadMsg", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_RELOAD)); 304 strings.SetString( 305 "more", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_MORE)); 306 strings.SetString( 307 "less", l10n_util::GetStringUTF16(IDS_ERRORPAGES_BUTTON_LESS)); 308 strings.SetString( 309 "moreTitle", 310 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_MORE_TITLE)); 311 strings.SetString( 312 "techTitle", 313 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TECH_TITLE)); 314 315 // Strings that are dependent on the URL. 316 base::string16 url(ASCIIToUTF16(request_url_.host())); 317 bool rtl = base::i18n::IsRTL(); 318 strings.SetString("textDirection", rtl ? "rtl" : "ltr"); 319 if (rtl) 320 base::i18n::WrapStringWithLTRFormatting(&url); 321 strings.SetString( 322 "headline", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HEADLINE, 323 url.c_str())); 324 strings.SetString( 325 "message", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_BODY_TEXT, 326 url.c_str())); 327 strings.SetString( 328 "moreMessage", 329 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_MORE_TEXT, 330 url.c_str())); 331 strings.SetString("reloadUrl", request_url_.spec()); 332 333 // Strings that are dependent on the error type. 334 SSLErrorInfo::ErrorType type = 335 SSLErrorInfo::NetErrorToErrorType(cert_error_); 336 base::string16 errorType; 337 if (type == SSLErrorInfo::CERT_REVOKED) { 338 errorType = base::string16(ASCIIToUTF16("Key revocation")); 339 strings.SetString( 340 "failure", 341 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_REVOKED)); 342 } else if (type == SSLErrorInfo::CERT_INVALID) { 343 errorType = base::string16(ASCIIToUTF16("Malformed certificate")); 344 strings.SetString( 345 "failure", 346 l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_FORMATTED)); 347 } else if (type == SSLErrorInfo::CERT_PINNED_KEY_MISSING) { 348 errorType = base::string16(ASCIIToUTF16("Certificate pinning failure")); 349 strings.SetString( 350 "failure", 351 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_PINNING, 352 url.c_str())); 353 } else if (type == SSLErrorInfo::CERT_WEAK_KEY_DH) { 354 errorType = base::string16(ASCIIToUTF16("Weak DH public key")); 355 strings.SetString( 356 "failure", 357 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_WEAK_DH, 358 url.c_str())); 359 } else { 360 // HSTS failure. 361 errorType = base::string16(ASCIIToUTF16("HSTS failure")); 362 strings.SetString( 363 "failure", 364 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HSTS, url.c_str())); 365 } 366 if (rtl) 367 base::i18n::WrapStringWithLTRFormatting(&errorType); 368 strings.SetString( 369 "errorType", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_ERROR, 370 errorType.c_str())); 371 372 // Strings that display the invalid cert. 373 base::string16 subject( 374 ASCIIToUTF16(ssl_info_.cert->subject().GetDisplayName())); 375 base::string16 issuer( 376 ASCIIToUTF16(ssl_info_.cert->issuer().GetDisplayName())); 377 std::string hashes; 378 for (std::vector<net::HashValue>::const_iterator it = 379 ssl_info_.public_key_hashes.begin(); 380 it != ssl_info_.public_key_hashes.end(); 381 ++it) { 382 base::StringAppendF(&hashes, "%s ", it->ToString().c_str()); 383 } 384 base::string16 fingerprint(ASCIIToUTF16(hashes)); 385 if (rtl) { 386 // These are always going to be LTR. 387 base::i18n::WrapStringWithLTRFormatting(&subject); 388 base::i18n::WrapStringWithLTRFormatting(&issuer); 389 base::i18n::WrapStringWithLTRFormatting(&fingerprint); 390 } 391 strings.SetString( 392 "subject", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_SUBJECT, 393 subject.c_str())); 394 strings.SetString( 395 "issuer", l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_ISSUER, 396 issuer.c_str())); 397 strings.SetString( 398 "fingerprint", 399 l10n_util::GetStringFUTF16(IDS_SSL_BLOCKING_PAGE_HASHES, 400 fingerprint.c_str())); 401 } 402 403 base::StringPiece html( 404 ResourceBundle::GetSharedInstance().GetRawDataResource( 405 resource_id)); 406 return webui::GetI18nTemplateHtml(html, &strings); 407 } 408 409 std::string SSLBlockingPage::GetHTMLContentsV2() { 410 base::DictionaryValue load_time_data; 411 base::string16 url(ASCIIToUTF16(request_url_.host())); 412 if (base::i18n::IsRTL()) 413 base::i18n::WrapStringWithLTRFormatting(&url); 414 webui::SetFontAndTextDirection(&load_time_data); 415 416 // Shared values for both the overridable and non-overridable versions. 417 load_time_data.SetBoolean("ssl", true); 418 load_time_data.SetBoolean( 419 "overridable", overridable_ && !strict_enforcement_); 420 load_time_data.SetString( 421 "tabTitle", l10n_util::GetStringUTF16(IDS_SSL_V2_TITLE)); 422 load_time_data.SetString( 423 "heading", l10n_util::GetStringUTF16(IDS_SSL_V2_HEADING)); 424 load_time_data.SetString( 425 "primaryParagraph", 426 l10n_util::GetStringFUTF16(IDS_SSL_V2_PRIMARY_PARAGRAPH, url)); 427 load_time_data.SetString( 428 "openDetails", 429 l10n_util::GetStringUTF16(IDS_SSL_V2_OPEN_DETAILS_BUTTON)); 430 load_time_data.SetString( 431 "closeDetails", 432 l10n_util::GetStringUTF16(IDS_SSL_V2_CLOSE_DETAILS_BUTTON)); 433 434 if (overridable_ && !strict_enforcement_) { // Overridable. 435 SSLErrorInfo error_info = 436 SSLErrorInfo::CreateError( 437 SSLErrorInfo::NetErrorToErrorType(cert_error_), 438 ssl_info_.cert.get(), 439 request_url_); 440 load_time_data.SetString( 441 "explanationParagraph", error_info.details()); 442 load_time_data.SetString( 443 "primaryButtonText", 444 l10n_util::GetStringUTF16(IDS_SSL_OVERRIDABLE_SAFETY_BUTTON)); 445 load_time_data.SetString( 446 "finalParagraph", 447 l10n_util::GetStringFUTF16(IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH, url)); 448 } else { // Non-overridable. 449 load_time_data.SetBoolean("overridable", false); 450 load_time_data.SetString( 451 "explanationParagraph", 452 l10n_util::GetStringFUTF16(IDS_SSL_NONOVERRIDABLE_MORE, url)); 453 load_time_data.SetString( 454 "primaryButtonText", 455 l10n_util::GetStringUTF16(IDS_SSL_NONOVERRIDABLE_RELOAD_BUTTON)); 456 // Customize the help link depending on the specific error type. 457 // Only mark as HSTS if none of the more specific error types apply, and use 458 // INVALID as a fallback if no other string is appropriate. 459 SSLErrorInfo::ErrorType type = 460 SSLErrorInfo::NetErrorToErrorType(cert_error_); 461 load_time_data.SetInteger("errorType", type); 462 int help_string = IDS_SSL_NONOVERRIDABLE_INVALID; 463 switch (type) { 464 case SSLErrorInfo::CERT_REVOKED: 465 help_string = IDS_SSL_NONOVERRIDABLE_REVOKED; 466 break; 467 case SSLErrorInfo::CERT_PINNED_KEY_MISSING: 468 help_string = IDS_SSL_NONOVERRIDABLE_PINNED; 469 break; 470 case SSLErrorInfo::CERT_INVALID: 471 help_string = IDS_SSL_NONOVERRIDABLE_INVALID; 472 break; 473 default: 474 if (strict_enforcement_) 475 help_string = IDS_SSL_NONOVERRIDABLE_HSTS; 476 } 477 load_time_data.SetString( 478 "finalParagraph", l10n_util::GetStringFUTF16(help_string, url)); 479 load_time_data.SetString("errorCode", net::ErrorToString(cert_error_)); 480 } 481 482 base::StringPiece html( 483 ResourceBundle::GetSharedInstance().GetRawDataResource( 484 IRD_SSL_INTERSTITIAL_V2_HTML)); 485 webui::UseVersion2 version; 486 return webui::GetI18nTemplateHtml(html, &load_time_data); 487 } 488 489 void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) { 490 int cert_id = content::CertStore::GetInstance()->StoreCert( 491 ssl_info_.cert.get(), web_contents_->GetRenderProcessHost()->GetID()); 492 DCHECK(cert_id); 493 494 entry->GetSSL().security_style = 495 content::SECURITY_STYLE_AUTHENTICATION_BROKEN; 496 entry->GetSSL().cert_id = cert_id; 497 entry->GetSSL().cert_status = ssl_info_.cert_status; 498 entry->GetSSL().security_bits = ssl_info_.security_bits; 499 } 500 501 // This handles the commands sent from the interstitial JavaScript. They are 502 // defined in chrome/browser/resources/ssl/ssl_errors_common.js. 503 // DO NOT reorder or change this logic without also changing the JavaScript! 504 void SSLBlockingPage::CommandReceived(const std::string& command) { 505 int cmd = 0; 506 bool retval = base::StringToInt(command, &cmd); 507 DCHECK(retval); 508 switch (cmd) { 509 case CMD_DONT_PROCEED: { 510 interstitial_page_->DontProceed(); 511 break; 512 } 513 case CMD_PROCEED: { 514 interstitial_page_->Proceed(); 515 break; 516 } 517 case CMD_MORE: { 518 RecordSSLBlockingPageEventStats(MORE); 519 break; 520 } 521 case CMD_RELOAD: { 522 // The interstitial can't refresh itself. 523 web_contents_->GetController().Reload(true); 524 break; 525 } 526 case CMD_HELP: { 527 // The interstitial can't open a popup or navigate itself. 528 // TODO(felt): We're going to need a new help page. 529 content::NavigationController::LoadURLParams help_page_params(GURL( 530 "https://support.google.com/chrome/answer/4454607")); 531 web_contents_->GetController().LoadURLWithParams(help_page_params); 532 break; 533 } 534 default: { 535 NOTREACHED(); 536 } 537 } 538 } 539 540 void SSLBlockingPage::OverrideRendererPrefs( 541 content::RendererPreferences* prefs) { 542 Profile* profile = Profile::FromBrowserContext( 543 web_contents_->GetBrowserContext()); 544 renderer_preferences_util::UpdateFromSystemSettings(prefs, profile); 545 } 546 547 void SSLBlockingPage::OnProceed() { 548 RecordSSLBlockingPageDetailedStats(true, 549 cert_error_, 550 overridable_ && !strict_enforcement_, 551 internal_, 552 num_visits_, 553 captive_portal_detection_enabled_, 554 captive_portal_probe_completed_, 555 captive_portal_no_response_, 556 captive_portal_detected_); 557 // Accepting the certificate resumes the loading of the page. 558 NotifyAllowCertificate(); 559 } 560 561 void SSLBlockingPage::OnDontProceed() { 562 RecordSSLBlockingPageDetailedStats(false, 563 cert_error_, 564 overridable_ && !strict_enforcement_, 565 internal_, 566 num_visits_, 567 captive_portal_detection_enabled_, 568 captive_portal_probe_completed_, 569 captive_portal_no_response_, 570 captive_portal_detected_); 571 NotifyDenyCertificate(); 572 } 573 574 void SSLBlockingPage::NotifyDenyCertificate() { 575 // It's possible that callback_ may not exist if the user clicks "Proceed" 576 // followed by pressing the back button before the interstitial is hidden. 577 // In that case the certificate will still be treated as allowed. 578 if (callback_.is_null()) 579 return; 580 581 callback_.Run(false); 582 callback_.Reset(); 583 } 584 585 void SSLBlockingPage::NotifyAllowCertificate() { 586 DCHECK(!callback_.is_null()); 587 588 callback_.Run(true); 589 callback_.Reset(); 590 } 591 592 // static 593 void SSLBlockingPage::SetExtraInfo( 594 base::DictionaryValue* strings, 595 const std::vector<base::string16>& extra_info) { 596 DCHECK_LT(extra_info.size(), 5U); // We allow 5 paragraphs max. 597 const char* keys[5] = { 598 "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5" 599 }; 600 int i; 601 for (i = 0; i < static_cast<int>(extra_info.size()); i++) { 602 strings->SetString(keys[i], extra_info[i]); 603 } 604 for (; i < 5; i++) { 605 strings->SetString(keys[i], std::string()); 606 } 607 } 608 609 void SSLBlockingPage::OnGotHistoryCount(HistoryService::Handle handle, 610 bool success, 611 int num_visits, 612 base::Time first_visit) { 613 num_visits_ = num_visits; 614 } 615 616 void SSLBlockingPage::Observe( 617 int type, 618 const content::NotificationSource& source, 619 const content::NotificationDetails& details) { 620 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 621 // When detection is disabled, captive portal service always sends 622 // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case. 623 if (!captive_portal_detection_enabled_) 624 return; 625 if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) { 626 captive_portal_probe_completed_ = true; 627 CaptivePortalService::Results* results = 628 content::Details<CaptivePortalService::Results>( 629 details).ptr(); 630 // If a captive portal was detected at any point when the interstitial was 631 // displayed, assume that the interstitial was caused by a captive portal. 632 // Example scenario: 633 // 1- Interstitial displayed and captive portal detected, setting the flag. 634 // 2- Captive portal detection automatically opens portal login page. 635 // 3- User logs in on the portal login page. 636 // A notification will be received here for RESULT_INTERNET_CONNECTED. Make 637 // sure we don't clear the captive portal flag, since the interstitial was 638 // potentially caused by the captive portal. 639 captive_portal_detected_ = captive_portal_detected_ || 640 (results->result == captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL); 641 // Also keep track of non-HTTP portals and error cases. 642 captive_portal_no_response_ = captive_portal_no_response_ || 643 (results->result == captive_portal::RESULT_NO_RESPONSE); 644 } 645 #endif 646 } 647