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.
6 #include <pango/pango-font.h>
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"
30 const char kDetailsFontFamily
[] = "monospace";
32 ////////////////////////////////////////////////////////////////////////////////
33 // Gtk utility functions.
35 void AddTitle(GtkTable
* table
, int row
, const std::string
& text
) {
36 gtk_table_attach_defaults(table
,
37 gtk_util::CreateBoldLabel(text
),
42 void AddKeyValue(GtkTable
* table
, int row
, const std::string
& text
,
43 const std::string
& value
) {
44 gtk_table_attach_defaults(
46 gtk_util::IndentWidget(
47 gtk_util::LeftAlignMisc(gtk_label_new(text
.c_str()))),
49 GtkWidget
* label
= gtk_label_new(value
.c_str());
50 gtk_label_set_selectable(GTK_LABEL(label
), TRUE
);
51 gtk_table_attach_defaults(
53 gtk_util::LeftAlignMisc(label
),
57 ////////////////////////////////////////////////////////////////////////////////
58 // CertificateViewer class definition.
60 class CertificateViewer
{
62 CertificateViewer(gfx::NativeWindow parent
,
63 net::X509Certificate
* certificate
);
66 void InitGeneralPage();
67 void InitDetailsPage();
72 // Indices and column count for the certificate chain hierarchy tree store.
80 // Indices and column count for the certificate fields tree store.
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;
92 // Fill the tree store with the details of the given certificate.
93 static void FillTreeStoreWithCertFields(
94 GtkTreeStore
* store
, net::X509Certificate::OSCertHandle cert
);
96 // Create a tree store filled with the details of the given certificate.
97 static GtkTreeStore
* CreateFieldsTreeStore(
98 net::X509Certificate::OSCertHandle cert
);
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
);
106 // Callback for export button.
107 static void OnExportClicked(GtkButton
*button
, CertificateViewer
* viewer
);
109 // The certificate hierarchy (leaf cert first).
110 net::X509Certificate::OSCertHandles cert_chain_list_
;
111 scoped_refptr
<net::X509Certificate
> certificate_
;
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_
;
122 DISALLOW_COPY_AND_ASSIGN(CertificateViewer
);
125 ////////////////////////////////////////////////////////////////////////////////
126 // CertificateViewer implementation.
128 // Close button callback.
129 void OnResponse(GtkWidget
* dialog
, int response_id
) {
130 // "Close" was clicked.
131 gtk_widget_destroy(dialog
);
134 void OnDestroy(GtkDialog
* dialog
, CertificateViewer
* cert_viewer
) {
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());
148 dialog_
= gtk_dialog_new_with_buttons(
149 l10n_util::GetStringFUTF8(
150 IDS_CERT_INFO_DIALOG_TITLE
,
152 x509_certificate_model::GetTitle(
153 cert_chain_list_
.front()))).c_str(),
156 GTK_DIALOG_NO_SEPARATOR
,
161 GtkWidget
* content_area
= gtk_dialog_get_content_area(GTK_DIALOG(dialog_
));
162 gtk_box_set_spacing(GTK_BOX(content_area
), ui::kContentAreaSpacing
);
164 x509_certificate_model::RegisterDynamicOids();
168 notebook_
= gtk_notebook_new();
169 gtk_container_add(GTK_CONTAINER(content_area
), notebook_
);
171 gtk_notebook_append_page(
172 GTK_NOTEBOOK(notebook_
),
174 gtk_label_new_with_mnemonic(
175 ui::ConvertAcceleratorsFromWindowsStyle(
176 l10n_util::GetStringUTF8(
177 IDS_CERT_INFO_GENERAL_TAB_LABEL
)).c_str()));
179 gtk_notebook_append_page(
180 GTK_NOTEBOOK(notebook_
),
182 gtk_label_new_with_mnemonic(
183 ui::ConvertAcceleratorsFromWindowsStyle(
184 l10n_util::GetStringUTF8(
185 IDS_CERT_INFO_DETAILS_TAB_LABEL
)).c_str()));
187 g_signal_connect(dialog_
, "response", G_CALLBACK(OnResponse
), NULL
);
188 g_signal_connect(dialog_
, "destroy", G_CALLBACK(OnDestroy
), this);
191 CertificateViewer::~CertificateViewer() {
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
);
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);
204 gtk_util::CreateBoldLabel(
205 l10n_util::GetStringUTF8(IDS_CERT_INFO_VERIFIED_USAGES_GROUP
)),
208 std::vector
<std::string
> usages
;
209 x509_certificate_model::GetUsageStrings(cert
, &usages
);
210 for (size_t i
= 0; i
< usages
.size(); ++i
)
213 gtk_util::IndentWidget(gtk_util::LeftAlignMisc(gtk_label_new(
214 usages
[i
].c_str()))),
217 gtk_box_pack_start(GTK_BOX(general_page_vbox_
), gtk_hseparator_new(),
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
);
225 gtk_box_pack_start(GTK_BOX(general_page_vbox_
), GTK_WIDGET(table
),
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
));
250 row
+= 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
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
));
268 row
+= 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
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
));
278 issued_str
= alternative_text
;
279 expires_str
= alternative_text
;
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
),
286 AddKeyValue(table
, row
++,
287 l10n_util::GetStringUTF8(IDS_CERT_INFO_EXPIRES_ON_LABEL
),
290 row
+= 2; // Add spacing (kControlSpacing * 3 == kContentAreaSpacing).
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
));
301 DCHECK_EQ(row
, num_rows
);
304 void CertificateViewer::FillHierarchyStore(GtkTreeStore
* hierarchy_store
,
305 GtkTreeIter
* leaf
) const {
307 GtkTreeIter
* parent_ptr
= NULL
;
310 gint index
= cert_chain_list_
.size() - 1;
311 DCHECK_NE(-1, index
);
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
);
319 hierarchy_store
, &iter
,
320 HIERARCHY_NAME
, x509_certificate_model::GetTitle(*i
).c_str(),
321 HIERARCHY_OBJECT
, fields_store
,
322 HIERARCHY_INDEX
, index
,
324 g_object_unref(fields_store
);
326 parent_ptr
= &parent
;
333 void CertificateViewer::FillTreeStoreWithCertFields(
334 GtkTreeStore
* store
, net::X509Certificate::OSCertHandle cert
) {
336 gtk_tree_store_append(store
, &top
, NULL
);
339 FIELDS_NAME
, x509_certificate_model::GetTitle(cert
).c_str(),
343 GtkTreeIter cert_iter
;
344 gtk_tree_store_append(store
, &cert_iter
, &top
);
348 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE
).c_str(),
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
));
358 gtk_tree_store_append(store
, &iter
, &cert_iter
);
362 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION
).c_str(),
363 FIELDS_VALUE
, version_str
.c_str(),
366 gtk_tree_store_append(store
, &iter
, &cert_iter
);
370 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER
).c_str(),
372 x509_certificate_model::GetSerialNumberHexified(
374 l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT
)).c_str(),
377 gtk_tree_store_append(store
, &iter
, &cert_iter
);
381 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG
).c_str(),
383 x509_certificate_model::ProcessSecAlgorithmSignature(cert
).c_str(),
386 gtk_tree_store_append(store
, &iter
, &cert_iter
);
390 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER
).c_str(),
391 FIELDS_VALUE
, x509_certificate_model::GetIssuerName(cert
).c_str(),
394 GtkTreeIter validity_iter
;
395 gtk_tree_store_append(store
, &validity_iter
, &cert_iter
);
397 store
, &validity_iter
,
399 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY
).c_str(),
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
));
409 gtk_tree_store_append(store
, &iter
, &validity_iter
);
413 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE
).c_str(),
414 FIELDS_VALUE
, issued_str
.c_str(),
416 gtk_tree_store_append(store
, &iter
, &validity_iter
);
420 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER
).c_str(),
421 FIELDS_VALUE
, expires_str
.c_str(),
424 gtk_tree_store_append(store
, &iter
, &cert_iter
);
428 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT
).c_str(),
429 FIELDS_VALUE
, x509_certificate_model::GetSubjectName(cert
).c_str(),
432 GtkTreeIter subject_public_key_iter
;
433 gtk_tree_store_append(store
, &subject_public_key_iter
, &cert_iter
);
435 store
, &subject_public_key_iter
,
437 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO
).c_str(),
441 gtk_tree_store_append(store
, &iter
, &subject_public_key_iter
);
445 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG
).c_str(),
447 x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert
).c_str(),
450 gtk_tree_store_append(store
, &iter
, &subject_public_key_iter
);
454 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY
).c_str(),
456 x509_certificate_model::ProcessSubjectPublicKeyInfo(cert
).c_str(),
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
),
465 if (!extensions
.empty()) {
466 GtkTreeIter extensions_iter
;
467 gtk_tree_store_append(store
, &extensions_iter
, &cert_iter
);
469 store
, &extensions_iter
,
471 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS
).c_str(),
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
);
480 FIELDS_NAME
, i
->name
.c_str(),
481 FIELDS_VALUE
, i
->value
.c_str(),
486 gtk_tree_store_append(store
, &iter
, &top
);
490 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG
).c_str(),
492 x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert
).c_str(),
495 gtk_tree_store_append(store
, &iter
, &top
);
499 l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE
).c_str(),
501 x509_certificate_model::ProcessRawBitsSignatureWrap(cert
).c_str(),
504 GtkTreeIter top_fingerprints_iter
;
505 gtk_tree_store_append(store
, &top_fingerprints_iter
, &top
);
507 store
, &top_fingerprints_iter
,
509 l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP
).c_str(),
513 GtkTreeIter fingerprints_iter
;
514 gtk_tree_store_append(store
, &fingerprints_iter
, &top_fingerprints_iter
);
516 store
, &fingerprints_iter
,
518 l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL
).c_str(),
519 FIELDS_VALUE
, x509_certificate_model::HashCertSHA256(cert
).c_str(),
522 gtk_tree_store_append(store
, &fingerprints_iter
, &top_fingerprints_iter
);
524 store
, &fingerprints_iter
,
526 l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL
).c_str(),
527 FIELDS_VALUE
, x509_certificate_model::HashCertSHA1(cert
).c_str(),
532 GtkTreeStore
* CertificateViewer::CreateFieldsTreeStore(
533 net::X509Certificate::OSCertHandle cert
) {
534 GtkTreeStore
* fields_store
= gtk_tree_store_new(FIELDS_COLUMNS
, G_TYPE_STRING
,
536 FillTreeStoreWithCertFields(fields_store
, cert
);
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
);
545 GtkWidget
* hierarchy_vbox
= gtk_vbox_new(FALSE
, ui::kControlSpacing
);
546 gtk_box_pack_start(GTK_BOX(details_page_vbox_
), hierarchy_vbox
,
549 gtk_box_pack_start(GTK_BOX(hierarchy_vbox
),
550 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
551 IDS_CERT_DETAILS_CERTIFICATE_HIERARCHY_LABEL
)),
554 GtkTreeStore
* hierarchy_store
= gtk_tree_store_new(HIERARCHY_COLUMNS
,
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
,
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
,
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);
584 GtkWidget
* fields_vbox
= gtk_vbox_new(FALSE
, ui::kControlSpacing
);
585 gtk_box_pack_start(GTK_BOX(details_page_vbox_
), fields_vbox
,
587 gtk_box_pack_start(GTK_BOX(fields_vbox
),
588 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
589 IDS_CERT_DETAILS_CERTIFICATE_FIELDS_LABEL
)),
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(),
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);
614 GtkWidget
* value_vbox
= gtk_vbox_new(FALSE
, ui::kControlSpacing
);
615 gtk_box_pack_start(GTK_BOX(details_page_vbox_
), value_vbox
,
617 gtk_box_pack_start(GTK_BOX(value_vbox
),
618 gtk_util::CreateBoldLabel(l10n_util::GetStringUTF8(
619 IDS_CERT_DETAILS_CERTIFICATE_FIELD_VALUE_LABEL
)),
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);
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());
644 GtkWidget
* export_hbox
= gtk_hbox_new(FALSE
, 0);
645 gtk_box_pack_start(GTK_BOX(details_page_vbox_
), export_hbox
,
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_
,
656 // Select the initial certificate in the hierarchy.
657 gtk_tree_selection_select_iter(hierarchy_selection_
, &hierarchy_leaf_iter
);
661 void CertificateViewer::OnHierarchySelectionChanged(
662 GtkTreeSelection
* selection
, CertificateViewer
* viewer
) {
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
);
673 gtk_tree_view_set_model(GTK_TREE_VIEW(viewer
->fields_tree_
), NULL
);
674 gtk_widget_set_sensitive(viewer
->export_button_
, FALSE
);
679 void CertificateViewer::OnFieldsSelectionChanged(GtkTreeSelection
* selection
,
680 CertificateViewer
* viewer
) {
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);
687 gtk_text_buffer_set_text(viewer
->field_value_buffer_
, value_string
, -1);
688 g_free(value_string
);
690 gtk_text_buffer_set_text(viewer
->field_value_buffer_
, "", 0);
693 gtk_text_buffer_set_text(viewer
->field_value_buffer_
, "", 0);
698 void CertificateViewer::OnExportClicked(GtkButton
*button
,
699 CertificateViewer
* viewer
) {
702 if (!gtk_tree_selection_get_selected(viewer
->hierarchy_selection_
, &model
,
705 gint cert_index
= -1;
706 gtk_tree_model_get(model
, &iter
, HIERARCHY_INDEX
, &cert_index
, -1);
708 if (cert_index
< 0) {
713 ShowCertExportDialog(NULL
, GTK_WINDOW(viewer
->dialog_
),
714 viewer
->cert_chain_list_
[cert_index
]);
717 void CertificateViewer::Show() {
718 gtk_util::ShowDialog(dialog_
);
723 void ShowCertificateViewer(content::WebContents
* web_contents
,
724 gfx::NativeWindow parent
,
725 net::X509Certificate
* cert
) {
726 (new CertificateViewer(parent
, cert
))->Show();