Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: chrome/browser/gtk/ssl_client_certificate_selector.cc

Issue 6251001: Move chrome/browser/gtk/ to chrome/browser/ui/gtk/... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gtk/slide_animator_gtk.cc ('k') | chrome/browser/gtk/status_bubble_gtk.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 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_client_certificate_selector.h"
6
7 #include <gtk/gtk.h>
8
9 #include <string>
10 #include <vector>
11
12 #include "app/gtk_signal.h"
13 #include "app/l10n_util.h"
14 #include "base/i18n/time_formatting.h"
15 #include "base/logging.h"
16 #include "base/nss_util.h"
17 #include "base/utf_string_conversions.h"
18 #include "chrome/browser/certificate_viewer.h"
19 #include "chrome/browser/gtk/constrained_window_gtk.h"
20 #include "chrome/browser/gtk/gtk_util.h"
21 #include "chrome/browser/gtk/owned_widget_gtk.h"
22 #include "chrome/browser/ssl/ssl_client_auth_handler.h"
23 #include "chrome/browser/tab_contents/tab_contents.h"
24 #include "chrome/browser/ui/pk11_password_dialog.h"
25 #include "chrome/common/net/x509_certificate_model.h"
26 #include "gfx/native_widget_types.h"
27 #include "grit/generated_resources.h"
28 #include "net/base/x509_certificate.h"
29
30 namespace {
31
32 enum {
33 RESPONSE_SHOW_CERT_INFO = 1,
34 };
35
36 ///////////////////////////////////////////////////////////////////////////////
37 // SSLClientCertificateSelector
38
39 class SSLClientCertificateSelector : public ConstrainedDialogDelegate {
40 public:
41 explicit SSLClientCertificateSelector(
42 TabContents* parent,
43 net::SSLCertRequestInfo* cert_request_info,
44 SSLClientAuthHandler* delegate);
45 ~SSLClientCertificateSelector();
46
47 void Show();
48
49 // ConstrainedDialogDelegate implementation:
50 virtual GtkWidget* GetWidgetRoot() { return root_widget_.get(); }
51 virtual void DeleteDelegate();
52
53 private:
54 void PopulateCerts();
55
56 net::X509Certificate* GetSelectedCert();
57
58 static std::string FormatComboBoxText(
59 net::X509Certificate::OSCertHandle cert,
60 const std::string& nickname);
61 static std::string FormatDetailsText(
62 net::X509Certificate::OSCertHandle cert);
63
64 // Callback after unlocking certificate slot.
65 void Unlocked();
66
67 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnComboBoxChanged);
68 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnViewClicked);
69 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnCancelClicked);
70 CHROMEGTK_CALLBACK_0(SSLClientCertificateSelector, void, OnOkClicked);
71 CHROMEGTK_CALLBACK_1(SSLClientCertificateSelector, void, OnPromptShown,
72 GtkWidget*);
73
74 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
75
76 std::vector<std::string> details_strings_;
77
78 GtkWidget* cert_combo_box_;
79 GtkTextBuffer* cert_details_buffer_;
80
81 scoped_refptr<SSLClientAuthHandler> delegate_;
82
83 OwnedWidgetGtk root_widget_;
84 // Hold on to the select button to focus it.
85 GtkWidget* select_button_;
86
87 TabContents* parent_;
88 ConstrainedWindow* window_;
89
90 DISALLOW_COPY_AND_ASSIGN(SSLClientCertificateSelector);
91 };
92
93 SSLClientCertificateSelector::SSLClientCertificateSelector(
94 TabContents* parent,
95 net::SSLCertRequestInfo* cert_request_info,
96 SSLClientAuthHandler* delegate)
97 : cert_request_info_(cert_request_info),
98 delegate_(delegate),
99 parent_(parent),
100 window_(NULL) {
101 root_widget_.Own(gtk_vbox_new(FALSE, gtk_util::kControlSpacing));
102
103 GtkWidget* site_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
104 gtk_box_pack_start(GTK_BOX(root_widget_.get()), site_vbox,
105 FALSE, FALSE, 0);
106
107 GtkWidget* site_description_label = gtk_util::CreateBoldLabel(
108 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_SITE_DESCRIPTION_LABEL));
109 gtk_box_pack_start(GTK_BOX(site_vbox), site_description_label,
110 FALSE, FALSE, 0);
111
112 GtkWidget* site_label = gtk_label_new(
113 cert_request_info->host_and_port.c_str());
114 gtk_util::LeftAlignMisc(site_label);
115 gtk_box_pack_start(GTK_BOX(site_vbox), site_label, FALSE, FALSE, 0);
116
117 GtkWidget* selector_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
118 gtk_box_pack_start(GTK_BOX(root_widget_.get()), selector_vbox,
119 TRUE, TRUE, 0);
120
121 GtkWidget* choose_description_label = gtk_util::CreateBoldLabel(
122 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CHOOSE_DESCRIPTION_LABEL));
123 gtk_box_pack_start(GTK_BOX(selector_vbox), choose_description_label,
124 FALSE, FALSE, 0);
125
126
127 cert_combo_box_ = gtk_combo_box_new_text();
128 g_signal_connect(cert_combo_box_, "changed",
129 G_CALLBACK(OnComboBoxChangedThunk), this);
130 gtk_box_pack_start(GTK_BOX(selector_vbox), cert_combo_box_,
131 FALSE, FALSE, 0);
132
133 GtkWidget* details_label = gtk_label_new(l10n_util::GetStringUTF8(
134 IDS_CERT_SELECTOR_DETAILS_DESCRIPTION_LABEL).c_str());
135 gtk_util::LeftAlignMisc(details_label);
136 gtk_box_pack_start(GTK_BOX(selector_vbox), details_label, FALSE, FALSE, 0);
137
138 // TODO(mattm): fix text view coloring (should have grey background).
139 GtkWidget* cert_details_view = gtk_text_view_new();
140 gtk_text_view_set_editable(GTK_TEXT_VIEW(cert_details_view), FALSE);
141 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(cert_details_view), GTK_WRAP_WORD);
142 cert_details_buffer_ = gtk_text_view_get_buffer(
143 GTK_TEXT_VIEW(cert_details_view));
144 // We put the details in a frame instead of a scrolled window so that the
145 // entirety will be visible without requiring scrolling or expanding the
146 // dialog. This does however mean the dialog will grow itself if you switch
147 // to different cert that has longer details text.
148 GtkWidget* details_frame = gtk_frame_new(NULL);
149 gtk_frame_set_shadow_type(GTK_FRAME(details_frame), GTK_SHADOW_ETCHED_IN);
150 gtk_container_add(GTK_CONTAINER(details_frame), cert_details_view);
151 gtk_box_pack_start(GTK_BOX(selector_vbox), details_frame, TRUE, TRUE, 0);
152
153 // And then create a set of buttons like a GtkDialog would.
154 GtkWidget* button_box = gtk_hbutton_box_new();
155 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END);
156 gtk_box_set_spacing(GTK_BOX(button_box), gtk_util::kControlSpacing);
157 gtk_box_pack_end(GTK_BOX(root_widget_.get()), button_box, FALSE, FALSE, 0);
158
159 GtkWidget* view_button = gtk_button_new_with_mnemonic(
160 l10n_util::GetStringUTF8(IDS_PAGEINFO_CERT_INFO_BUTTON).c_str());
161 gtk_box_pack_start(GTK_BOX(button_box), view_button, FALSE, FALSE, 0);
162 g_signal_connect(view_button, "clicked",
163 G_CALLBACK(OnViewClickedThunk), this);
164
165 GtkWidget* cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
166 gtk_box_pack_end(GTK_BOX(button_box), cancel_button, FALSE, FALSE, 0);
167 g_signal_connect(cancel_button, "clicked",
168 G_CALLBACK(OnCancelClickedThunk), this);
169
170 GtkWidget* select_button = gtk_button_new_from_stock(GTK_STOCK_OK);
171 gtk_box_pack_end(GTK_BOX(button_box), select_button, FALSE, FALSE, 0);
172 g_signal_connect(select_button, "clicked",
173 G_CALLBACK(OnOkClickedThunk), this);
174
175 // When we are attached to a window, focus the select button.
176 select_button_ = select_button;
177 g_signal_connect(root_widget_.get(), "hierarchy-changed",
178 G_CALLBACK(OnPromptShownThunk), this);
179 PopulateCerts();
180
181 gtk_widget_show_all(root_widget_.get());
182 }
183
184 SSLClientCertificateSelector::~SSLClientCertificateSelector() {
185 root_widget_.Destroy();
186 }
187
188 void SSLClientCertificateSelector::Show() {
189 DCHECK(!window_);
190 window_ = parent_->CreateConstrainedDialog(this);
191 }
192
193 void SSLClientCertificateSelector::DeleteDelegate() {
194 if (delegate_) {
195 // The dialog was closed by escape key.
196 delegate_->CertificateSelected(NULL);
197 }
198 delete this;
199 }
200
201 void SSLClientCertificateSelector::PopulateCerts() {
202 std::vector<std::string> nicknames;
203 x509_certificate_model::GetNicknameStringsFromCertList(
204 cert_request_info_->client_certs,
205 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_EXPIRED),
206 l10n_util::GetStringUTF8(IDS_CERT_SELECTOR_CERT_NOT_YET_VALID),
207 &nicknames);
208
209 DCHECK_EQ(nicknames.size(),
210 cert_request_info_->client_certs.size());
211
212 for (size_t i = 0; i < cert_request_info_->client_certs.size(); ++i) {
213 net::X509Certificate::OSCertHandle cert =
214 cert_request_info_->client_certs[i]->os_cert_handle();
215
216 details_strings_.push_back(FormatDetailsText(cert));
217
218 gtk_combo_box_append_text(
219 GTK_COMBO_BOX(cert_combo_box_),
220 FormatComboBoxText(cert, nicknames[i]).c_str());
221 }
222
223 // Auto-select the first cert.
224 gtk_combo_box_set_active(GTK_COMBO_BOX(cert_combo_box_), 0);
225 }
226
227 net::X509Certificate* SSLClientCertificateSelector::GetSelectedCert() {
228 int selected = gtk_combo_box_get_active(GTK_COMBO_BOX(cert_combo_box_));
229 if (selected >= 0 &&
230 selected < static_cast<int>(
231 cert_request_info_->client_certs.size()))
232 return cert_request_info_->client_certs[selected];
233 return NULL;
234 }
235
236 // static
237 std::string SSLClientCertificateSelector::FormatComboBoxText(
238 net::X509Certificate::OSCertHandle cert, const std::string& nickname) {
239 std::string rv(nickname);
240 rv += " [";
241 rv += x509_certificate_model::GetSerialNumberHexified(cert, "");
242 rv += ']';
243 return rv;
244 }
245
246 // static
247 std::string SSLClientCertificateSelector::FormatDetailsText(
248 net::X509Certificate::OSCertHandle cert) {
249 std::string rv;
250
251 rv += l10n_util::GetStringFUTF8(
252 IDS_CERT_SUBJECTNAME_FORMAT,
253 UTF8ToUTF16(x509_certificate_model::GetSubjectName(cert)));
254
255 rv += "\n ";
256 rv += l10n_util::GetStringFUTF8(
257 IDS_CERT_SERIAL_NUMBER_FORMAT,
258 UTF8ToUTF16(
259 x509_certificate_model::GetSerialNumberHexified(cert, "")));
260
261 base::Time issued, expires;
262 if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
263 string16 issued_str = base::TimeFormatShortDateAndTime(issued);
264 string16 expires_str = base::TimeFormatShortDateAndTime(expires);
265 rv += "\n ";
266 rv += l10n_util::GetStringFUTF8(IDS_CERT_VALIDITY_RANGE_FORMAT,
267 issued_str, expires_str);
268 }
269
270 std::vector<std::string> usages;
271 x509_certificate_model::GetUsageStrings(cert, &usages);
272 if (usages.size()) {
273 rv += "\n ";
274 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_EXTENDED_KEY_USAGE_FORMAT,
275 UTF8ToUTF16(JoinString(usages, ',')));
276 }
277
278 std::string key_usage_str = x509_certificate_model::GetKeyUsageString(cert);
279 if (!key_usage_str.empty()) {
280 rv += "\n ";
281 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_KEY_USAGE_FORMAT,
282 UTF8ToUTF16(key_usage_str));
283 }
284
285 std::vector<std::string> email_addresses;
286 x509_certificate_model::GetEmailAddresses(cert, &email_addresses);
287 if (email_addresses.size()) {
288 rv += "\n ";
289 rv += l10n_util::GetStringFUTF8(
290 IDS_CERT_EMAIL_ADDRESSES_FORMAT,
291 UTF8ToUTF16(JoinString(email_addresses, ',')));
292 }
293
294 rv += '\n';
295 rv += l10n_util::GetStringFUTF8(
296 IDS_CERT_ISSUERNAME_FORMAT,
297 UTF8ToUTF16(x509_certificate_model::GetIssuerName(cert)));
298
299 string16 token(UTF8ToUTF16(x509_certificate_model::GetTokenName(cert)));
300 if (!token.empty()) {
301 rv += '\n';
302 rv += l10n_util::GetStringFUTF8(IDS_CERT_TOKEN_FORMAT, token);
303 }
304
305 return rv;
306 }
307
308 void SSLClientCertificateSelector::Unlocked() {
309 // TODO(mattm): refactor so we don't need to call GetSelectedCert again.
310 net::X509Certificate* cert = GetSelectedCert();
311 delegate_->CertificateSelected(cert);
312 delegate_ = NULL;
313 DCHECK(window_);
314 window_->CloseConstrainedWindow();
315 }
316
317 void SSLClientCertificateSelector::OnComboBoxChanged(GtkWidget* combo_box) {
318 int selected = gtk_combo_box_get_active(
319 GTK_COMBO_BOX(cert_combo_box_));
320 if (selected < 0)
321 return;
322 gtk_text_buffer_set_text(cert_details_buffer_,
323 details_strings_[selected].c_str(),
324 details_strings_[selected].size());
325 }
326
327 void SSLClientCertificateSelector::OnViewClicked(GtkWidget* button) {
328 net::X509Certificate* cert = GetSelectedCert();
329 if (cert) {
330 GtkWidget* toplevel = gtk_widget_get_toplevel(root_widget_.get());
331 ShowCertificateViewer(GTK_WINDOW(toplevel), cert);
332 }
333 }
334
335 void SSLClientCertificateSelector::OnCancelClicked(GtkWidget* button) {
336 delegate_->CertificateSelected(NULL);
337 delegate_ = NULL;
338 DCHECK(window_);
339 window_->CloseConstrainedWindow();
340 }
341
342 void SSLClientCertificateSelector::OnOkClicked(GtkWidget* button) {
343 net::X509Certificate* cert = GetSelectedCert();
344
345 browser::UnlockCertSlotIfNecessary(
346 cert,
347 browser::kPK11PasswordClientAuth,
348 cert_request_info_->host_and_port,
349 NewCallback(this, &SSLClientCertificateSelector::Unlocked));
350 }
351
352 void SSLClientCertificateSelector::OnPromptShown(GtkWidget* widget,
353 GtkWidget* previous_toplevel) {
354 if (!root_widget_.get() ||
355 !GTK_WIDGET_TOPLEVEL(gtk_widget_get_toplevel(root_widget_.get())))
356 return;
357 GTK_WIDGET_SET_FLAGS(select_button_, GTK_CAN_DEFAULT);
358 gtk_widget_grab_default(select_button_);
359 gtk_widget_grab_focus(select_button_);
360 }
361
362 } // namespace
363
364 ///////////////////////////////////////////////////////////////////////////////
365 // SSLClientAuthHandler platform specific implementation:
366
367 namespace browser {
368
369 void ShowSSLClientCertificateSelector(
370 TabContents* parent,
371 net::SSLCertRequestInfo* cert_request_info,
372 SSLClientAuthHandler* delegate) {
373 (new SSLClientCertificateSelector(parent,
374 cert_request_info,
375 delegate))->Show();
376 }
377
378 } // namespace browser
OLDNEW
« no previous file with comments | « chrome/browser/gtk/slide_animator_gtk.cc ('k') | chrome/browser/gtk/status_bubble_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698