diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2012-08-09 18:22:32 +0800 |
---|---|---|
committer | Carlos Garcia Campos <carlosgc@gnome.org> | 2012-08-09 20:50:33 +0800 |
commit | 2baca54cfea1c4b12d2b363d744c72f24f7f71c3 (patch) | |
tree | a6cf2b1087dae4971594582c7ab215046bd52deb | |
parent | 833d2ba2b1f1c08c73f47c0bb3ef843fa94c7055 (diff) | |
download | gsoc2013-epiphany-2baca54cfea1c4b12d2b363d744c72f24f7f71c3.tar.gz gsoc2013-epiphany-2baca54cfea1c4b12d2b363d744c72f24f7f71c3.tar.zst gsoc2013-epiphany-2baca54cfea1c4b12d2b363d744c72f24f7f71c3.zip |
Show information about the SSL errors when clicking on lock icon
If libgcr is available it's used to show the information about the TLS
certificate in the dialog too.
https://bugzilla.gnome.org/show_bug.cgi?id=681506
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/widgets/Makefile.am | 2 | ||||
-rw-r--r-- | lib/widgets/ephy-certificate-dialog.c | 330 | ||||
-rw-r--r-- | lib/widgets/ephy-certificate-dialog.h | 65 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/ephy-window.c | 27 |
6 files changed, 427 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 7fd5d4e63..7ffc0071a 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,7 @@ LIBSOUP_GNOME_REQUIRED=2.39.6 GNOME_KEYRING_REQUIRED=2.26.0 GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=0.0.1 LIBNOTIFY_REQUIRED=0.5.1 +GCR_REQUIRED=3.5.5 AC_ARG_WITH(webkit2, [AC_HELP_STRING([--with-webkit2], [build with WebKit2 [default=no]])], @@ -130,6 +131,7 @@ PKG_CHECK_MODULES([DEPENDENCIES], [ gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED libnotify >= $LIBNOTIFY_REQUIRED sqlite3 + gcr-3 >= $GCR_REQUIRED ]) # ****************** diff --git a/lib/widgets/Makefile.am b/lib/widgets/Makefile.am index 9f751e0d8..8a7e54b81 100644 --- a/lib/widgets/Makefile.am +++ b/lib/widgets/Makefile.am @@ -1,6 +1,8 @@ noinst_LTLIBRARIES = libephywidgets.la libephywidgets_la_SOURCES = \ + ephy-certificate-dialog.c \ + ephy-certificate-dialog.h \ ephy-download-widget.c \ ephy-download-widget.h \ ephy-history-view.c \ diff --git a/lib/widgets/ephy-certificate-dialog.c b/lib/widgets/ephy-certificate-dialog.c new file mode 100644 index 000000000..a1632cdef --- /dev/null +++ b/lib/widgets/ephy-certificate-dialog.c @@ -0,0 +1,330 @@ +/* + * Copyright © 2012 Igalia S.L. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "ephy-certificate-dialog.h" + +#define GCR_API_SUBJECT_TO_CHANGE +#include <gcr/gcr.h> +#include <glib/gi18n.h> +#include <libsoup/soup.h> + +/** + * SECTION:ephy-certificate-dialog + * @short_description: A dialog to show SSL certificate information + * + * #EphyCertificateDialog shows information about SSL certificates. + */ + +enum +{ + PROP_0, + PROP_ADDRESS, + PROP_CERTIFICATE, + PROP_TLS_ERRORS +}; + +struct _EphyCertificateDialogPrivate +{ + GtkWidget *icon; + GtkWidget *title; + GtkWidget *text; +}; + +G_DEFINE_TYPE (EphyCertificateDialog, ephy_certificate_dialog, GTK_TYPE_DIALOG) + +static void +ephy_certificate_dialog_set_address (EphyCertificateDialog *dialog, + const char *address) +{ + SoupURI *uri; + + uri = soup_uri_new (address); + gtk_window_set_title (GTK_WINDOW (dialog), uri->host); + soup_uri_free (uri); +} + +static void +ephy_certificate_dialog_set_certificate (EphyCertificateDialog *dialog, + GTlsCertificate *certificate) +{ + GcrCertificate *simple_certificate; + GByteArray *certificate_data; + GtkWidget *certificate_widget; + GtkWidget *content_area; + + g_object_get (certificate, "certificate", &certificate_data, NULL); + simple_certificate = gcr_simple_certificate_new ((const guchar *)certificate_data->data, + certificate_data->len); + g_byte_array_unref (certificate_data); + + certificate_widget = GTK_WIDGET (gcr_certificate_widget_new (simple_certificate)); + g_object_unref (simple_certificate); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_pack_start (GTK_BOX (content_area), certificate_widget, TRUE, TRUE, 0); + gtk_widget_show (certificate_widget); +} + +static char * +get_error_messages_from_tls_errors (GTlsCertificateFlags tls_errors) +{ + GPtrArray *errors = g_ptr_array_new (); + char *retval; + + if (tls_errors & G_TLS_CERTIFICATE_BAD_IDENTITY) + g_ptr_array_add (errors, _("The certificate does not match the expected identity")); + + if (tls_errors & G_TLS_CERTIFICATE_EXPIRED) + g_ptr_array_add (errors, _("The certificate has expired")); + + if (tls_errors & G_TLS_CERTIFICATE_UNKNOWN_CA) + g_ptr_array_add (errors, _("The signing certificate authority is not known")); + + if (tls_errors & G_TLS_CERTIFICATE_GENERIC_ERROR) + g_ptr_array_add (errors, _("The certificate contains errors")); + + if (tls_errors & G_TLS_CERTIFICATE_REVOKED) + g_ptr_array_add (errors, _("The certificate has been revoked")); + + if (tls_errors & G_TLS_CERTIFICATE_INSECURE) + g_ptr_array_add (errors, _("The certificate is signed using a weak signature algorithm")); + + if (tls_errors & G_TLS_CERTIFICATE_NOT_ACTIVATED) + g_ptr_array_add (errors, _("The certificate activation time is still in the future")); + + if (errors->len == 1) + retval = g_strdup (g_ptr_array_index (errors, 0)); + else { + GString *message = g_string_new (NULL); + guint i; + + for (i = 0; i < errors->len; i++) { + g_string_append_printf (message, "• %s", + (char *)g_ptr_array_index (errors, i)); + if (i < errors->len - 1) + g_string_append_c (message, '\n'); + } + + retval = g_string_free (message, FALSE); + } + + g_ptr_array_free (errors, TRUE); + + return retval; +} + +static void +ephy_certificate_dialog_set_tls_errors (EphyCertificateDialog *dialog, + GTlsCertificateFlags tls_errors) +{ + EphyCertificateDialogPrivate *priv = dialog->priv; + GIcon *icon; + char *markup; + + icon = tls_errors == 0 ? + g_themed_icon_new_with_default_fallbacks ("channel-secure-symbolic") : + g_themed_icon_new_with_default_fallbacks ("channel-insecure-symbolic"); + gtk_image_set_from_gicon (GTK_IMAGE (priv->icon), icon, GTK_ICON_SIZE_DIALOG); + g_object_unref (icon); + + markup = g_strdup_printf ("<span weight=\"bold\" size=\"large\">%s</span>", + tls_errors == 0 ? + _("The identity of this website has been verified") : + _("The identity of this website has not been verified")); + gtk_label_set_markup (GTK_LABEL (priv->title), markup); + g_free (markup); + + if (tls_errors) { + char *text = get_error_messages_from_tls_errors (tls_errors); + + gtk_label_set_text (GTK_LABEL (priv->text), text); + g_free (text); + + gtk_widget_show (priv->text); + } +} + +static void +ephy_certificate_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyCertificateDialog *dialog = EPHY_CERTIFICATE_DIALOG (object); + + switch (prop_id) { + case PROP_ADDRESS: + ephy_certificate_dialog_set_address (dialog, g_value_get_string (value)); + break; + case PROP_CERTIFICATE: + ephy_certificate_dialog_set_certificate (dialog, g_value_get_object (value)); + break; + case PROP_TLS_ERRORS: + ephy_certificate_dialog_set_tls_errors (dialog, g_value_get_flags (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +ephy_certificate_dialog_class_init (EphyCertificateDialogClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = ephy_certificate_dialog_set_property; + + /** + * EphyCertificateDialog:address: + * + * The address of the website. + */ + g_object_class_install_property (object_class, + PROP_ADDRESS, + g_param_spec_string ("address", + "Address", + "The address of the website", + NULL, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyCertificateDialog:certificate: + * + * The certificate of the website. + */ + g_object_class_install_property (object_class, + PROP_CERTIFICATE, + g_param_spec_object ("certificate", + "Certificate", + "The certificate of the website", + G_TYPE_TLS_CERTIFICATE, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyCertificateDialog:tls-errors: + * + * The verification errors on the TLS certificate. + */ + g_object_class_install_property (object_class, + PROP_TLS_ERRORS, + g_param_spec_flags ("tls-errors", + "TLS Errors", + "The verification errors on the TLS certificate", + G_TYPE_TLS_CERTIFICATE_FLAGS, + 0, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_type_class_add_private (object_class, sizeof (EphyCertificateDialogPrivate)); +} + +static void +ephy_certificate_dialog_init (EphyCertificateDialog *dialog) +{ + GtkWidget *vbox, *hbox; + GtkWidget *content_area, *action_area; + EphyCertificateDialogPrivate *priv; + + dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog, + EPHY_TYPE_CERTIFICATE_DIALOG, + EphyCertificateDialogPrivate); + priv = dialog->priv; + + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); + + priv->icon = gtk_image_new (); + gtk_widget_set_halign (priv->icon, GTK_ALIGN_CENTER); + gtk_widget_set_valign (priv->icon, GTK_ALIGN_START); + gtk_box_pack_start (GTK_BOX (hbox), priv->icon, FALSE, FALSE, 0); + gtk_widget_show (priv->icon); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + + priv->title = gtk_label_new (NULL); + gtk_label_set_use_markup (GTK_LABEL (priv->title), TRUE); + gtk_label_set_line_wrap (GTK_LABEL (priv->title), TRUE); + gtk_label_set_selectable (GTK_LABEL (priv->title), TRUE); + gtk_widget_set_halign (priv->title, GTK_ALIGN_START); + gtk_widget_set_valign (priv->title, GTK_ALIGN_START); + gtk_misc_set_alignment (GTK_MISC (priv->title), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), priv->title, FALSE, FALSE, 0); + gtk_widget_show (priv->title); + + priv->text = gtk_label_new (NULL); + gtk_label_set_line_wrap (GTK_LABEL (priv->text), TRUE); + gtk_label_set_selectable (GTK_LABEL (priv->text), TRUE); + gtk_widget_set_halign (priv->text, GTK_ALIGN_START); + gtk_widget_set_valign (priv->text, GTK_ALIGN_START); + gtk_misc_set_alignment (GTK_MISC (priv->text), 0.0, 0.0); + gtk_box_pack_start (GTK_BOX (vbox), priv->text, TRUE, TRUE, 0); + + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + gtk_widget_show (vbox); + + content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); + gtk_box_set_spacing (GTK_BOX (content_area), 14); + gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog)); + gtk_container_set_border_width (GTK_CONTAINER (action_area), 5); + gtk_box_set_spacing (GTK_BOX (action_area), 6); +} + +GtkWidget * +ephy_certificate_dialog_new (GtkWindow *parent, + const char *address, + GTlsCertificate *certificate, + GTlsCertificateFlags tls_errors) +{ + GtkWidget *dialog; + + g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail (G_IS_TLS_CERTIFICATE (certificate), NULL); + + dialog = GTK_WIDGET (g_object_new (EPHY_TYPE_CERTIFICATE_DIALOG, + "address", address, + "certificate", certificate, + "tls-errors", tls_errors, + NULL)); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, + NULL); + if (parent) + gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); + + return dialog; +} + diff --git a/lib/widgets/ephy-certificate-dialog.h b/lib/widgets/ephy-certificate-dialog.h new file mode 100644 index 000000000..2f2a612b6 --- /dev/null +++ b/lib/widgets/ephy-certificate-dialog.h @@ -0,0 +1,65 @@ +/* + * Copyright © 2012 Igalia S.L. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION) +#error "Only <epiphany/epiphany.h> can be included directly." +#endif + +#ifndef EPHY_CERTIFICATE_DIALOG_H +#define EPHY_CERTIFICATE_DIALOG_H + +#include <gio/gio.h> +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +#define EPHY_TYPE_CERTIFICATE_DIALOG (ephy_certificate_dialog_get_type()) +#define EPHY_CERTIFICATE_DIALOG(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_CERTIFICATE_DIALOG, EphyCertificateDialog)) +#define EPHY_IS_CERTIFICATE_DIALOG(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_CERTIFICATE_DIALOG)) +#define EPHY_CERTIFICATE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_CERTIFICATE_DIALOG, EphyCertificateDialogClass)) +#define EPHY_IS_CERTIFICATE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_CERTIFICATE_DIALOG)) +#define EPHY_CERTIFICATE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_CERTIFICATE_DIALOG, EphyCertificateDialogClass)) + +typedef struct _EphyCertificateDialog EphyCertificateDialog; +typedef struct _EphyCertificateDialogClass EphyCertificateDialogClass; +typedef struct _EphyCertificateDialogPrivate EphyCertificateDialogPrivate; + +struct _EphyCertificateDialog +{ + GtkDialog parent_object; + + /*< private >*/ + EphyCertificateDialogPrivate *priv; +}; + +struct _EphyCertificateDialogClass +{ + GtkDialogClass parent_class; +}; + +GType ephy_certificate_dialog_get_type (void); + +GtkWidget *ephy_certificate_dialog_new (GtkWindow *parent, + const char *address, + GTlsCertificate *certificate, + GTlsCertificateFlags tls_errors); + +G_END_DECLS + +#endif diff --git a/po/POTFILES.in b/po/POTFILES.in index 108396bb2..e7211b88b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -25,6 +25,7 @@ lib/ephy-string.c lib/ephy-time-helpers.c lib/ephy-zoom.h lib/history/ephy-history-service-hosts-table.c +lib/widgets/ephy-certificate-dialog.c lib/widgets/ephy-download-widget.c lib/widgets/ephy-hosts-store.c lib/widgets/ephy-hosts-view.c diff --git a/src/ephy-window.c b/src/ephy-window.c index bf91d30b6..c9113c2eb 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -25,6 +25,7 @@ #include "ephy-action-helper.h" #include "ephy-bookmarks-ui.h" +#include "ephy-certificate-dialog.h" #include "ephy-combined-stop-reload-action.h" #include "ephy-debug.h" #include "ephy-download-widget.h" @@ -3429,6 +3430,30 @@ zoom_to_level_cb (GtkAction *action, ephy_window_set_zoom (window, zoom); } +static void +lock_clicked_cb (EphyLocationController *controller, + EphyWindow *window) +{ + EphyWindowPrivate *priv = window->priv; + EphyWebView *view; + GTlsCertificate *certificate; + GTlsCertificateFlags tls_errors; + GtkWidget *certificate_dialog; + + view = ephy_embed_get_web_view (priv->active_embed); + ephy_web_view_get_security_level (view, NULL, &certificate, &tls_errors); + + certificate_dialog = ephy_certificate_dialog_new (GTK_WINDOW (window), + ephy_location_controller_get_address (controller), + certificate, + tls_errors); + gtk_window_set_destroy_with_parent (GTK_WINDOW (certificate_dialog), TRUE); + g_signal_connect (certificate_dialog, "response", + G_CALLBACK (gtk_widget_destroy), + NULL); + gtk_widget_show (certificate_dialog); +} + static GtkWidget * setup_toolbar (EphyWindow *window) { @@ -3559,6 +3584,8 @@ ephy_window_constructor (GType type, G_CALLBACK (sync_user_input_cb), window); g_signal_connect_swapped (priv->location_controller, "open-link", G_CALLBACK (ephy_link_open), window); + g_signal_connect (priv->location_controller, "lock-clicked", + G_CALLBACK (lock_clicked_cb), window); g_signal_connect_swapped (priv->notebook, "open-link", G_CALLBACK (ephy_link_open), window); |