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