• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/i18n/rtl.h"
8 #include "base/metrics/histogram.h"
9 #include "base/string_piece.h"
10 #include "base/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/dom_operation_notification_details.h"
13 #include "chrome/browser/ssl/ssl_cert_error_handler.h"
14 #include "chrome/browser/ssl/ssl_error_info.h"
15 #include "chrome/common/jstemplate_builder.h"
16 #include "content/browser/cert_store.h"
17 #include "content/browser/renderer_host/render_process_host.h"
18 #include "content/browser/renderer_host/render_view_host.h"
19 #include "content/browser/tab_contents/navigation_controller.h"
20 #include "content/browser/tab_contents/navigation_entry.h"
21 #include "content/browser/tab_contents/tab_contents.h"
22 #include "content/common/notification_service.h"
23 #include "grit/browser_resources.h"
24 #include "grit/generated_resources.h"
25 #include "ui/base/l10n/l10n_util.h"
26 #include "ui/base/resource/resource_bundle.h"
27 
28 namespace {
29 
30 enum SSLBlockingPageEvent {
31   SHOW,
32   PROCEED,
33   DONT_PROCEED,
34   UNUSED_ENUM,
35 };
36 
RecordSSLBlockingPageStats(SSLBlockingPageEvent event)37 void RecordSSLBlockingPageStats(SSLBlockingPageEvent event) {
38   UMA_HISTOGRAM_ENUMERATION("interstial.ssl", event, UNUSED_ENUM);
39 }
40 
41 }  // namespace
42 
43 // Note that we always create a navigation entry with SSL errors.
44 // No error happening loading a sub-resource triggers an interstitial so far.
SSLBlockingPage(SSLCertErrorHandler * handler,Delegate * delegate,ErrorLevel error_level)45 SSLBlockingPage::SSLBlockingPage(SSLCertErrorHandler* handler,
46                                  Delegate* delegate,
47                                  ErrorLevel error_level)
48     : InterstitialPage(handler->GetTabContents(), true, handler->request_url()),
49       handler_(handler),
50       delegate_(delegate),
51       delegate_has_been_notified_(false),
52       error_level_(error_level) {
53   RecordSSLBlockingPageStats(SHOW);
54 }
55 
~SSLBlockingPage()56 SSLBlockingPage::~SSLBlockingPage() {
57   if (!delegate_has_been_notified_) {
58     // The page is closed without the user having chosen what to do, default to
59     // deny.
60     NotifyDenyCertificate();
61   }
62 }
63 
GetHTMLContents()64 std::string SSLBlockingPage::GetHTMLContents() {
65   // Let's build the html error page.
66   DictionaryValue strings;
67   SSLErrorInfo error_info = delegate_->GetSSLErrorInfo(handler_);
68   strings.SetString("headLine", error_info.title());
69   strings.SetString("description", error_info.details());
70 
71   strings.SetString("moreInfoTitle",
72                     l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXTRA_INFO_TITLE));
73   SetExtraInfo(&strings, error_info.extra_information());
74 
75   int resource_id;
76   if (error_level_ == ERROR_OVERRIDABLE) {
77     resource_id = IDR_SSL_ROAD_BLOCK_HTML;
78     strings.SetString("title",
79                       l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_TITLE));
80     strings.SetString("proceed",
81                       l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_PROCEED));
82     strings.SetString("exit",
83                       l10n_util::GetStringUTF16(IDS_SSL_BLOCKING_PAGE_EXIT));
84   } else {
85     DCHECK_EQ(error_level_, ERROR_FATAL);
86     resource_id = IDR_SSL_ERROR_HTML;
87     strings.SetString("title",
88                       l10n_util::GetStringUTF16(IDS_SSL_ERROR_PAGE_TITLE));
89     strings.SetString("back",
90                       l10n_util::GetStringUTF16(IDS_SSL_ERROR_PAGE_BACK));
91   }
92 
93   strings.SetString("textdirection", base::i18n::IsRTL() ? "rtl" : "ltr");
94 
95   base::StringPiece html(
96       ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
97 
98   return jstemplate_builder::GetI18nTemplateHtml(html, &strings);
99 }
100 
UpdateEntry(NavigationEntry * entry)101 void SSLBlockingPage::UpdateEntry(NavigationEntry* entry) {
102   const net::SSLInfo& ssl_info = handler_->ssl_info();
103   int cert_id = CertStore::GetInstance()->StoreCert(
104       ssl_info.cert, tab()->render_view_host()->process()->id());
105 
106   entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN);
107   entry->ssl().set_cert_id(cert_id);
108   entry->ssl().set_cert_status(ssl_info.cert_status);
109   entry->ssl().set_security_bits(ssl_info.security_bits);
110   NotificationService::current()->Notify(
111       NotificationType::SSL_VISIBLE_STATE_CHANGED,
112       Source<NavigationController>(&tab()->controller()),
113       NotificationService::NoDetails());
114 }
115 
CommandReceived(const std::string & command)116 void SSLBlockingPage::CommandReceived(const std::string& command) {
117   if (command == "1") {
118     Proceed();
119   } else {
120     DontProceed();
121   }
122 }
123 
Proceed()124 void SSLBlockingPage::Proceed() {
125   RecordSSLBlockingPageStats(PROCEED);
126 
127   // Accepting the certificate resumes the loading of the page.
128   NotifyAllowCertificate();
129 
130   // This call hides and deletes the interstitial.
131   InterstitialPage::Proceed();
132 }
133 
DontProceed()134 void SSLBlockingPage::DontProceed() {
135   RecordSSLBlockingPageStats(DONT_PROCEED);
136 
137   NotifyDenyCertificate();
138   InterstitialPage::DontProceed();
139 }
140 
NotifyDenyCertificate()141 void SSLBlockingPage::NotifyDenyCertificate() {
142   DCHECK(!delegate_has_been_notified_);
143 
144   delegate_->OnDenyCertificate(handler_);
145   delegate_has_been_notified_ = true;
146 }
147 
NotifyAllowCertificate()148 void SSLBlockingPage::NotifyAllowCertificate() {
149   DCHECK(!delegate_has_been_notified_);
150 
151   delegate_->OnAllowCertificate(handler_);
152   delegate_has_been_notified_ = true;
153 }
154 
155 // static
SetExtraInfo(DictionaryValue * strings,const std::vector<string16> & extra_info)156 void SSLBlockingPage::SetExtraInfo(
157     DictionaryValue* strings,
158     const std::vector<string16>& extra_info) {
159   DCHECK(extra_info.size() < 5);  // We allow 5 paragraphs max.
160   const char* keys[5] = {
161       "moreInfo1", "moreInfo2", "moreInfo3", "moreInfo4", "moreInfo5"
162   };
163   int i;
164   for (i = 0; i < static_cast<int>(extra_info.size()); i++) {
165     strings->SetString(keys[i], extra_info[i]);
166   }
167   for (; i < 5; i++) {
168     strings->SetString(keys[i], "");
169   }
170 }
171