OLD | NEW |
| (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/gtk/certificate_viewer.h" | |
6 | |
7 #include <gtk/gtk.h> | |
8 | |
9 #include <algorithm> | |
10 #include <vector> | |
11 | |
12 #include "app/l10n_util.h" | |
13 #include "base/i18n/time_formatting.h" | |
14 #include "base/nss_util.h" | |
15 #include "base/scoped_ptr.h" | |
16 #include "base/string_number_conversions.h" | |
17 #include "base/time.h" | |
18 #include "base/utf_string_conversions.h" | |
19 #include "chrome/browser/gtk/certificate_dialogs.h" | |
20 #include "chrome/browser/gtk/gtk_util.h" | |
21 #include "chrome/common/net/x509_certificate_model.h" | |
22 #include "gfx/gtk_util.h" | |
23 #include "grit/generated_resources.h" | |
24 #include "net/base/x509_certificate.h" | |
25 | |
26 namespace { | |
27 | |
28 const char kDetailsFontFamily[] = "monospace"; | |
29 | |
30 //////////////////////////////////////////////////////////////////////////////// | |
31 // Gtk utility functions. | |
32 | |
33 void AddTitle(GtkTable* table, int row, const std::string& text) { | |
34 gtk_table_attach_defaults(table, | |
35 gtk_util::CreateBoldLabel(text), | |
36 0, 2, | |
37 row, row + 1); | |
38 } | |
39 | |
40 void AddKeyValue(GtkTable* table, int row, const std::string& text, | |
41 const std::string& value) { | |
42 gtk_table_attach_defaults( | |
43 table, | |
44 gtk_util::IndentWidget( | |
45 gtk_util::LeftAlignMisc(gtk_label_new(text.c_str()))), | |
46 0, 1, row, row + 1); | |
47 gtk_table_attach_defaults( | |
48 table, | |
49 gtk_util::LeftAlignMisc(gtk_label_new(value.c_str())), | |
50 1, 2, row, row + 1); | |
51 } | |
52 | |
53 //////////////////////////////////////////////////////////////////////////////// | |
54 // CertificateViewer class definition. | |
55 | |
56 class CertificateViewer { | |
57 public: | |
58 CertificateViewer(gfx::NativeWindow parent, | |
59 const net::X509Certificate::OSCertHandles& cert_chain_list); | |
60 ~CertificateViewer(); | |
61 | |
62 void InitGeneralPage(); | |
63 void InitDetailsPage(); | |
64 | |
65 void Show(); | |
66 | |
67 private: | |
68 // Indices and column count for the certificate chain hierarchy tree store. | |
69 enum { | |
70 HIERARCHY_NAME, | |
71 HIERARCHY_OBJECT, | |
72 HIERARCHY_INDEX, | |
73 HIERARCHY_COLUMNS | |
74 }; | |
75 | |
76 // Indices and column count for the certificate fields tree store. | |
77 enum { | |
78 FIELDS_NAME, | |
79 FIELDS_VALUE, | |
80 FIELDS_COLUMNS | |
81 }; | |
82 | |
83 // Fill the tree store with the certificate hierarchy, and set |leaf| to the | |
84 // iter of the leaf node. | |
85 void FillHierarchyStore(GtkTreeStore* hierarchy_store, | |
86 GtkTreeIter* leaf) const; | |
87 | |
88 // Fill the tree store with the details of the given certificate. | |
89 static void FillTreeStoreWithCertFields( | |
90 GtkTreeStore* store, net::X509Certificate::OSCertHandle cert); | |
91 | |
92 // Create a tree store filled with the details of the given certificate. | |
93 static GtkTreeStore* CreateFieldsTreeStore( | |
94 net::X509Certificate::OSCertHandle cert); | |
95 | |
96 // Callbacks for user selecting elements in the trees. | |
97 static void OnHierarchySelectionChanged(GtkTreeSelection* selection, | |
98 CertificateViewer* viewer); | |
99 static void OnFieldsSelectionChanged(GtkTreeSelection* selection, | |
100 CertificateViewer* viewer); | |
101 | |
102 // Callback for export button. | |
103 static void OnExportClicked(GtkButton *button, CertificateViewer* viewer); | |
104 | |
105 // The certificate hierarchy (leaf cert first). | |
106 net::X509Certificate::OSCertHandles cert_chain_list_; | |
107 | |
108 GtkWidget* dialog_; | |
109 GtkWidget* notebook_; | |
110 GtkWidget* general_page_vbox_; | |
111 GtkWidget* details_page_vbox_; | |
112 GtkTreeSelection* hierarchy_selection_; | |
113 GtkWidget* fields_tree_; | |
114 GtkTextBuffer* field_value_buffer_; | |
115 GtkWidget* export_button_; | |
116 | |
117 DISALLOW_COPY_AND_ASSIGN(CertificateViewer); | |
118 }; | |
119 | |
120 //////////////////////////////////////////////////////////////////////////////// | |
121 // CertificateViewer implementation. | |
122 | |
123 // Close button callback. | |
124 void OnDialogResponse(GtkDialog* dialog, gint response_id, | |
125 gpointer user_data) { | |
126 // "Close" was clicked. | |
127 gtk_widget_destroy(GTK_WIDGET(dialog)); | |
128 } | |
129 | |
130 void OnDestroy(GtkDialog* dialog, CertificateViewer* cert_viewer) { | |
131 delete cert_viewer; | |
132 } | |
133 | |
134 CertificateViewer::CertificateViewer( | |
135 gfx::NativeWindow parent, | |
136 const net::X509Certificate::OSCertHandles& cert_chain_list) | |
137 : cert_chain_list_(cert_chain_list) { | |
138 dialog_ = gtk_dialog_new_with_buttons( | |
139 l10n_util::GetStringFUTF8( | |
140 IDS_CERT_INFO_DIALOG_TITLE, | |
141 UTF8ToUTF16( | |
142 x509_certificate_model::GetTitle( | |
143 cert_chain_list_.front()))).c_str(), | |
144 parent, | |
145 // Non-modal. | |
146 GTK_DIALOG_NO_SEPARATOR, | |
147 GTK_STOCK_CLOSE, | |
148 GTK_RESPONSE_CLOSE, | |
149 NULL); | |
150 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), | |
151 gtk_util::kContentAreaSpacing); | |
152 | |
153 x509_certificate_model::RegisterDynamicOids(); | |
154 InitGeneralPage(); | |
155 InitDetailsPage(); | |
156 | |
157 notebook_ = gtk_notebook_new(); | |
158 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_); | |
159 | |
160 gtk_notebook_append_page( | |
161 GTK_NOTEBOOK(notebook_), | |
162 general_page_vbox_, | |
163 gtk_label_new_with_mnemonic( | |
164 gfx::ConvertAcceleratorsFromWindowsStyle( | |
165 l10n_util::GetStringUTF8( | |
166 IDS_CERT_INFO_GENERAL_TAB_LABEL)).c_str())); | |
167 | |
168 gtk_notebook_append_page( | |
169 GTK_NOTEBOOK(notebook_), | |
170 details_page_vbox_, | |
171 gtk_label_new_with_mnemonic( | |
172 gfx::ConvertAcceleratorsFromWindowsStyle( | |
173 l10n_util::GetStringUTF8( | |
174 IDS_CERT_INFO_DETAILS_TAB_LABEL)).c_str())); | |
175 | |
176 g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), NULL); | |
177 g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this); | |
178 } | |
179 | |
180 CertificateViewer::~CertificateViewer() { | |
181 x509_certificate_model::DestroyCertChain(&cert_chain_list_); | |
182 } | |
183 | |
184 void CertificateViewer::InitGeneralPage() { | |
185 net::X509Certificate::OSCertHandle cert = cert_chain_list_.front(); | |
186 general_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing); | |
187 gtk_container_set_border_width(GTK_CONTAINER(general_page_vbox_), | |
188 gtk_util::kContentAreaBorder); | |
189 | |
190 GtkWidget* uses_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
191 gtk_box_pack_start(GTK_BOX(general_page_vbox_), uses_vbox, FALSE, FALSE, 0); | |
192 gtk_box_pack_start( | |
193 GTK_BOX(uses_vbox), | |
194 gtk_util::CreateBoldLabel( | |
195 l10n_util::GetStringUTF8(IDS_CERT_INFO_VERIFIED_USAGES_GROUP)), | |
196 FALSE, FALSE, 0); | |
197 | |
198 std::vector<std::string> usages; | |
199 x509_certificate_model::GetUsageStrings(cert, &usages); | |
200 for (size_t i = 0; i < usages.size(); ++i) | |
201 gtk_box_pack_start( | |
202 GTK_BOX(uses_vbox), | |
203 gtk_util::IndentWidget(gtk_util::LeftAlignMisc(gtk_label_new( | |
204 usages[i].c_str()))), | |
205 FALSE, FALSE, 0); | |
206 | |
207 gtk_box_pack_start(GTK_BOX(general_page_vbox_), gtk_hseparator_new(), | |
208 FALSE, FALSE, 0); | |
209 | |
210 const int num_rows = 21; | |
211 GtkTable* table = GTK_TABLE(gtk_table_new(num_rows, 2, FALSE)); | |
212 gtk_table_set_col_spacing(table, 0, gtk_util::kLabelSpacing); | |
213 gtk_table_set_row_spacings(table, gtk_util::kControlSpacing); | |
214 | |
215 gtk_box_pack_start(GTK_BOX(general_page_vbox_), GTK_WIDGET(table), | |
216 FALSE, FALSE, 0); | |
217 int row = 0; | |
218 const std::string alternative_text = | |
219 l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT); | |
220 AddTitle(table, row++, | |
221 l10n_util::GetStringUTF8(IDS_CERT_INFO_SUBJECT_GROUP)); | |
222 AddKeyValue(table, row++, | |
223 l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL), | |
224 x509_certificate_model::ProcessIDN( | |
225 x509_certificate_model::GetSubjectCommonName( | |
226 cert, alternative_text))); | |
227 AddKeyValue(table, row++, | |
228 l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL), | |
229 x509_certificate_model::GetSubjectOrgName( | |
230 cert, alternative_text)); | |
231 AddKeyValue(table, row++, | |
232 l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL), | |
233 x509_certificate_model::GetSubjectOrgUnitName( | |
234 cert, alternative_text)); | |
235 AddKeyValue(table, row++, | |
236 l10n_util::GetStringUTF8(IDS_CERT_INFO_SERIAL_NUMBER_LABEL), | |
237 x509_certificate_model::GetSerialNumberHexified( | |
238 cert, alternative_text)); | |
239 | |
240 row += 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing). | |
241 | |
242 AddTitle(table, row++, | |
243 l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUER_GROUP)); | |
244 AddKeyValue(table, row++, | |
245 l10n_util::GetStringUTF8(IDS_CERT_INFO_COMMON_NAME_LABEL), | |
246 x509_certificate_model::ProcessIDN( | |
247 x509_certificate_model::GetIssuerCommonName( | |
248 cert, alternative_text))); | |
249 AddKeyValue(table, row++, | |
250 l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATION_LABEL), | |
251 x509_certificate_model::GetIssuerOrgName( | |
252 cert, alternative_text)); | |
253 AddKeyValue(table, row++, | |
254 l10n_util::GetStringUTF8(IDS_CERT_INFO_ORGANIZATIONAL_UNIT_LABEL), | |
255 x509_certificate_model::GetIssuerOrgUnitName( | |
256 cert, alternative_text)); | |
257 | |
258 row += 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing). | |
259 | |
260 base::Time issued, expires; | |
261 std::string issued_str, expires_str; | |
262 if (x509_certificate_model::GetTimes(cert, &issued, &expires)) { | |
263 issued_str = UTF16ToUTF8( | |
264 base::TimeFormatShortDateNumeric(issued)); | |
265 expires_str = UTF16ToUTF8( | |
266 base::TimeFormatShortDateNumeric(expires)); | |
267 } else { | |
268 issued_str = alternative_text; | |
269 expires_str = alternative_text; | |
270 } | |
271 AddTitle(table, row++, | |
272 l10n_util::GetStringUTF8(IDS_CERT_INFO_VALIDITY_GROUP)); | |
273 AddKeyValue(table, row++, | |
274 l10n_util::GetStringUTF8(IDS_CERT_INFO_ISSUED_ON_LABEL), | |
275 issued_str); | |
276 AddKeyValue(table, row++, | |
277 l10n_util::GetStringUTF8(IDS_CERT_INFO_EXPIRES_ON_LABEL), | |
278 expires_str); | |
279 | |
280 row += 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing). | |
281 | |
282 AddTitle(table, row++, | |
283 l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP)); | |
284 AddKeyValue(table, row++, | |
285 l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL), | |
286 x509_certificate_model::HashCertSHA256(cert)); | |
287 AddKeyValue(table, row++, | |
288 l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL), | |
289 x509_certificate_model::HashCertSHA1(cert)); | |
290 | |
291 DCHECK_EQ(row, num_rows); | |
292 } | |
293 | |
294 void CertificateViewer::FillHierarchyStore(GtkTreeStore* hierarchy_store, | |
295 GtkTreeIter* leaf) const { | |
296 GtkTreeIter parent; | |
297 GtkTreeIter* parent_ptr = NULL; | |
298 GtkTreeIter iter; | |
299 gint index = cert_chain_list_.size() - 1; | |
300 for (net::X509Certificate::OSCertHandles::const_reverse_iterator i = | |
301 cert_chain_list_.rbegin(); | |
302 i != cert_chain_list_.rend(); ++i, --index) { | |
303 gtk_tree_store_append(hierarchy_store, &iter, parent_ptr); | |
304 GtkTreeStore* fields_store = CreateFieldsTreeStore(*i); | |
305 gtk_tree_store_set( | |
306 hierarchy_store, &iter, | |
307 HIERARCHY_NAME, x509_certificate_model::GetTitle(*i).c_str(), | |
308 HIERARCHY_OBJECT, fields_store, | |
309 HIERARCHY_INDEX, index, | |
310 -1); | |
311 g_object_unref(fields_store); | |
312 parent = iter; | |
313 parent_ptr = &parent; | |
314 } | |
315 *leaf = iter; | |
316 } | |
317 | |
318 // static | |
319 void CertificateViewer::FillTreeStoreWithCertFields( | |
320 GtkTreeStore* store, net::X509Certificate::OSCertHandle cert) { | |
321 GtkTreeIter top; | |
322 gtk_tree_store_append(store, &top, NULL); | |
323 gtk_tree_store_set( | |
324 store, &top, | |
325 FIELDS_NAME, x509_certificate_model::GetTitle(cert).c_str(), | |
326 FIELDS_VALUE, "", | |
327 -1); | |
328 | |
329 GtkTreeIter cert_iter; | |
330 gtk_tree_store_append(store, &cert_iter, &top); | |
331 gtk_tree_store_set( | |
332 store, &cert_iter, | |
333 FIELDS_NAME, | |
334 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE).c_str(), | |
335 FIELDS_VALUE, "", | |
336 -1); | |
337 | |
338 std::string version_str; | |
339 std::string version = x509_certificate_model::GetVersion(cert); | |
340 if (!version.empty()) | |
341 version_str = l10n_util::GetStringFUTF8(IDS_CERT_DETAILS_VERSION_FORMAT, | |
342 UTF8ToUTF16(version)); | |
343 GtkTreeIter iter; | |
344 gtk_tree_store_append(store, &iter, &cert_iter); | |
345 gtk_tree_store_set( | |
346 store, &iter, | |
347 FIELDS_NAME, | |
348 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION).c_str(), | |
349 FIELDS_VALUE, version_str.c_str(), | |
350 -1); | |
351 | |
352 gtk_tree_store_append(store, &iter, &cert_iter); | |
353 gtk_tree_store_set( | |
354 store, &iter, | |
355 FIELDS_NAME, | |
356 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER).c_str(), | |
357 FIELDS_VALUE, | |
358 x509_certificate_model::GetSerialNumberHexified( | |
359 cert, | |
360 l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT)).c_str(), | |
361 -1); | |
362 | |
363 gtk_tree_store_append(store, &iter, &cert_iter); | |
364 gtk_tree_store_set( | |
365 store, &iter, | |
366 FIELDS_NAME, | |
367 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(), | |
368 FIELDS_VALUE, | |
369 x509_certificate_model::ProcessSecAlgorithmSignature(cert).c_str(), | |
370 -1); | |
371 | |
372 gtk_tree_store_append(store, &iter, &cert_iter); | |
373 gtk_tree_store_set( | |
374 store, &iter, | |
375 FIELDS_NAME, | |
376 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER).c_str(), | |
377 FIELDS_VALUE, x509_certificate_model::GetIssuerName(cert).c_str(), | |
378 -1); | |
379 | |
380 GtkTreeIter validity_iter; | |
381 gtk_tree_store_append(store, &validity_iter, &cert_iter); | |
382 gtk_tree_store_set( | |
383 store, &validity_iter, | |
384 FIELDS_NAME, | |
385 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY).c_str(), | |
386 FIELDS_VALUE, "", | |
387 -1); | |
388 | |
389 base::Time issued, expires; | |
390 std::string issued_str, expires_str; | |
391 if (x509_certificate_model::GetTimes(cert, &issued, &expires)) { | |
392 issued_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(issued)); | |
393 expires_str = UTF16ToUTF8(base::TimeFormatShortDateAndTime(expires)); | |
394 } | |
395 gtk_tree_store_append(store, &iter, &validity_iter); | |
396 gtk_tree_store_set( | |
397 store, &iter, | |
398 FIELDS_NAME, | |
399 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE).c_str(), | |
400 FIELDS_VALUE, issued_str.c_str(), | |
401 -1); | |
402 gtk_tree_store_append(store, &iter, &validity_iter); | |
403 gtk_tree_store_set( | |
404 store, &iter, | |
405 FIELDS_NAME, | |
406 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER).c_str(), | |
407 FIELDS_VALUE, expires_str.c_str(), | |
408 -1); | |
409 | |
410 gtk_tree_store_append(store, &iter, &cert_iter); | |
411 gtk_tree_store_set( | |
412 store, &iter, | |
413 FIELDS_NAME, | |
414 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT).c_str(), | |
415 FIELDS_VALUE, x509_certificate_model::GetSubjectName(cert).c_str(), | |
416 -1); | |
417 | |
418 GtkTreeIter subject_public_key_iter; | |
419 gtk_tree_store_append(store, &subject_public_key_iter, &cert_iter); | |
420 gtk_tree_store_set( | |
421 store, &subject_public_key_iter, | |
422 FIELDS_NAME, | |
423 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO).c_str(), | |
424 FIELDS_VALUE, "", | |
425 -1); | |
426 | |
427 gtk_tree_store_append(store, &iter, &subject_public_key_iter); | |
428 gtk_tree_store_set( | |
429 store, &iter, | |
430 FIELDS_NAME, | |
431 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG).c_str(), | |
432 FIELDS_VALUE, | |
433 x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert).c_str(), | |
434 -1); | |
435 | |
436 gtk_tree_store_append(store, &iter, &subject_public_key_iter); | |
437 gtk_tree_store_set( | |
438 store, &iter, | |
439 FIELDS_NAME, | |
440 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY).c_str(), | |
441 FIELDS_VALUE, | |
442 x509_certificate_model::ProcessSubjectPublicKeyInfo(cert).c_str(), | |
443 -1); | |
444 | |
445 x509_certificate_model::Extensions extensions; | |
446 x509_certificate_model::GetExtensions( | |
447 l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL), | |
448 l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL), | |
449 cert, &extensions); | |
450 | |
451 if (!extensions.empty()) { | |
452 GtkTreeIter extensions_iter; | |
453 gtk_tree_store_append(store, &extensions_iter, &cert_iter); | |
454 gtk_tree_store_set( | |
455 store, &extensions_iter, | |
456 FIELDS_NAME, | |
457 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS).c_str(), | |
458 FIELDS_VALUE, "", | |
459 -1); | |
460 | |
461 for (x509_certificate_model::Extensions::const_iterator i = | |
462 extensions.begin(); i != extensions.end(); ++i) { | |
463 gtk_tree_store_append(store, &iter, &extensions_iter); | |
464 gtk_tree_store_set( | |
465 store, &iter, | |
466 FIELDS_NAME, i->name.c_str(), | |
467 FIELDS_VALUE, i->value.c_str(), | |
468 -1); | |
469 } | |
470 } | |
471 | |
472 gtk_tree_store_append(store, &iter, &top); | |
473 gtk_tree_store_set( | |
474 store, &iter, | |
475 FIELDS_NAME, | |
476 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG).c_str(), | |
477 FIELDS_VALUE, | |
478 x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert).c_str(), | |
479 -1); | |
480 | |
481 gtk_tree_store_append(store, &iter, &top); | |
482 gtk_tree_store_set( | |
483 store, &iter, | |
484 FIELDS_NAME, | |
485 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE).c_str(), | |
486 FIELDS_VALUE, | |
487 x509_certificate_model::ProcessRawBitsSignatureWrap(cert).c_str(), | |
488 -1); | |
489 } | |
490 | |
491 // static | |
492 GtkTreeStore* CertificateViewer::CreateFieldsTreeStore( | |
493 net::X509Certificate::OSCertHandle cert) { | |
494 GtkTreeStore* fields_store = gtk_tree_store_new(FIELDS_COLUMNS, G_TYPE_STRING, | |
495 G_TYPE_STRING); | |
496 FillTreeStoreWithCertFields(fields_store, cert); | |
497 return fields_store; | |
498 } | |
499 | |
500 void CertificateViewer::InitDetailsPage() { | |
501 details_page_vbox_ = gtk_vbox_new(FALSE, gtk_util::kContentAreaSpacing); | |
502 gtk_container_set_border_width(GTK_CONTAINER(details_page_vbox_), | |
503 gtk_util::kContentAreaBorder); | |
504 | |
505 GtkWidget* hierarchy_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
506 gtk_box_pack_start(GTK_BOX(details_page_vbox_), hierarchy_vbox, | |
507 FALSE, FALSE, 0); | |
508 | |
509 gtk_box_pack_start(GTK_BOX(hierarchy_vbox), | |
510 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8( | |
511 IDS_CERT_DETAILS_CERTIFICATE_HIERARCHY_LABEL)), | |
512 FALSE, FALSE, 0); | |
513 | |
514 GtkTreeStore* hierarchy_store = gtk_tree_store_new(HIERARCHY_COLUMNS, | |
515 G_TYPE_STRING, | |
516 G_TYPE_OBJECT, | |
517 G_TYPE_INT); | |
518 GtkTreeIter hierarchy_leaf_iter; | |
519 FillHierarchyStore(hierarchy_store, &hierarchy_leaf_iter); | |
520 GtkWidget* hierarchy_tree = gtk_tree_view_new_with_model( | |
521 GTK_TREE_MODEL(hierarchy_store)); | |
522 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(hierarchy_tree), FALSE); | |
523 gtk_tree_view_append_column( | |
524 GTK_TREE_VIEW(hierarchy_tree), | |
525 gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(), | |
526 "text", HIERARCHY_NAME, | |
527 NULL)); | |
528 gtk_tree_view_expand_all(GTK_TREE_VIEW(hierarchy_tree)); | |
529 hierarchy_selection_ = gtk_tree_view_get_selection( | |
530 GTK_TREE_VIEW(hierarchy_tree)); | |
531 gtk_tree_selection_set_mode(hierarchy_selection_, GTK_SELECTION_SINGLE); | |
532 g_signal_connect(hierarchy_selection_, "changed", | |
533 G_CALLBACK(OnHierarchySelectionChanged), this); | |
534 GtkWidget* hierarchy_scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
535 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(hierarchy_scroll_window), | |
536 GTK_POLICY_AUTOMATIC, | |
537 GTK_POLICY_NEVER); | |
538 gtk_scrolled_window_set_shadow_type( | |
539 GTK_SCROLLED_WINDOW(hierarchy_scroll_window), GTK_SHADOW_ETCHED_IN); | |
540 gtk_container_add(GTK_CONTAINER(hierarchy_scroll_window), hierarchy_tree); | |
541 gtk_box_pack_start(GTK_BOX(hierarchy_vbox), | |
542 hierarchy_scroll_window, FALSE, FALSE, 0); | |
543 | |
544 GtkWidget* fields_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
545 gtk_box_pack_start(GTK_BOX(details_page_vbox_), fields_vbox, | |
546 TRUE, TRUE, 0); | |
547 gtk_box_pack_start(GTK_BOX(fields_vbox), | |
548 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8( | |
549 IDS_CERT_DETAILS_CERTIFICATE_FIELDS_LABEL)), | |
550 FALSE, FALSE, 0); | |
551 | |
552 fields_tree_ = gtk_tree_view_new(); | |
553 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(fields_tree_), FALSE); | |
554 gtk_tree_view_append_column( | |
555 GTK_TREE_VIEW(fields_tree_), | |
556 gtk_tree_view_column_new_with_attributes("", gtk_cell_renderer_text_new(), | |
557 "text", FIELDS_NAME, | |
558 NULL)); | |
559 GtkTreeSelection* fields_selection = gtk_tree_view_get_selection( | |
560 GTK_TREE_VIEW(fields_tree_)); | |
561 gtk_tree_selection_set_mode(fields_selection, GTK_SELECTION_SINGLE); | |
562 g_signal_connect(fields_selection, "changed", | |
563 G_CALLBACK(OnFieldsSelectionChanged), this); | |
564 GtkWidget* fields_scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
565 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(fields_scroll_window), | |
566 GTK_POLICY_AUTOMATIC, | |
567 GTK_POLICY_AUTOMATIC); | |
568 gtk_scrolled_window_set_shadow_type( | |
569 GTK_SCROLLED_WINDOW(fields_scroll_window), GTK_SHADOW_ETCHED_IN); | |
570 gtk_container_add(GTK_CONTAINER(fields_scroll_window), fields_tree_); | |
571 gtk_box_pack_start(GTK_BOX(fields_vbox), | |
572 fields_scroll_window, TRUE, TRUE, 0); | |
573 | |
574 GtkWidget* value_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
575 gtk_box_pack_start(GTK_BOX(details_page_vbox_), value_vbox, | |
576 TRUE, TRUE, 0); | |
577 gtk_box_pack_start(GTK_BOX(value_vbox), | |
578 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8( | |
579 IDS_CERT_DETAILS_CERTIFICATE_FIELD_VALUE_LABEL)), | |
580 FALSE, FALSE, 0); | |
581 | |
582 // TODO(mattm): fix text view coloring (should have grey background). | |
583 GtkWidget* field_value_view = gtk_text_view_new(); | |
584 gtk_text_view_set_editable(GTK_TEXT_VIEW(field_value_view), FALSE); | |
585 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(field_value_view), GTK_WRAP_NONE); | |
586 field_value_buffer_ = gtk_text_view_get_buffer( | |
587 GTK_TEXT_VIEW(field_value_view)); | |
588 GtkWidget* value_scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
589 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(value_scroll_window), | |
590 GTK_POLICY_AUTOMATIC, | |
591 GTK_POLICY_AUTOMATIC); | |
592 gtk_scrolled_window_set_shadow_type( | |
593 GTK_SCROLLED_WINDOW(value_scroll_window), GTK_SHADOW_ETCHED_IN); | |
594 gtk_container_add(GTK_CONTAINER(value_scroll_window), field_value_view); | |
595 gtk_box_pack_start(GTK_BOX(value_vbox), | |
596 value_scroll_window, TRUE, TRUE, 0); | |
597 | |
598 gtk_widget_ensure_style(field_value_view); | |
599 PangoFontDescription* font_desc = pango_font_description_copy( | |
600 gtk_widget_get_style(field_value_view)->font_desc); | |
601 pango_font_description_set_family(font_desc, kDetailsFontFamily); | |
602 gtk_widget_modify_font(field_value_view, font_desc); | |
603 pango_font_description_free(font_desc); | |
604 | |
605 GtkWidget* export_hbox = gtk_hbox_new(FALSE, 0); | |
606 gtk_box_pack_start(GTK_BOX(details_page_vbox_), export_hbox, | |
607 FALSE, FALSE, 0); | |
608 export_button_ = gtk_button_new_with_mnemonic( | |
609 gfx::ConvertAcceleratorsFromWindowsStyle( | |
610 l10n_util::GetStringUTF8( | |
611 IDS_CERT_DETAILS_EXPORT_CERTIFICATE)).c_str()); | |
612 g_signal_connect(export_button_, "clicked", | |
613 G_CALLBACK(OnExportClicked), this); | |
614 gtk_box_pack_start(GTK_BOX(export_hbox), export_button_, | |
615 FALSE, FALSE, 0); | |
616 | |
617 // Select the initial certificate in the hierarchy. | |
618 gtk_tree_selection_select_iter(hierarchy_selection_, &hierarchy_leaf_iter); | |
619 } | |
620 | |
621 // static | |
622 void CertificateViewer::OnHierarchySelectionChanged( | |
623 GtkTreeSelection* selection, CertificateViewer* viewer) { | |
624 GtkTreeIter iter; | |
625 GtkTreeModel* model; | |
626 if (gtk_tree_selection_get_selected(selection, &model, &iter)) { | |
627 GtkTreeStore* fields_store = NULL; | |
628 gtk_tree_model_get(model, &iter, HIERARCHY_OBJECT, &fields_store, -1); | |
629 gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_), | |
630 GTK_TREE_MODEL(fields_store)); | |
631 gtk_tree_view_expand_all(GTK_TREE_VIEW(viewer->fields_tree_)); | |
632 gtk_widget_set_sensitive(viewer->export_button_, TRUE); | |
633 } else { | |
634 gtk_tree_view_set_model(GTK_TREE_VIEW(viewer->fields_tree_), NULL); | |
635 gtk_widget_set_sensitive(viewer->export_button_, FALSE); | |
636 } | |
637 } | |
638 | |
639 // static | |
640 void CertificateViewer::OnFieldsSelectionChanged(GtkTreeSelection* selection, | |
641 CertificateViewer* viewer) { | |
642 GtkTreeIter iter; | |
643 GtkTreeModel* model; | |
644 if (gtk_tree_selection_get_selected(selection, &model, &iter)) { | |
645 gchar* value_string = NULL; | |
646 gtk_tree_model_get(model, &iter, FIELDS_VALUE, &value_string, -1); | |
647 if (value_string) { | |
648 gtk_text_buffer_set_text(viewer->field_value_buffer_, value_string, -1); | |
649 g_free(value_string); | |
650 } else { | |
651 gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0); | |
652 } | |
653 } else { | |
654 gtk_text_buffer_set_text(viewer->field_value_buffer_, "", 0); | |
655 } | |
656 } | |
657 | |
658 // static | |
659 void CertificateViewer::OnExportClicked(GtkButton *button, | |
660 CertificateViewer* viewer) { | |
661 GtkTreeIter iter; | |
662 GtkTreeModel* model; | |
663 if (!gtk_tree_selection_get_selected(viewer->hierarchy_selection_, &model, | |
664 &iter)) | |
665 return; | |
666 gint cert_index = -1; | |
667 gtk_tree_model_get(model, &iter, HIERARCHY_INDEX, &cert_index, -1); | |
668 | |
669 if (cert_index < 0) { | |
670 NOTREACHED(); | |
671 return; | |
672 } | |
673 | |
674 ShowCertExportDialog(GTK_WINDOW(viewer->dialog_), | |
675 viewer->cert_chain_list_[cert_index]); | |
676 } | |
677 | |
678 void CertificateViewer::Show() { | |
679 gtk_util::ShowDialog(dialog_); | |
680 } | |
681 | |
682 } // namespace | |
683 | |
684 void ShowCertificateViewer(gfx::NativeWindow parent, | |
685 net::X509Certificate::OSCertHandle cert) { | |
686 net::X509Certificate::OSCertHandles cert_chain; | |
687 x509_certificate_model::GetCertChainFromCert(cert, &cert_chain); | |
688 (new CertificateViewer(parent, cert_chain))->Show(); | |
689 } | |
690 | |
691 void ShowCertificateViewer(gfx::NativeWindow parent, | |
692 net::X509Certificate* cert) { | |
693 ShowCertificateViewer(parent, cert->os_cert_handle()); | |
694 } | |
OLD | NEW |