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
RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event)90 void RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event) {
91 UMA_HISTOGRAM_ENUMERATION("interstitial.ssl",
92 event,
93 UNUSED_BLOCKING_PAGE_EVENT);
94 }
95
RecordSSLBlockingPageDetailedStats(bool proceed,int cert_error,bool overridable,bool internal,int num_visits,bool captive_portal_detection_enabled,bool captive_portal_probe_completed,bool captive_portal_no_response,bool captive_portal_detected)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.
SSLBlockingPage(content::WebContents * web_contents,int cert_error,const net::SSLInfo & ssl_info,const GURL & request_url,bool overridable,bool strict_enforcement,const base::Callback<void (bool)> & callback)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
~SSLBlockingPage()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
GetHTMLContents()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
GetHTMLContentsV1()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
GetHTMLContentsV2()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
OverrideEntry(NavigationEntry * entry)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!
CommandReceived(const std::string & command)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
OverrideRendererPrefs(content::RendererPreferences * prefs)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
OnProceed()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
OnDontProceed()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
NotifyDenyCertificate()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
NotifyAllowCertificate()585 void SSLBlockingPage::NotifyAllowCertificate() {
586 DCHECK(!callback_.is_null());
587
588 callback_.Run(true);
589 callback_.Reset();
590 }
591
592 // static
SetExtraInfo(base::DictionaryValue * strings,const std::vector<base::string16> & extra_info)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
OnGotHistoryCount(HistoryService::Handle handle,bool success,int num_visits,base::Time first_visit)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
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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