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