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