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
GetCertIcon()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
SSLCertAddedInfoBarDelegate(TabContents * tab_contents,net::X509Certificate * cert)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
~SSLCertAddedInfoBarDelegate()65 SSLCertAddedInfoBarDelegate::~SSLCertAddedInfoBarDelegate() {
66 }
67
InfoBarClosed()68 void SSLCertAddedInfoBarDelegate::InfoBarClosed() {
69 // ConfirmInfoBarDelegate doesn't delete itself.
70 delete this;
71 }
72
GetIcon() const73 SkBitmap* SSLCertAddedInfoBarDelegate::GetIcon() const {
74 return GetCertIcon();
75 }
76
GetInfoBarType() const77 InfoBarDelegate::Type SSLCertAddedInfoBarDelegate::GetInfoBarType() const {
78 return PAGE_ACTION_TYPE;
79 }
80
GetMessageText() const81 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
GetButtons() const87 int SSLCertAddedInfoBarDelegate::GetButtons() const {
88 return BUTTON_OK;
89 }
90
GetButtonLabel(InfoBarButton button) const91 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
Accept()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
SSLAddCertData(TabContents * tab_contents)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
~SSLAddCertData()141 TabContentsSSLHelper::SSLAddCertData::~SSLAddCertData() {
142 }
143
ShowInfoBar(InfoBarDelegate * delegate)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
ShowErrorInfoBar(const string16 & message)153 void TabContentsSSLHelper::SSLAddCertData::ShowErrorInfoBar(
154 const string16& message) {
155 ShowInfoBar(new SimpleAlertInfoBarDelegate(tab_contents_, GetCertIcon(),
156 message, true));
157 }
158
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)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
TabContentsSSLHelper(TabContents * tab_contents)174 TabContentsSSLHelper::TabContentsSSLHelper(TabContents* tab_contents)
175 : tab_contents_(tab_contents) {
176 }
177
~TabContentsSSLHelper()178 TabContentsSSLHelper::~TabContentsSSLHelper() {
179 }
180
ShowClientCertificateRequestDialog(scoped_refptr<SSLClientAuthHandler> handler)181 void TabContentsSSLHelper::ShowClientCertificateRequestDialog(
182 scoped_refptr<SSLClientAuthHandler> handler) {
183 browser::ShowSSLClientCertificateSelector(
184 tab_contents_, handler->cert_request_info(), handler);
185 }
186
OnVerifyClientCertificateError(scoped_refptr<SSLAddCertHandler> handler,int error_code)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
AskToAddClientCertificate(scoped_refptr<SSLAddCertHandler> handler)198 void TabContentsSSLHelper::AskToAddClientCertificate(
199 scoped_refptr<SSLAddCertHandler> handler) {
200 NOTREACHED(); // Not implemented yet.
201 }
202
OnAddClientCertificateSuccess(scoped_refptr<SSLAddCertHandler> handler)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
OnAddClientCertificateError(scoped_refptr<SSLAddCertHandler> handler,int error_code)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
OnAddClientCertificateFinished(scoped_refptr<SSLAddCertHandler> handler)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
GetAddCertData(SSLAddCertHandler * handler)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