1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ssl/ssl_tab_helper.h"
10 #include "base/basictypes.h"
11 #include "base/command_line.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/browser/certificate_viewer.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/content_settings/host_content_settings_map.h"
18 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
19 #include "chrome/browser/infobars/infobar.h"
20 #include "chrome/browser/infobars/infobar_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ssl/ssl_add_cert_handler.h"
23 #include "chrome/browser/ssl/ssl_client_certificate_selector.h"
24 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "content/public/browser/notification_source.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/browser/web_contents_view.h"
32 #include "grit/generated_resources.h"
33 #include "grit/theme_resources.h"
34 #include "net/base/net_errors.h"
35 #include "net/cert/x509_certificate.h"
36 #include "ui/base/l10n/l10n_util.h"
39 // SSLCertResultInfoBarDelegate -----------------------------------------------
43 class SSLCertResultInfoBarDelegate
: public ConfirmInfoBarDelegate
{
45 // Creates an SSL cert result infobar and delegate. If |previous_infobar| is
46 // NULL, adds the infobar to |infobar_service|; otherwise, replaces
47 // |previous_infobar|. Returns the new infobar if it was successfully added.
48 // |cert| is valid iff cert addition was successful.
49 static InfoBar
* Create(InfoBarService
* infobar_service
,
50 InfoBar
* previous_infobar
,
51 const base::string16
& message
,
52 net::X509Certificate
* cert
);
55 SSLCertResultInfoBarDelegate(const base::string16
& message
,
56 net::X509Certificate
* cert
);
57 virtual ~SSLCertResultInfoBarDelegate();
59 // ConfirmInfoBarDelegate:
60 virtual int GetIconID() const OVERRIDE
;
61 virtual Type
GetInfoBarType() const OVERRIDE
;
62 virtual base::string16
GetMessageText() const OVERRIDE
;
63 virtual int GetButtons() const OVERRIDE
;
64 virtual base::string16
GetButtonLabel(InfoBarButton button
) const OVERRIDE
;
65 virtual bool Accept() OVERRIDE
;
67 base::string16 message_
;
68 scoped_refptr
<net::X509Certificate
> cert_
; // The cert we added, if any.
70 DISALLOW_COPY_AND_ASSIGN(SSLCertResultInfoBarDelegate
);
74 InfoBar
* SSLCertResultInfoBarDelegate::Create(InfoBarService
* infobar_service
,
75 InfoBar
* previous_infobar
,
76 const base::string16
& message
,
77 net::X509Certificate
* cert
) {
78 scoped_ptr
<InfoBar
> infobar(ConfirmInfoBarDelegate::CreateInfoBar(
79 scoped_ptr
<ConfirmInfoBarDelegate
>(
80 new SSLCertResultInfoBarDelegate(message
, cert
))));
81 return previous_infobar
?
82 infobar_service
->ReplaceInfoBar(previous_infobar
, infobar
.Pass()) :
83 infobar_service
->AddInfoBar(infobar
.Pass());
86 SSLCertResultInfoBarDelegate::SSLCertResultInfoBarDelegate(
87 const base::string16
& message
,
88 net::X509Certificate
* cert
)
89 : ConfirmInfoBarDelegate(),
94 SSLCertResultInfoBarDelegate::~SSLCertResultInfoBarDelegate() {
97 int SSLCertResultInfoBarDelegate::GetIconID() const {
98 // TODO(davidben): use a more appropriate icon.
99 return IDR_INFOBAR_SAVE_PASSWORD
;
102 InfoBarDelegate::Type
SSLCertResultInfoBarDelegate::GetInfoBarType() const {
103 return cert_
.get() ? PAGE_ACTION_TYPE
: WARNING_TYPE
;
106 base::string16
SSLCertResultInfoBarDelegate::GetMessageText() const {
110 int SSLCertResultInfoBarDelegate::GetButtons() const {
111 return cert_
.get() ? BUTTON_OK
: BUTTON_NONE
;
114 base::string16
SSLCertResultInfoBarDelegate::GetButtonLabel(
115 InfoBarButton button
) const {
116 DCHECK_EQ(BUTTON_OK
, button
);
117 return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON
);
120 bool SSLCertResultInfoBarDelegate::Accept() {
121 ShowCertificateViewer(web_contents(),
122 web_contents()->GetView()->GetTopLevelNativeWindow(),
124 return false; // Hiding the infobar just as the dialog opens looks weird.
130 // SSLTabHelper::SSLAddCertData ------------------------------------------------
132 class SSLTabHelper::SSLAddCertData
133 : public content::NotificationObserver
{
135 explicit SSLAddCertData(InfoBarService
* infobar_service
);
136 virtual ~SSLAddCertData();
138 // Displays an infobar, replacing |infobar_| if it exists.
139 void ShowInfoBar(const base::string16
& message
, net::X509Certificate
* cert
);
142 // content::NotificationObserver:
143 virtual void Observe(int type
,
144 const content::NotificationSource
& source
,
145 const content::NotificationDetails
& details
) OVERRIDE
;
147 InfoBarService
* infobar_service_
;
149 content::NotificationRegistrar registrar_
;
151 DISALLOW_COPY_AND_ASSIGN(SSLAddCertData
);
154 SSLTabHelper::SSLAddCertData::SSLAddCertData(InfoBarService
* infobar_service
)
155 : infobar_service_(infobar_service
),
157 content::Source
<InfoBarService
> source(infobar_service_
);
158 registrar_
.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED
,
160 registrar_
.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED
,
164 SSLTabHelper::SSLAddCertData::~SSLAddCertData() {
167 void SSLTabHelper::SSLAddCertData::ShowInfoBar(const base::string16
& message
,
168 net::X509Certificate
* cert
) {
169 infobar_
= SSLCertResultInfoBarDelegate::Create(infobar_service_
, infobar_
,
173 void SSLTabHelper::SSLAddCertData::Observe(
175 const content::NotificationSource
& source
,
176 const content::NotificationDetails
& details
) {
177 DCHECK(type
== chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED
||
178 type
== chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED
);
180 ((type
== chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED
) ?
181 content::Details
<InfoBar::RemovedDetails
>(details
)->first
:
182 content::Details
<InfoBar::ReplacedDetails
>(details
)->first
))
187 // SSLTabHelper ----------------------------------------------------------------
189 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SSLTabHelper
);
191 SSLTabHelper::SSLTabHelper(content::WebContents
* contents
)
192 : WebContentsObserver(contents
),
193 web_contents_(contents
) {
196 SSLTabHelper::~SSLTabHelper() {
199 void SSLTabHelper::DidChangeVisibleSSLState() {
200 #if !defined(OS_ANDROID)
201 Browser
* browser
= chrome::FindBrowserWithWebContents(web_contents_
);
203 browser
->VisibleSSLStateChanged(web_contents_
);
204 #endif // !defined(OS_ANDROID)
207 void SSLTabHelper::ShowClientCertificateRequestDialog(
208 const net::HttpNetworkSession
* network_session
,
209 net::SSLCertRequestInfo
* cert_request_info
,
210 const base::Callback
<void(net::X509Certificate
*)>& callback
) {
211 chrome::ShowSSLClientCertificateSelector(web_contents_
, network_session
,
212 cert_request_info
, callback
);
215 void SSLTabHelper::OnVerifyClientCertificateError(
216 scoped_refptr
<SSLAddCertHandler
> handler
, int error_code
) {
217 // Display an infobar with the error message.
218 // TODO(davidben): Display a more user-friendly error string.
219 GetAddCertData(handler
.get())->ShowInfoBar(
220 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT
,
221 base::IntToString16(-error_code
),
223 net::ErrorToString(error_code
))),
227 void SSLTabHelper::AskToAddClientCertificate(
228 scoped_refptr
<SSLAddCertHandler
> handler
) {
229 NOTREACHED(); // Not implemented yet.
232 void SSLTabHelper::OnAddClientCertificateSuccess(
233 scoped_refptr
<SSLAddCertHandler
> handler
) {
234 net::X509Certificate
* cert
= handler
->cert();
235 // TODO(evanm): GetDisplayName should return UTF-16.
236 GetAddCertData(handler
.get())->ShowInfoBar(
237 l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL
,
239 cert
->issuer().GetDisplayName())),
243 void SSLTabHelper::OnAddClientCertificateError(
244 scoped_refptr
<SSLAddCertHandler
> handler
,
246 // TODO(davidben): Display a more user-friendly error string.
247 GetAddCertData(handler
.get())->ShowInfoBar(
248 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_FAILED
,
249 base::IntToString16(-error_code
),
251 net::ErrorToString(error_code
))),
255 void SSLTabHelper::OnAddClientCertificateFinished(
256 scoped_refptr
<SSLAddCertHandler
> handler
) {
258 request_id_to_add_cert_data_
.erase(handler
->network_request_id());
261 SSLTabHelper::SSLAddCertData
*
262 SSLTabHelper::GetAddCertData(SSLAddCertHandler
* handler
) {
263 // Find/create the slot.
264 linked_ptr
<SSLAddCertData
>& ptr_ref
=
265 request_id_to_add_cert_data_
[handler
->network_request_id()];
266 // Fill it if necessary.
267 if (!ptr_ref
.get()) {
269 new SSLAddCertData(InfoBarService::FromWebContents(web_contents_
)));
271 return ptr_ref
.get();