Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ssl / ssl_add_certificate.cc
blob89cbe5ff8fc065882be1a0b0ba99cdcd0e4e3e04
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/grit/generated_resources.h"
13 #include "components/infobars/core/confirm_infobar_delegate.h"
14 #include "components/infobars/core/infobar.h"
15 #include "components/infobars/core/simple_alert_infobar_delegate.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;
29 namespace chrome {
31 namespace {
33 class SSLAddCertificateInfoBarDelegate : public ConfirmInfoBarDelegate {
34 public:
35 // Creates an SSL certificate enrollment result infobar and delegate and adds
36 // the infobar to |infobar_service|.
37 static void Create(InfoBarService* infobar_service,
38 net::X509Certificate* cert);
40 private:
41 explicit SSLAddCertificateInfoBarDelegate(net::X509Certificate* cert);
42 ~SSLAddCertificateInfoBarDelegate() override;
44 // ConfirmInfoBarDelegate:
45 Type GetInfoBarType() const override;
46 int GetIconId() const override;
47 base::string16 GetMessageText() const override;
48 int GetButtons() const override;
49 base::string16 GetButtonLabel(InfoBarButton button) const override;
50 bool Accept() override;
52 // The certificate that was added.
53 scoped_refptr<net::X509Certificate> cert_;
55 DISALLOW_COPY_AND_ASSIGN(SSLAddCertificateInfoBarDelegate);
58 // static
59 void SSLAddCertificateInfoBarDelegate::Create(InfoBarService* infobar_service,
60 net::X509Certificate* cert) {
61 infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
62 scoped_ptr<ConfirmInfoBarDelegate>(
63 new SSLAddCertificateInfoBarDelegate(cert))));
66 SSLAddCertificateInfoBarDelegate::SSLAddCertificateInfoBarDelegate(
67 net::X509Certificate* cert)
68 : cert_(cert) {
71 SSLAddCertificateInfoBarDelegate::~SSLAddCertificateInfoBarDelegate() {
74 infobars::InfoBarDelegate::Type
75 SSLAddCertificateInfoBarDelegate::GetInfoBarType() const {
76 return PAGE_ACTION_TYPE;
79 int SSLAddCertificateInfoBarDelegate::GetIconId() const {
80 // TODO(davidben): Use a more appropriate icon.
81 return IDR_INFOBAR_SAVE_PASSWORD;
84 base::string16 SSLAddCertificateInfoBarDelegate::GetMessageText() const {
85 // TODO(evanm): GetDisplayName should return UTF-16.
86 return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
87 base::UTF8ToUTF16(
88 cert_->issuer().GetDisplayName()));
91 int SSLAddCertificateInfoBarDelegate::GetButtons() const {
92 return BUTTON_OK;
95 base::string16 SSLAddCertificateInfoBarDelegate::GetButtonLabel(
96 InfoBarButton button) const {
97 DCHECK_EQ(BUTTON_OK, button);
98 return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON);
101 bool SSLAddCertificateInfoBarDelegate::Accept() {
102 WebContents* web_contents =
103 InfoBarService::WebContentsFromInfoBar(infobar());
104 ShowCertificateViewer(web_contents,
105 web_contents->GetTopLevelNativeWindow(),
106 cert_.get());
107 // It looks weird to hide the infobar just as the dialog opens.
108 return false;
111 void ShowErrorInfoBar(int message_id,
112 int render_process_id,
113 int render_frame_id,
114 int cert_error) {
115 WebContents* web_contents = WebContents::FromRenderFrameHost(
116 RenderFrameHost::FromID(render_process_id, render_frame_id));
117 if (!web_contents)
118 return;
120 // TODO(davidben): Use a more appropriate icon.
121 // TODO(davidben): Display a more user-friendly error string.
122 SimpleAlertInfoBarDelegate::Create(
123 InfoBarService::FromWebContents(web_contents),
124 IDR_INFOBAR_SAVE_PASSWORD,
125 l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT,
126 base::IntToString16(-cert_error),
127 base::ASCIIToUTF16(
128 net::ErrorToString(cert_error))),
129 true);
132 void ShowSuccessInfoBar(int render_process_id,
133 int render_frame_id,
134 net::X509Certificate* cert) {
135 WebContents* web_contents = WebContents::FromRenderFrameHost(
136 RenderFrameHost::FromID(render_process_id, render_frame_id));
137 if (!web_contents)
138 return;
140 SSLAddCertificateInfoBarDelegate::Create(
141 InfoBarService::FromWebContents(web_contents), cert);
144 } // namespace
146 void SSLAddCertificate(
147 net::CertificateMimeType cert_type,
148 const void* cert_data,
149 size_t cert_size,
150 int render_process_id,
151 int render_frame_id) {
152 // Chromium only supports X.509 User certificates on non-Android
153 // platforms. Note that this method should not be called for other
154 // certificate mime types.
155 if (cert_type != net::CERTIFICATE_MIME_TYPE_X509_USER_CERT)
156 return;
158 scoped_refptr<net::X509Certificate> cert;
159 if (cert_data != NULL) {
160 cert = net::X509Certificate::CreateFromBytes(
161 reinterpret_cast<const char*>(cert_data), cert_size);
163 // NOTE: Passing a NULL cert pointer if |cert_data| was NULL is
164 // intentional here.
166 // Check if we have a corresponding private key.
167 int cert_error = net::CertDatabase::GetInstance()->CheckUserCert(cert.get());
168 if (cert_error != net::OK) {
169 LOG_IF(ERROR, cert_error == net::ERR_NO_PRIVATE_KEY_FOR_CERT)
170 << "No corresponding private key in store for cert: "
171 << (cert.get() ? cert->subject().GetDisplayName() : "NULL");
173 BrowserThread::PostTask(
174 BrowserThread::UI, FROM_HERE,
175 base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_INVALID_CERT,
176 render_process_id, render_frame_id, cert_error));
177 return;
180 // Install it.
181 cert_error = net::CertDatabase::GetInstance()->AddUserCert(cert.get());
183 // Show the appropriate infobar.
184 if (cert_error != net::OK) {
185 BrowserThread::PostTask(
186 BrowserThread::UI, FROM_HERE,
187 base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_FAILED,
188 render_process_id, render_frame_id, cert_error));
189 } else {
190 BrowserThread::PostTask(
191 BrowserThread::UI, FROM_HERE,
192 base::Bind(&ShowSuccessInfoBar,
193 render_process_id, render_frame_id, cert));
197 } // namespace chrome