Home | History | Annotate | Download | only in ssl
      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