1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/ssl/ssl_blocking_page.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h"
8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_piece.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/dom_operation_notification_details.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/ssl/ssl_cert_error_handler.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/ssl/ssl_error_info.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/jstemplate_builder.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/cert_store.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_controller.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/navigation_entry.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/browser_resources.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum SSLBlockingPageEvent {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SHOW,
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PROCEED,
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DONT_PROCEED,
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UNUSED_ENUM,
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RecordSSLBlockingPageStats(SSLBlockingPageEvent event) {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UMA_HISTOGRAM_ENUMERATION("interstial.ssl", event, UNUSED_ENUM);
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Note that we always create a navigation entry with SSL errors.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// No error happening loading a sub-resource triggers an interstitial so far.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSSLBlockingPage::SSLBlockingPage(SSLCertErrorHandler* handler,
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 Delegate* delegate,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 ErrorLevel error_level)
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : InterstitialPage(handler->GetTabContents(), true, handler->request_url()),
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      handler_(handler),
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_(delegate),
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_has_been_notified_(false),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      error_level_(error_level) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RecordSSLBlockingPageStats(SHOW);
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSSLBlockingPage::~SSLBlockingPage() {
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!delegate_has_been_notified_) {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The page is closed without the user having chosen what to do, default to
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // deny.
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyDenyCertificate();
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string SSLBlockingPage::GetHTMLContents() {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Let's build the html error page.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue strings;
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SSLErrorInfo error_info = delegate_->GetSSLErrorInfo(handler_);
683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  strings.SetString("headLine", error_info.title());
693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  strings.SetString("description", error_info.details());
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  strings.SetString("moreInfoTitle",
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                    l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetExtraInfo(&strings, error_info.extra_information());
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int resource_id;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (error_level_ == ERROR_OVERRIDABLE) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resource_id = IDR_SSL_ROAD_BLOCK_HTML;
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings.SetString("title",
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TITLE));
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings.SetString("proceed",
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_PROCEED));
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings.SetString("exit",
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_EXIT));
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(error_level_, ERROR_FATAL);
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    resource_id = IDR_SSL_ERROR_HTML;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings.SetString("title",
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      l10n_util::GetStringUTF16(IDS_SSL_ERROR_PAGE_TITLE));
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings.SetString("back",
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      l10n_util::GetStringUTF16(IDS_SSL_ERROR_PAGE_BACK));
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::StringPiece html(
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::UpdateEntry(NavigationEntry* entry) {
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const net::SSLInfo& ssl_info = handler_->ssl_info();
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int cert_id = CertStore::GetInstance()->StoreCert(
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ssl_info.cert, tab()->render_view_host()->process()->id());
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->ssl().set_cert_id(cert_id);
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->ssl().set_cert_status(ssl_info.cert_status);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  entry->ssl().set_security_bits(ssl_info.security_bits);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationService::current()->Notify(
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationType::SSL_VISIBLE_STATE_CHANGED,
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Source<NavigationController>(&tab()->controller()),
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotificationService::NoDetails());
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::CommandReceived(const std::string& command) {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (command == "1") {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Proceed();
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DontProceed();
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::Proceed() {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RecordSSLBlockingPageStats(PROCEED);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Accepting the certificate resumes the loading of the page.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotifyAllowCertificate();
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This call hides and deletes the interstitial.
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InterstitialPage::Proceed();
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::DontProceed() {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RecordSSLBlockingPageStats(DONT_PROCEED);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotifyDenyCertificate();
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InterstitialPage::DontProceed();
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::NotifyDenyCertificate() {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!delegate_has_been_notified_);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->OnDenyCertificate(handler_);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_has_been_notified_ = true;
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::NotifyAllowCertificate() {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!delegate_has_been_notified_);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->OnAllowCertificate(handler_);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_has_been_notified_ = true;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SSLBlockingPage::SetExtraInfo(
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* strings,
1583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    const std::vector<string16>& extra_info) {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(extra_info.size() < 5);  // We allow 5 paragraphs max.
1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* keys[5] = {
1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5"
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int i;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (i = 0; i < static_cast<int>(extra_info.size()); i++) {
1653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    strings->SetString(keys[i], extra_info[i]);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (; i < 5; i++) {
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    strings->SetString(keys[i], "");
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
171