tab_contents_ssl_helper.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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/tab_contents/tab_contents_ssl_helper.h" 6 7#include "app/l10n_util.h" 8#include "app/resource_bundle.h" 9#include "base/basictypes.h" 10#include "base/string_number_conversions.h" 11#include "base/utf_string_conversions.h" 12#include "chrome/browser/certificate_viewer.h" 13#include "chrome/browser/ssl/ssl_add_cert_handler.h" 14#include "chrome/browser/ssl/ssl_client_auth_handler.h" 15#include "chrome/browser/ssl_client_certificate_selector.h" 16#include "chrome/browser/tab_contents/infobar_delegate.h" 17#include "chrome/browser/tab_contents/tab_contents.h" 18#include "chrome/common/notification_details.h" 19#include "chrome/common/notification_source.h" 20#include "grit/generated_resources.h" 21#include "grit/theme_resources.h" 22#include "net/base/net_errors.h" 23 24namespace { 25 26SkBitmap* GetCertIcon() { 27 // TODO(davidben): use a more appropriate icon. 28 return ResourceBundle::GetSharedInstance().GetBitmapNamed( 29 IDR_INFOBAR_SAVE_PASSWORD); 30} 31 32class SSLCertAddedInfoBarDelegate : public ConfirmInfoBarDelegate { 33 public: 34 SSLCertAddedInfoBarDelegate(TabContents* tab_contents, 35 net::X509Certificate* cert) 36 : ConfirmInfoBarDelegate(tab_contents), 37 tab_contents_(tab_contents), 38 cert_(cert) { 39 } 40 41 virtual ~SSLCertAddedInfoBarDelegate() { 42 } 43 44 // Overridden from ConfirmInfoBarDelegate: 45 virtual string16 GetMessageText() const { 46 // TODO(evanm): GetDisplayName should return UTF-16. 47 return l10n_util::GetStringFUTF16( 48 IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL, 49 UTF8ToUTF16(cert_->issuer().GetDisplayName())); 50 } 51 52 virtual SkBitmap* GetIcon() const { 53 return GetCertIcon(); 54 } 55 56 virtual int GetButtons() const { 57 return BUTTON_OK; 58 } 59 60 virtual string16 GetButtonLabel(InfoBarButton button) const { 61 switch (button) { 62 case BUTTON_OK: 63 return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON); 64 default: 65 return string16(); 66 } 67 } 68 69 virtual Type GetInfoBarType() { 70 return PAGE_ACTION_TYPE; 71 } 72 73 virtual bool Accept() { 74 ShowCertificateViewer(tab_contents_->GetMessageBoxRootWindow(), cert_); 75 return false; // Hiding the infobar just as the dialog opens looks weird. 76 } 77 78 virtual void InfoBarClosed() { 79 // ConfirmInfoBarDelegate doesn't delete itself. 80 delete this; 81 } 82 83 private: 84 // The TabContents we are attached to 85 TabContents* tab_contents_; 86 // The cert we added. 87 scoped_refptr<net::X509Certificate> cert_; 88}; 89 90} // namespace 91 92class TabContentsSSLHelper::SSLAddCertData : public NotificationObserver { 93 public: 94 SSLAddCertData(TabContents* tab, SSLAddCertHandler* handler) 95 : tab_(tab), 96 handler_(handler), 97 infobar_delegate_(NULL) { 98 // Listen for disappearing InfoBars. 99 Source<TabContents> tc_source(tab_); 100 registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED, 101 tc_source); 102 registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED, 103 tc_source); 104 } 105 ~SSLAddCertData() {} 106 107 // Displays |delegate| as an infobar in |tab_|, replacing our current one if 108 // still active. 109 void ShowInfoBar(InfoBarDelegate* delegate) { 110 if (infobar_delegate_) { 111 tab_->ReplaceInfoBar(infobar_delegate_, delegate); 112 } else { 113 tab_->AddInfoBar(delegate); 114 } 115 infobar_delegate_ = delegate; 116 } 117 118 void ShowErrorInfoBar(const string16& message) { 119 ShowInfoBar( 120 new SimpleAlertInfoBarDelegate(tab_, message, GetCertIcon(), true)); 121 } 122 123 // NotificationObserver implementation. 124 virtual void Observe(NotificationType type, 125 const NotificationSource& source, 126 const NotificationDetails& details) { 127 switch (type.value) { 128 case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED: 129 InfoBarClosed(Details<InfoBarDelegate>(details).ptr()); 130 break; 131 case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED: 132 typedef std::pair<InfoBarDelegate*, InfoBarDelegate*> 133 InfoBarDelegatePair; 134 InfoBarClosed(Details<InfoBarDelegatePair>(details).ptr()->first); 135 break; 136 default: 137 NOTREACHED(); 138 break; 139 } 140 } 141 142 private: 143 void InfoBarClosed(InfoBarDelegate* delegate) { 144 if (infobar_delegate_ == delegate) 145 infobar_delegate_ = NULL; 146 } 147 148 // The TabContents we are attached to. 149 TabContents* tab_; 150 // The handler we call back to. 151 scoped_refptr<SSLAddCertHandler> handler_; 152 // The current InfoBarDelegate we're displaying. 153 InfoBarDelegate* infobar_delegate_; 154 155 NotificationRegistrar registrar_; 156 157 DISALLOW_COPY_AND_ASSIGN(SSLAddCertData); 158}; 159 160TabContentsSSLHelper::TabContentsSSLHelper(TabContents* tab_contents) 161 : tab_contents_(tab_contents) { 162} 163 164TabContentsSSLHelper::~TabContentsSSLHelper() { 165} 166 167void TabContentsSSLHelper::ShowClientCertificateRequestDialog( 168 scoped_refptr<SSLClientAuthHandler> handler) { 169 browser::ShowSSLClientCertificateSelector( 170 tab_contents_, handler->cert_request_info(), handler); 171} 172 173void TabContentsSSLHelper::OnVerifyClientCertificateError( 174 scoped_refptr<SSLAddCertHandler> handler, int error_code) { 175 SSLAddCertData* add_cert_data = GetAddCertData(handler); 176 // Display an infobar with the error message. 177 // TODO(davidben): Display a more user-friendly error string. 178 add_cert_data->ShowErrorInfoBar( 179 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT, 180 base::IntToString16(-error_code), 181 ASCIIToUTF16(net::ErrorToString(error_code)))); 182} 183 184void TabContentsSSLHelper::AskToAddClientCertificate( 185 scoped_refptr<SSLAddCertHandler> handler) { 186 NOTREACHED(); // Not implemented yet. 187} 188 189void TabContentsSSLHelper::OnAddClientCertificateSuccess( 190 scoped_refptr<SSLAddCertHandler> handler) { 191 SSLAddCertData* add_cert_data = GetAddCertData(handler); 192 // Display an infobar to inform the user. 193 add_cert_data->ShowInfoBar( 194 new SSLCertAddedInfoBarDelegate(tab_contents_, handler->cert())); 195} 196 197void TabContentsSSLHelper::OnAddClientCertificateError( 198 scoped_refptr<SSLAddCertHandler> handler, int error_code) { 199 SSLAddCertData* add_cert_data = GetAddCertData(handler); 200 // Display an infobar with the error message. 201 // TODO(davidben): Display a more user-friendly error string. 202 add_cert_data->ShowErrorInfoBar( 203 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_FAILED, 204 base::IntToString16(-error_code), 205 ASCIIToUTF16(net::ErrorToString(error_code)))); 206} 207 208void TabContentsSSLHelper::OnAddClientCertificateFinished( 209 scoped_refptr<SSLAddCertHandler> handler) { 210 // Clean up. 211 request_id_to_add_cert_data_.erase(handler->network_request_id()); 212} 213 214TabContentsSSLHelper::SSLAddCertData* TabContentsSSLHelper::GetAddCertData( 215 SSLAddCertHandler* handler) { 216 // Find/create the slot. 217 linked_ptr<SSLAddCertData>& ptr_ref = 218 request_id_to_add_cert_data_[handler->network_request_id()]; 219 // Fill it if necessary. 220 if (!ptr_ref.get()) 221 ptr_ref.reset(new SSLAddCertData(tab_contents_, handler)); 222 return ptr_ref.get(); 223} 224