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 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. 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 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 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 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 116 void SSLBlockingPage::CommandReceived(const std::string& command) { 117 if (command == "1") { 118 Proceed(); 119 } else { 120 DontProceed(); 121 } 122 } 123 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 134 void SSLBlockingPage::DontProceed() { 135 RecordSSLBlockingPageStats(DONT_PROCEED); 136 137 NotifyDenyCertificate(); 138 InterstitialPage::DontProceed(); 139 } 140 141 void SSLBlockingPage::NotifyDenyCertificate() { 142 DCHECK(!delegate_has_been_notified_); 143 144 delegate_->OnDenyCertificate(handler_); 145 delegate_has_been_notified_ = true; 146 } 147 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 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