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 28namespace { 29 30enum SSLBlockingPageEvent { 31 SHOW, 32 PROCEED, 33 DONT_PROCEED, 34 UNUSED_ENUM, 35}; 36 37void 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. 45SSLBlockingPage::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 56SSLBlockingPage::~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 64std::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 101void 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 116void SSLBlockingPage::CommandReceived(const std::string& command) { 117 if (command == "1") { 118 Proceed(); 119 } else { 120 DontProceed(); 121 } 122} 123 124void 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 134void SSLBlockingPage::DontProceed() { 135 RecordSSLBlockingPageStats(DONT_PROCEED); 136 137 NotifyDenyCertificate(); 138 InterstitialPage::DontProceed(); 139} 140 141void SSLBlockingPage::NotifyDenyCertificate() { 142 DCHECK(!delegate_has_been_notified_); 143 144 delegate_->OnDenyCertificate(handler_); 145 delegate_has_been_notified_ = true; 146} 147 148void SSLBlockingPage::NotifyAllowCertificate() { 149 DCHECK(!delegate_has_been_notified_); 150 151 delegate_->OnAllowCertificate(handler_); 152 delegate_has_been_notified_ = true; 153} 154 155// static 156void 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