ssl_blocking_page.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
1b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans// Use of this source code is governed by a BSD-style license that can be
3b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans// found in the LICENSE file.
4b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans
58d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/ssl/ssl_blocking_page.h"
68d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
78d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "base/i18n/rtl.h"
88d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "base/metrics/field_trial.h"
98d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "base/metrics/histogram.h"
10b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "base/strings/string_piece.h"
11b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "base/strings/utf_string_conversions.h"
12b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "base/values.h"
13b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "chrome/browser/history/history_service_factory.h"
148d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/profiles/profile.h"
158d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/renderer_preferences_util.h"
168d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/ssl/ssl_error_info.h"
178d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/ui/browser.h"
188d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "chrome/browser/ui/browser_finder.h"
198d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "content/public/browser/cert_store.h"
208d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "content/public/browser/interstitial_page.h"
218d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "content/public/browser/navigation_controller.h"
22b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "content/public/browser/navigation_entry.h"
23125b93e43fe764e46c8a89fc2f3957a4e02c92e1Jason Evans#include "content/public/browser/notification_service.h"
24b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "content/public/browser/notification_types.h"
25b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "content/public/browser/render_process_host.h"
26b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "content/public/browser/render_view_host.h"
2712a6845b6c91cf76caf3199495d76b16bba1f2feJason Evans#include "content/public/browser/web_contents.h"
2812a6845b6c91cf76caf3199495d76b16bba1f2feJason Evans#include "content/public/common/ssl_status.h"
29b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "grit/app_locale_settings.h"
30b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "grit/browser_resources.h"
31b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#include "grit/generated_resources.h"
328d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "net/base/net_errors.h"
338d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "net/base/net_util.h"
348d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "ui/base/l10n/l10n_util.h"
358d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "ui/base/resource/resource_bundle.h"
368d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "ui/webui/jstemplate_builder.h"
378d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
388d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#if defined(OS_WIN)
398d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#include "base/win/windows_version.h"
408d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans#endif
418d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
428d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansusing base::TimeTicks;
438d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansusing content::InterstitialPage;
448d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansusing content::NavigationController;
458d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansusing content::NavigationEntry;
468d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
478d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansnamespace {
488d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
498d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans// These represent the commands sent by ssl_roadblock.html.
508d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansenum SSLBlockingPageCommands {
518d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  CMD_DONT_PROCEED,
528d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  CMD_PROCEED,
538d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  CMD_FOCUS,
548d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  CMD_MORE,
558d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  CMD_SHOW_UNDERSTAND,  // Used by the Finch trial.
568d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans};
578d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
588d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans// Events for UMA.
598d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansenum SSLBlockingPageEvent {
608d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SHOW_ALL,
618d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SHOW_OVERRIDABLE,
628d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_OVERRIDABLE,
638d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_NAME,
648d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_DATE,
658d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_AUTHORITY,
668d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  DONT_PROCEED_OVERRIDABLE,
678d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  DONT_PROCEED_NAME,
688d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  DONT_PROCEED_DATE,
698d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  DONT_PROCEED_AUTHORITY,
708d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  MORE,
718d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SHOW_UNDERSTAND,
728d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SHOW_INTERNAL_HOSTNAME,
738d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_INTERNAL_HOSTNAME,
748d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SHOW_NEW_SITE,
758d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  PROCEED_NEW_SITE,
768d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  UNUSED_BLOCKING_PAGE_EVENT,
778d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans};
788d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
798d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansvoid RecordSSLBlockingPageEventStats(SSLBlockingPageEvent event) {
808d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  UMA_HISTOGRAM_ENUMERATION("interstitial.ssl",
818d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                            event,
828d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                            UNUSED_BLOCKING_PAGE_EVENT);
838d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans}
848d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
858d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansvoid RecordSSLBlockingPageDetailedStats(
868d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    bool proceed,
878d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    int cert_error,
888d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    bool overridable,
898d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    bool internal,
908d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    const base::TimeTicks& start_time,
918d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    int num_visits) {
928d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  UMA_HISTOGRAM_ENUMERATION("interstitial.ssl_error_type",
938d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans     SSLErrorInfo::NetErrorToErrorType(cert_error), SSLErrorInfo::END_OF_ENUM);
948d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (start_time.is_null() || !overridable) {
958d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    // A null start time will occur if the page never came into focus.
968d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    // Overridable is false if the user didn't have any option except to turn
978d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    // back. In either case, we don't want to record some of our metrics.
988d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    return;
998d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  }
1008d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (num_visits == 0)
1018d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    RecordSSLBlockingPageEventStats(SHOW_NEW_SITE);
1028d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (proceed) {
1038d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    RecordSSLBlockingPageEventStats(PROCEED_OVERRIDABLE);
1048d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    if (internal)
1058d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      RecordSSLBlockingPageEventStats(PROCEED_INTERNAL_HOSTNAME);
1068d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    if (num_visits == 0)
1078d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      RecordSSLBlockingPageEventStats(PROCEED_NEW_SITE);
1088d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  } else if (!proceed) {
1098d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    RecordSSLBlockingPageEventStats(DONT_PROCEED_OVERRIDABLE);
1108d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  }
1118d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SSLErrorInfo::ErrorType type = SSLErrorInfo::NetErrorToErrorType(cert_error);
1128d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  switch (type) {
1138d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    case SSLErrorInfo::CERT_COMMON_NAME_INVALID: {
1148d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      if (proceed)
1158d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(PROCEED_NAME);
1168d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      else
1178d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(DONT_PROCEED_NAME);
1188d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      break;
1198d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    }
1208d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    case SSLErrorInfo::CERT_DATE_INVALID: {
1218d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      if (proceed)
1228d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(PROCEED_DATE);
1238d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      else
1248d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(DONT_PROCEED_DATE);
1258d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      break;
1268d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    }
1278d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    case SSLErrorInfo::CERT_AUTHORITY_INVALID: {
1288d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      if (proceed)
1298d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(PROCEED_AUTHORITY);
1308d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      else
1318d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans        RecordSSLBlockingPageEventStats(DONT_PROCEED_AUTHORITY);
1328d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      break;
1338d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    }
1348d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    default: {
1358d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      break;
1368d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    }
1378d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  }
1388d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans}
1398d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1408d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans// These are the constants for the Finch experiment.
1418d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kStudyName[] = "InterstitialSSL517";
1428d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition15Control[] = "Condition15SSLControl";
1438d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition16Firefox[] = "Condition16SSLFirefox";
1448d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition17FancyFirefox[] = "Condition17SSLFancyFirefox";
1458d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition18NoImages[] = "Condition18SSLNoImages";
1468d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition19Policeman[] = "Condition19SSLPoliceman";
1478d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition20Stoplight[] = "Condition20SSLStoplight";
1488d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansconst char kCondition21Badguy[] = "Condition21SSLBadguy";
1498d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1508d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans}  // namespace
1518d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1528d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans// Note that we always create a navigation entry with SSL errors.
1538d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans// No error happening loading a sub-resource triggers an interstitial so far.
1548d8f9aeeaa77514d5732db5bd0111232af21fcfdJason EvansSSLBlockingPage::SSLBlockingPage(
1558d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    content::WebContents* web_contents,
1568d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    int cert_error,
1578d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    const net::SSLInfo& ssl_info,
1588d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    const GURL& request_url,
1598d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    bool overridable,
1608d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    bool strict_enforcement,
1618d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    const base::Callback<void(bool)>& callback)
1628d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    : callback_(callback),
1638d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      web_contents_(web_contents),
1648d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      cert_error_(cert_error),
1658d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      ssl_info_(ssl_info),
1668d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      request_url_(request_url),
1678d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      overridable_(overridable),
1688d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      strict_enforcement_(strict_enforcement),
1698d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      internal_(false),
1708d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      num_visits_(-1) {
1718d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  trialCondition_ = base::FieldTrialList::FindFullName(kStudyName);
1728d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1738d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  // For UMA stats.
1748d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (net::IsHostnameNonUnique(request_url_.HostNoBrackets()))
1758d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    internal_ = true;
1768d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  RecordSSLBlockingPageEventStats(SHOW_ALL);
1778d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (overridable_ && !strict_enforcement_) {
1788d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    RecordSSLBlockingPageEventStats(SHOW_OVERRIDABLE);
1798d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    if (internal_)
180b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      RecordSSLBlockingPageEventStats(SHOW_INTERNAL_HOSTNAME);
181b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    HistoryService* history_service = HistoryServiceFactory::GetForProfile(
182b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans        Profile::FromBrowserContext(web_contents->GetBrowserContext()),
183b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans        Profile::EXPLICIT_ACCESS);
184b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    if (history_service) {
1858d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      history_service->GetVisibleVisitCountToHost(
1868d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans          request_url_,
1878d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans          &request_consumer_,
1888d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans          base::Bind(&SSLBlockingPage::OnGotHistoryCount,
1898d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                    base::Unretained(this)));
1908d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    }
1918d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  }
1928d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1938d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  interstitial_page_ = InterstitialPage::Create(
1948d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      web_contents_, true, request_url, this);
1958d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  display_start_time_ = TimeTicks();
1968d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  interstitial_page_->Show();
1978d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans}
1988d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
1998d8f9aeeaa77514d5732db5bd0111232af21fcfdJason EvansSSLBlockingPage::~SSLBlockingPage() {
2008d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  if (!callback_.is_null()) {
2018d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    RecordSSLBlockingPageDetailedStats(false,
2028d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                       cert_error_,
2038d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                       overridable_ && !strict_enforcement_,
2048d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                       internal_,
2058d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                       display_start_time_,
2068d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                       num_visits_);
2078d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    // The page is closed without the user having chosen what to do, default to
2088d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans    // deny.
209b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    NotifyDenyCertificate();
210b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  }
2118d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans}
2128d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
2138d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evansstd::string SSLBlockingPage::GetHTMLContents() {
2148d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  // Let's build the html error page.
2158d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  DictionaryValue strings;
2168d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SSLErrorInfo error_info =
2178d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      SSLErrorInfo::CreateError(SSLErrorInfo::NetErrorToErrorType(cert_error_),
2188d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                ssl_info_.cert.get(),
2198d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                                request_url_);
2208d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
2218d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  int resource_id = IDR_SSL_ROAD_BLOCK_HTML;
2228d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  strings.SetString("headLine", error_info.title());
2238d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  strings.SetString("description", error_info.details());
2248d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  strings.SetString("moreInfoTitle",
2258d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans      l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
2268d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans  SetExtraInfo(&strings, error_info.extra_information());
2278d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans
228b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  strings.SetString("exit",
2298d8f9aeeaa77514d5732db5bd0111232af21fcfdJason Evans                    l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_EXIT));
230b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans
231b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  if (overridable_ && !strict_enforcement_) {
232b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("title",
233b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                      l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TITLE));
234b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("proceed",
235b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                      l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_PROCEED));
236b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("reasonForNotProceeding",
237b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                      l10n_util::GetStringUTF16(
238b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                          IDS_SSL_BLOCKING_PAGE_SHOULD_NOT_PROCEED));
239b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("errorType", "overridable");
240b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  } else {
241b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("title",
2429b0cbf0850b130a9b0a8c58bd10b2926b2083510Jason Evans                      l10n_util::GetStringUTF16(IDS_SSL_ERROR_PAGE_TITLE));
2439b0cbf0850b130a9b0a8c58bd10b2926b2083510Jason Evans    if (strict_enforcement_) {
244b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      strings.SetString("reasonForNotProceeding",
245b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                        l10n_util::GetStringUTF16(
246b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans                            IDS_SSL_ERROR_PAGE_CANNOT_PROCEED));
247b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    } else {
248b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      strings.SetString("reasonForNotProceeding", std::string());
249b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    }
250b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("errorType", "notoverridable");
251b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  }
252b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans
253b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
254b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans
255b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  // Set up the Finch trial layouts.
256b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  strings.SetString("trialType", trialCondition_);
257b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans  if (trialCondition_ == kCondition16Firefox ||
258b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      trialCondition_ == kCondition17FancyFirefox ||
259b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      trialCondition_ == kCondition18NoImages) {
260b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    strings.SetString("domain", request_url_.host());
261b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    std::string font_family = l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY);
262b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#if defined(OS_WIN)
263b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    if (base::win::GetVersion() < base::win::VERSION_VISTA) {
264b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans      font_family = l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY_XP);
265b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans    }
266b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#endif
267#if defined(TOOLKIT_GTK)
268    font_family = ui::ResourceBundle::GetSharedInstance().GetFont(
269        ui::ResourceBundle::BaseFont).GetFontName() + ", " + font_family;
270#endif
271    strings.SetString("fontfamily", font_family);
272    if (trialCondition_ == kCondition16Firefox ||
273        trialCondition_ == kCondition18NoImages) {
274      resource_id = IDR_SSL_FIREFOX_HTML;
275    } else if (trialCondition_ == kCondition17FancyFirefox) {
276      resource_id = IDR_SSL_FANCY_FIREFOX_HTML;
277    }
278  }
279
280  base::StringPiece html(
281      ResourceBundle::GetSharedInstance().GetRawDataResource(
282          resource_id));
283
284  return webui::GetI18nTemplateHtml(html, &strings);
285}
286
287void SSLBlockingPage::OverrideEntry(NavigationEntry* entry) {
288  int cert_id = content::CertStore::GetInstance()->StoreCert(
289      ssl_info_.cert.get(), web_contents_->GetRenderProcessHost()->GetID());
290
291  entry->GetSSL().security_style =
292      content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
293  entry->GetSSL().cert_id = cert_id;
294  entry->GetSSL().cert_status = ssl_info_.cert_status;
295  entry->GetSSL().security_bits = ssl_info_.security_bits;
296#if !defined(OS_ANDROID)
297  Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
298  if (browser)
299    browser->VisibleSSLStateChanged(web_contents_);
300#endif  // !defined(OS_ANDROID)
301}
302
303// Matches events defined in ssl_error.html and ssl_roadblock.html.
304void SSLBlockingPage::CommandReceived(const std::string& command) {
305  int cmd = atoi(command.c_str());
306  if (cmd == CMD_DONT_PROCEED) {
307    interstitial_page_->DontProceed();
308  } else if (cmd == CMD_PROCEED) {
309    interstitial_page_->Proceed();
310  } else if (cmd == CMD_FOCUS) {
311    // Start recording the time when the page is first in focus
312    display_start_time_ = base::TimeTicks::Now();
313  } else if (cmd == CMD_MORE) {
314    RecordSSLBlockingPageEventStats(MORE);
315  } else if (cmd == CMD_SHOW_UNDERSTAND) {
316    // Used in the Finch experiment.
317    RecordSSLBlockingPageEventStats(SHOW_UNDERSTAND);
318  }
319}
320
321void SSLBlockingPage::OverrideRendererPrefs(
322      content::RendererPreferences* prefs) {
323  Profile* profile = Profile::FromBrowserContext(
324      web_contents_->GetBrowserContext());
325  renderer_preferences_util::UpdateFromSystemSettings(prefs, profile);
326}
327
328void SSLBlockingPage::OnProceed() {
329  RecordSSLBlockingPageDetailedStats(true,
330                                     cert_error_,
331                                     overridable_ && !strict_enforcement_,
332                                     internal_,
333                                     display_start_time_,
334                                     num_visits_);
335  // Accepting the certificate resumes the loading of the page.
336  NotifyAllowCertificate();
337}
338
339void SSLBlockingPage::OnDontProceed() {
340  RecordSSLBlockingPageDetailedStats(false,
341                                     cert_error_,
342                                     overridable_ && !strict_enforcement_,
343                                     internal_,
344                                     display_start_time_,
345                                     num_visits_);
346  NotifyDenyCertificate();
347}
348
349void SSLBlockingPage::NotifyDenyCertificate() {
350  // It's possible that callback_ may not exist if the user clicks "Proceed"
351  // followed by pressing the back button before the interstitial is hidden.
352  // In that case the certificate will still be treated as allowed.
353  if (callback_.is_null())
354    return;
355
356  callback_.Run(false);
357  callback_.Reset();
358}
359
360void SSLBlockingPage::NotifyAllowCertificate() {
361  DCHECK(!callback_.is_null());
362
363  callback_.Run(true);
364  callback_.Reset();
365}
366
367// static
368void SSLBlockingPage::SetExtraInfo(
369    DictionaryValue* strings,
370    const std::vector<string16>& extra_info) {
371  DCHECK_LT(extra_info.size(), 5U);  // We allow 5 paragraphs max.
372  const char* keys[5] = {
373      "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5"
374  };
375  int i;
376  for (i = 0; i < static_cast<int>(extra_info.size()); i++) {
377    strings->SetString(keys[i], extra_info[i]);
378  }
379  for (; i < 5; i++) {
380    strings->SetString(keys[i], std::string());
381  }
382}
383
384void SSLBlockingPage::OnGotHistoryCount(HistoryService::Handle handle,
385                                        bool success,
386                                        int num_visits,
387                                        base::Time first_visit) {
388  num_visits_ = num_visits;
389}
390