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