OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/ssl/ssl_add_certificate.h" | |
6 | |
7 #include "base/macros.h" | |
8 #include "base/strings/string_number_conversions.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "build/build_config.h" | |
11 #include "chrome/browser/certificate_viewer.h" | |
12 #include "chrome/browser/infobars/infobar_service.h" | |
13 #include "chrome/grit/generated_resources.h" | |
14 #include "chrome/grit/theme_resources.h" | |
15 #include "components/infobars/core/confirm_infobar_delegate.h" | |
16 #include "components/infobars/core/infobar.h" | |
17 #include "components/infobars/core/infobar_delegate.h" | |
18 #include "components/infobars/core/simple_alert_infobar_delegate.h" | |
19 #include "content/public/browser/browser_thread.h" | |
20 #include "content/public/browser/render_frame_host.h" | |
21 #include "content/public/browser/web_contents.h" | |
22 #include "net/base/net_errors.h" | |
23 #include "net/cert/cert_database.h" | |
24 #include "net/cert/x509_certificate.h" | |
25 #include "ui/base/l10n/l10n_util.h" | |
26 #include "ui/gfx/vector_icons_public.h" | |
27 | |
28 using content::BrowserThread; | |
29 using content::RenderFrameHost; | |
30 using content::WebContents; | |
31 | |
32 namespace chrome { | |
33 | |
34 namespace { | |
35 | |
36 class SSLAddCertificateInfoBarDelegate : public ConfirmInfoBarDelegate { | |
37 public: | |
38 // Creates an SSL certificate enrollment result infobar and delegate and adds | |
39 // the infobar to |infobar_service|. | |
40 static void Create(InfoBarService* infobar_service, | |
41 net::X509Certificate* cert); | |
42 | |
43 private: | |
44 explicit SSLAddCertificateInfoBarDelegate(net::X509Certificate* cert); | |
45 ~SSLAddCertificateInfoBarDelegate() override; | |
46 | |
47 // ConfirmInfoBarDelegate: | |
48 Type GetInfoBarType() const override; | |
49 infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; | |
50 int GetIconId() const override; | |
51 gfx::VectorIconId GetVectorIconId() const override; | |
52 base::string16 GetMessageText() const override; | |
53 int GetButtons() const override; | |
54 base::string16 GetButtonLabel(InfoBarButton button) const override; | |
55 bool Accept() override; | |
56 | |
57 // The certificate that was added. | |
58 scoped_refptr<net::X509Certificate> cert_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(SSLAddCertificateInfoBarDelegate); | |
61 }; | |
62 | |
63 // static | |
64 void SSLAddCertificateInfoBarDelegate::Create(InfoBarService* infobar_service, | |
65 net::X509Certificate* cert) { | |
66 infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar( | |
67 std::unique_ptr<ConfirmInfoBarDelegate>( | |
68 new SSLAddCertificateInfoBarDelegate(cert)))); | |
69 } | |
70 | |
71 SSLAddCertificateInfoBarDelegate::SSLAddCertificateInfoBarDelegate( | |
72 net::X509Certificate* cert) | |
73 : cert_(cert) { | |
74 } | |
75 | |
76 SSLAddCertificateInfoBarDelegate::~SSLAddCertificateInfoBarDelegate() { | |
77 } | |
78 | |
79 infobars::InfoBarDelegate::Type | |
80 SSLAddCertificateInfoBarDelegate::GetInfoBarType() const { | |
81 return PAGE_ACTION_TYPE; | |
82 } | |
83 | |
84 infobars::InfoBarDelegate::InfoBarIdentifier | |
85 SSLAddCertificateInfoBarDelegate::GetIdentifier() const { | |
86 return SSL_ADD_CERTIFICATE_INFOBAR_DELEGATE; | |
87 } | |
88 | |
89 int SSLAddCertificateInfoBarDelegate::GetIconId() const { | |
90 // TODO(davidben): Use a more appropriate icon. | |
91 return IDR_INFOBAR_SAVE_PASSWORD; | |
92 } | |
93 | |
94 gfx::VectorIconId SSLAddCertificateInfoBarDelegate::GetVectorIconId() const { | |
95 #if !defined(OS_MACOSX) | |
96 return gfx::VectorIconId::AUTOLOGIN; | |
97 #else | |
98 return gfx::VectorIconId::VECTOR_ICON_NONE; | |
99 #endif | |
100 } | |
101 | |
102 base::string16 SSLAddCertificateInfoBarDelegate::GetMessageText() const { | |
103 // TODO(evanm): GetDisplayName should return UTF-16. | |
104 return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL, | |
105 base::UTF8ToUTF16( | |
106 cert_->issuer().GetDisplayName())); | |
107 } | |
108 | |
109 int SSLAddCertificateInfoBarDelegate::GetButtons() const { | |
110 return BUTTON_OK; | |
111 } | |
112 | |
113 base::string16 SSLAddCertificateInfoBarDelegate::GetButtonLabel( | |
114 InfoBarButton button) const { | |
115 DCHECK_EQ(BUTTON_OK, button); | |
116 return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON); | |
117 } | |
118 | |
119 bool SSLAddCertificateInfoBarDelegate::Accept() { | |
120 WebContents* web_contents = | |
121 InfoBarService::WebContentsFromInfoBar(infobar()); | |
122 ShowCertificateViewer(web_contents, | |
123 web_contents->GetTopLevelNativeWindow(), | |
124 cert_.get()); | |
125 // It looks weird to hide the infobar just as the dialog opens. | |
126 return false; | |
127 } | |
128 | |
129 void ShowErrorInfoBar(int message_id, | |
130 int render_process_id, | |
131 int render_frame_id, | |
132 int cert_error) { | |
133 WebContents* web_contents = WebContents::FromRenderFrameHost( | |
134 RenderFrameHost::FromID(render_process_id, render_frame_id)); | |
135 if (!web_contents) | |
136 return; | |
137 | |
138 // TODO(davidben): Use a more appropriate icon. | |
139 // TODO(davidben): Display a more user-friendly error string. | |
140 SimpleAlertInfoBarDelegate::Create( | |
141 InfoBarService::FromWebContents(web_contents), | |
142 infobars::InfoBarDelegate::SSL_ADD_CERTIFICATE, | |
143 IDR_INFOBAR_SAVE_PASSWORD, | |
144 #if !defined(OS_MACOSX) | |
145 gfx::VectorIconId::AUTOLOGIN, | |
146 #else | |
147 gfx::VectorIconId::VECTOR_ICON_NONE, | |
148 #endif | |
149 l10n_util::GetStringFUTF16( | |
150 IDS_ADD_CERT_ERR_INVALID_CERT, base::IntToString16(-cert_error), | |
151 base::ASCIIToUTF16(net::ErrorToString(cert_error))), | |
152 true); | |
153 } | |
154 | |
155 void ShowSuccessInfoBar(int render_process_id, | |
156 int render_frame_id, | |
157 net::X509Certificate* cert) { | |
158 WebContents* web_contents = WebContents::FromRenderFrameHost( | |
159 RenderFrameHost::FromID(render_process_id, render_frame_id)); | |
160 if (!web_contents) | |
161 return; | |
162 | |
163 SSLAddCertificateInfoBarDelegate::Create( | |
164 InfoBarService::FromWebContents(web_contents), cert); | |
165 } | |
166 | |
167 } // namespace | |
168 | |
169 void SSLAddCertificate( | |
170 net::CertificateMimeType cert_type, | |
171 const void* cert_data, | |
172 size_t cert_size, | |
173 int render_process_id, | |
174 int render_frame_id) { | |
175 // Chromium only supports X.509 User certificates on non-Android | |
176 // platforms. Note that this method should not be called for other | |
177 // certificate mime types. | |
178 if (cert_type != net::CERTIFICATE_MIME_TYPE_X509_USER_CERT) | |
179 return; | |
180 | |
181 scoped_refptr<net::X509Certificate> cert; | |
182 if (cert_data != NULL) { | |
183 cert = net::X509Certificate::CreateFromBytes( | |
184 reinterpret_cast<const char*>(cert_data), cert_size); | |
185 } | |
186 // NOTE: Passing a NULL cert pointer if |cert_data| was NULL is | |
187 // intentional here. | |
188 | |
189 // Check if we have a corresponding private key. | |
190 int cert_error = net::CertDatabase::GetInstance()->CheckUserCert(cert.get()); | |
191 if (cert_error != net::OK) { | |
192 LOG_IF(ERROR, cert_error == net::ERR_NO_PRIVATE_KEY_FOR_CERT) | |
193 << "No corresponding private key in store for cert: " | |
194 << (cert.get() ? cert->subject().GetDisplayName() : "NULL"); | |
195 | |
196 BrowserThread::PostTask( | |
197 BrowserThread::UI, FROM_HERE, | |
198 base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_INVALID_CERT, | |
199 render_process_id, render_frame_id, cert_error)); | |
200 return; | |
201 } | |
202 | |
203 // Install it. | |
204 cert_error = net::CertDatabase::GetInstance()->AddUserCert(cert.get()); | |
205 | |
206 // Show the appropriate infobar. | |
207 if (cert_error != net::OK) { | |
208 BrowserThread::PostTask( | |
209 BrowserThread::UI, FROM_HERE, | |
210 base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_FAILED, | |
211 render_process_id, render_frame_id, cert_error)); | |
212 } else { | |
213 BrowserThread::PostTask( | |
214 BrowserThread::UI, FROM_HERE, | |
215 base::Bind(&ShowSuccessInfoBar, render_process_id, render_frame_id, | |
216 base::RetainedRef(cert))); | |
217 } | |
218 } | |
219 | |
220 } // namespace chrome | |
OLD | NEW |