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