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_add_certificate.h"
7 #include "base/basictypes.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/certificate_viewer.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/infobars/simple_alert_infobar_delegate.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/infobars/core/confirm_infobar_delegate.h"
15 #include "components/infobars/core/infobar.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "grit/theme_resources.h"
20 #include "net/base/net_errors.h"
21 #include "net/cert/cert_database.h"
22 #include "net/cert/x509_certificate.h"
23 #include "ui/base/l10n/l10n_util.h"
25 using content::BrowserThread
;
26 using content::RenderFrameHost
;
27 using content::WebContents
;
33 class SSLAddCertificateInfoBarDelegate
: public ConfirmInfoBarDelegate
{
35 // Creates an SSL certificate enrollment result infobar and delegate.
36 static void Create(InfoBarService
* infobar_service
,
37 net::X509Certificate
* cert
) {
38 infobar_service
->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
39 scoped_ptr
<ConfirmInfoBarDelegate
>(
40 new SSLAddCertificateInfoBarDelegate(cert
))));
44 explicit SSLAddCertificateInfoBarDelegate(net::X509Certificate
* cert
)
46 virtual ~SSLAddCertificateInfoBarDelegate() {}
48 // ConfirmInfoBarDelegate implementation:
49 virtual int GetIconID() const OVERRIDE
{
50 // TODO(davidben): Use a more appropriate icon.
51 return IDR_INFOBAR_SAVE_PASSWORD
;
54 virtual Type
GetInfoBarType() const OVERRIDE
{
55 return PAGE_ACTION_TYPE
;
58 virtual base::string16
GetMessageText() const OVERRIDE
{
59 // TODO(evanm): GetDisplayName should return UTF-16.
60 return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL
,
62 cert_
->issuer().GetDisplayName()));
65 virtual int GetButtons() const OVERRIDE
{
69 virtual base::string16
GetButtonLabel(InfoBarButton button
) const OVERRIDE
{
70 DCHECK_EQ(BUTTON_OK
, button
);
71 return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON
);
74 virtual bool Accept() OVERRIDE
{
75 WebContents
* web_contents
=
76 InfoBarService::WebContentsFromInfoBar(infobar());
77 ShowCertificateViewer(web_contents
,
78 web_contents
->GetTopLevelNativeWindow(),
80 // It looks weird to hide the infobar just as the dialog opens.
84 // The certificate that was added.
85 scoped_refptr
<net::X509Certificate
> cert_
;
87 DISALLOW_COPY_AND_ASSIGN(SSLAddCertificateInfoBarDelegate
);
90 void ShowErrorInfoBar(int message_id
,
91 int render_process_id
,
94 WebContents
* web_contents
= WebContents::FromRenderFrameHost(
95 RenderFrameHost::FromID(render_process_id
, render_frame_id
));
99 // TODO(davidben): Use a more appropriate icon.
100 // TODO(davidben): Display a more user-friendly error string.
101 SimpleAlertInfoBarDelegate::Create(
102 InfoBarService::FromWebContents(web_contents
),
103 IDR_INFOBAR_SAVE_PASSWORD
,
104 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT
,
105 base::IntToString16(-cert_error
),
107 net::ErrorToString(cert_error
))),
111 void ShowSuccessInfoBar(int render_process_id
,
113 net::X509Certificate
* cert
) {
114 WebContents
* web_contents
= WebContents::FromRenderFrameHost(
115 RenderFrameHost::FromID(render_process_id
, render_frame_id
));
119 SSLAddCertificateInfoBarDelegate::Create(
120 InfoBarService::FromWebContents(web_contents
), cert
);
125 void SSLAddCertificate(
126 net::CertificateMimeType cert_type
,
127 const void* cert_data
,
129 int render_process_id
,
130 int render_frame_id
) {
131 // Chromium only supports X.509 User certificates on non-Android
132 // platforms. Note that this method should not be called for other
133 // certificate mime types.
134 if (cert_type
!= net::CERTIFICATE_MIME_TYPE_X509_USER_CERT
)
137 scoped_refptr
<net::X509Certificate
> cert
;
138 if (cert_data
!= NULL
) {
139 cert
= net::X509Certificate::CreateFromBytes(
140 reinterpret_cast<const char*>(cert_data
), cert_size
);
142 // NOTE: Passing a NULL cert pointer if |cert_data| was NULL is
145 // Check if we have a corresponding private key.
146 int cert_error
= net::CertDatabase::GetInstance()->CheckUserCert(cert
.get());
147 if (cert_error
!= net::OK
) {
148 LOG_IF(ERROR
, cert_error
== net::ERR_NO_PRIVATE_KEY_FOR_CERT
)
149 << "No corresponding private key in store for cert: "
150 << (cert
.get() ? cert
->subject().GetDisplayName() : "NULL");
152 BrowserThread::PostTask(
153 BrowserThread::UI
, FROM_HERE
,
154 base::Bind(&ShowErrorInfoBar
, IDS_ADD_CERT_ERR_INVALID_CERT
,
155 render_process_id
, render_frame_id
, cert_error
));
160 cert_error
= net::CertDatabase::GetInstance()->AddUserCert(cert
.get());
162 // Show the appropriate infobar.
163 if (cert_error
!= net::OK
) {
164 BrowserThread::PostTask(
165 BrowserThread::UI
, FROM_HERE
,
166 base::Bind(&ShowErrorInfoBar
, IDS_ADD_CERT_ERR_FAILED
,
167 render_process_id
, render_frame_id
, cert_error
));
169 BrowserThread::PostTask(
170 BrowserThread::UI
, FROM_HERE
,
171 base::Bind(&ShowSuccessInfoBar
,
172 render_process_id
, render_frame_id
, cert
));
176 } // namespace chrome