[epiphany/tls-errors] Allow clicking through the TLS error page



commit e0ecc90c0c8e76934e25f92991f8caeeeba88932
Author: Michael Catanzaro <mcatanzaro igalia com>
Date:   Thu Jul 10 12:27:59 2014 -0500

    Allow clicking through the TLS error page
    
    We decided not to show the certificate dialog, but adopt Chromium's
    approach and simply allow the user to visit the page if he really wants
    to.
    
    This can be revisited in the future if desired.

 embed/ephy-embed-shell.c                 |   42 ++++++++--------
 embed/ephy-web-view.c                    |   78 ++++++++++++++++++++++--------
 embed/ephy-web-view.h                    |    4 +-
 embed/web-extension/ephy-web-extension.c |   36 +++++++-------
 src/ephy-window.c                        |   48 ++++++------------
 src/resources/tls-error.html             |    6 +-
 6 files changed, 116 insertions(+), 98 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 01d6832..3b44e2d 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -62,7 +62,7 @@ struct _EphyEmbedShellPrivate
   guint web_extensions_page_created_signal_id;
   guint web_extensions_form_auth_save_signal_id;
   guint web_extensions_remove_from_overview_signal_id;
-  guint web_extensions_open_certificate_viewer_signal_id;
+  guint web_extensions_allow_tls_certificate_signal_id;
 };
 
 enum
@@ -71,7 +71,7 @@ enum
   RESTORED_WINDOW,
   WEB_VIEW_CREATED,
   PAGE_CREATED,
-  OPEN_CERTIFICATE_VIEWER_REQUEST,
+  ALLOW_TLS_CERTIFICATE,
 
   LAST_SIGNAL
 };
@@ -269,15 +269,15 @@ web_extension_remove_from_overview (GDBusConnection *connection,
 }
 
 static void
-web_extension_open_certificate_viewer (GDBusConnection *connection,
-                                       const char *sender_name,
-                                       const char *object_path,
-                                       const char *interface_name,
-                                       const char *signal_name,
-                                       GVariant *parameters,
-                                       EphyEmbedShell *shell)
+web_extension_allow_tls_certificate (GDBusConnection *connection,
+                                              const char *sender_name,
+                                              const char *object_path,
+                                              const char *interface_name,
+                                              const char *signal_name,
+                                              GVariant *parameters,
+                                              EphyEmbedShell *shell)
 {
-  g_signal_emit (shell, signals[OPEN_CERTIFICATE_VIEWER_REQUEST], 0);
+  g_signal_emit (shell, signals[ALLOW_TLS_CERTIFICATE], 0);
 }
 
 static void
@@ -554,15 +554,15 @@ ephy_embed_shell_setup_web_extensions_connection (EphyEmbedShell *shell)
                                         (GDBusSignalCallback)web_extension_remove_from_overview,
                                         shell,
                                         NULL);
-  shell->priv->web_extensions_open_certificate_viewer_signal_id =
+  shell->priv->web_extensions_allow_tls_certificate_signal_id =
     g_dbus_connection_signal_subscribe (shell->priv->bus,
                                         NULL,
                                         EPHY_WEB_EXTENSION_INTERFACE,
-                                        "OpenCertificateViewer",
+                                        "AllowTLSCertificate",
                                         EPHY_WEB_EXTENSION_OBJECT_PATH,
                                         NULL,
                                         G_DBUS_SIGNAL_FLAGS_NONE,
-                                        (GDBusSignalCallback)web_extension_open_certificate_viewer,
+                                        (GDBusSignalCallback)web_extension_allow_tls_certificate,
                                         shell,
                                         NULL);
 }
@@ -666,9 +666,9 @@ ephy_embed_shell_shutdown (GApplication* application)
     priv->web_extensions_remove_from_overview_signal_id = 0;
   }
 
-  if (priv->web_extensions_open_certificate_viewer_signal_id > 0) {
-    g_dbus_connection_signal_unsubscribe (priv->bus, priv->web_extensions_open_certificate_viewer_signal_id);
-    priv->web_extensions_open_certificate_viewer_signal_id = 0;
+  if (priv->web_extensions_allow_tls_certificate_signal_id > 0) {
+    g_dbus_connection_signal_unsubscribe (priv->bus, priv->web_extensions_allow_tls_certificate_signal_id);
+    priv->web_extensions_allow_tls_certificate_signal_id = 0;
   }
 
   g_list_foreach (priv->web_extensions, (GFunc)ephy_embed_shell_unwatch_web_extension, application);
@@ -818,15 +818,15 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass)
                   EPHY_TYPE_WEB_EXTENSION_PROXY);
 
   /**
-   * EphyEmbedShell::open-certificate-viewer-request:
+   * EphyEmbedShell::allow-tls-certificate:
    * @shell: the #EphyEmbedShell
    *
    * The ::open-certificate-viewer-request signal is emitted when
-   * the web extension requests the certificate viewer be displayed
-   * for the current page. It is intended for use by #EphyWindow.
+   * the web extension requests an exception be permitted for the
+   * invalid TLS certificate on the current page.
    */
-  signals[OPEN_CERTIFICATE_VIEWER_REQUEST] =
-    g_signal_new ("open-certificate-viewer-request",
+  signals[ALLOW_TLS_CERTIFICATE] =
+    g_signal_new ("allow-tls-certificate",
                   EPHY_TYPE_EMBED_SHELL,
                   G_SIGNAL_RUN_FIRST,
                   0, NULL, NULL,
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index be6ef57..965a0fd 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -2,7 +2,7 @@
 /* vim: set sw=2 ts=2 sts=2 et: */
 /*
  *  Copyright © 2008, 2009 Gustavo Noronha Silva
- *  Copyright © 2009, 2010 Igalia S.L.
+ *  Copyright © 2009, 2010, 2014 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
@@ -107,7 +107,11 @@ struct _EphyWebViewPrivate {
   /* TLS information. */
   GTlsCertificate *certificate;
   GTlsCertificateFlags tls_errors;
-  WebKitCertificateInfo *last_tls_error_info;
+
+  gboolean loading_tls_error_page;
+  /* Valid only if we are currently viewing the TLS error page */
+  WebKitCertificateInfo *tls_error_page_info;
+  char *tls_error_page_host;
 
   /* Web Extension */
   EphyWebExtensionProxy *web_extension;
@@ -760,8 +764,15 @@ ephy_web_view_finalize (GObject *object)
   g_free (priv->link_message);
   g_free (priv->loading_message);
 
-  if (priv->last_tls_error_info != NULL)
-    webkit_certificate_info_free (priv->last_tls_error_info);
+  if (priv->tls_error_page_info != NULL) {
+    g_warn_if_fail (priv->tls_error_page_host != NULL);
+    webkit_certificate_info_free (priv->tls_error_page_info);
+  } else {
+    g_warn_if_fail (priv->tls_error_page_host == NULL);
+  }
+
+  if (priv->tls_error_page_host != NULL)
+    g_free (priv->tls_error_page_host);
 
   G_OBJECT_CLASS (ephy_web_view_parent_class)->finalize (object);
 }
@@ -1596,6 +1607,24 @@ load_changed_cb (WebKitWebView *web_view,
 
     ephy_web_view_set_security_level (EPHY_WEB_VIEW (web_view), security_level);
 
+    if (priv->loading_tls_error_page) {
+      /* On the next load, either we won't be, or this well be set again. */
+      priv->loading_tls_error_page = false;
+    } else {
+      if (priv->tls_error_page_info != NULL) {
+        g_warn_if_fail (priv->tls_error_page_host != NULL);
+        webkit_certificate_info_free (priv->tls_error_page_info);
+        priv->tls_error_page_info = NULL;
+      } else {
+        g_warn_if_fail (priv->tls_error_page_host == NULL);
+      }
+
+      if (priv->tls_error_page_host != NULL) {
+        g_free (priv->tls_error_page_host);
+        priv->tls_error_page_host = NULL;
+      }
+    }
+
     /* History. */
     if (!ephy_web_view_is_history_frozen (view)) {
       char *history_uri = NULL;
@@ -1889,10 +1918,13 @@ tls_error_cb (WebKitWebView *web_view,
   char *stylesheet;
   GBytes *html_file;
 
-  /* Save this or we'll lose it, since pressing the button triggers a new load. */
-  if (priv->last_tls_error_info != NULL)
-    webkit_certificate_info_free (priv->last_tls_error_info);
-  priv->last_tls_error_info = webkit_certificate_info_copy (info);
+  if (priv->tls_error_page_info != NULL)
+    webkit_certificate_info_free (priv->tls_error_page_info);
+  if (priv->tls_error_page_host != NULL)
+    g_free (priv->tls_error_page_host);
+  priv->loading_tls_error_page = TRUE;
+  priv->tls_error_page_info = webkit_certificate_info_copy (info);
+  priv->tls_error_page_host = g_strdup (host);
 
   priv->load_failed = TRUE;
   ephy_web_view_set_link_message (view, NULL);
@@ -1929,7 +1961,7 @@ tls_error_cb (WebKitWebView *web_view,
                    _("Look out!"),
                    msg,
                    /* Button on error page when a website's TLS certificate is invalid */
-                   _("Create Security Exception…"));
+                   _("Load Anyway"));
 
   g_bytes_unref (html_file);
   g_free (msg);
@@ -2897,26 +2929,30 @@ ephy_web_view_set_visit_type (EphyWebView *view, EphyHistoryPageVisitType visit_
 }
 
 /**
- * ephy_web_view_get_last_tls_error_info:
+ * ephy_web_view_allow_certificate_exception:
  * @view: an #EphyWebView
- * @certificate: (out) (transfer none): return value of TLS certificate, or NULL
- * @errors: (out): return value of TLS errors
+ *
+ * Adds a temporary exception to allow visiting the current page. This
+ * function does nothing if the current page did not present an invalid
+ * TLS certificate.
  **/
 void
-ephy_web_view_get_last_tls_error_info (EphyWebView *view,
-                                       GTlsCertificate **certificate,
-                                       GTlsCertificateFlags *errors)
+ephy_web_view_allow_certificate_exception (EphyWebView *view)
 {
-  WebKitCertificateInfo *info = view->priv->last_tls_error_info;
+  EphyWebViewPrivate *priv = view->priv;
 
   g_return_if_fail (EPHY_IS_WEB_VIEW (view));
 
-  if (info == NULL) {
-    *certificate = NULL;
-    *errors = 0;
+  /* Beware: this page has already loaded. */
+  g_warn_if_fail (!priv->loading_tls_error_page);
+
+  if (priv->tls_error_page_info == NULL) {
+    g_return_if_fail (priv->tls_error_page_host == NULL);
+    g_warning ("Attempt to add certificate security exception when not viewing TLS error page");
     return;
   }
 
-  *certificate = webkit_certificate_info_get_tls_certificate (info);
-  *errors = webkit_certificate_info_get_tls_errors (info);
+  webkit_web_context_allow_tls_certificate_for_host (webkit_web_context_get_default (),
+                                                     priv->tls_error_page_info,
+                                                     priv->tls_error_page_host);
 }
diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h
index 7551e99..9effd0d 100644
--- a/embed/ephy-web-view.h
+++ b/embed/ephy-web-view.h
@@ -174,9 +174,7 @@ void                       ephy_web_view_get_web_app_title        (EphyWebView
 char                      *ephy_web_view_get_web_app_title_finish (EphyWebView               *view,
                                                                    GAsyncResult              *result,
                                                                    GError                   **error);
-void                       ephy_web_view_get_last_tls_error_info  (EphyWebView               *view,
-                                                                   GTlsCertificate          **certificate,
-                                                                   GTlsCertificateFlags      *errors);
+void                    ephy_web_view_allow_certificate_exception (EphyWebView               *view);
 
 G_END_DECLS
 
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
index 9ae6a7d..96ae3a6 100644
--- a/embed/web-extension/ephy-web-extension.c
+++ b/embed/web-extension/ephy-web-extension.c
@@ -107,7 +107,7 @@ static const char introspection_xml[] =
   "   <arg type='s' name='host' direction='in'/>"
   "  </method>"
   "  <method name='HistoryClear'/>"
-  "  <signal name='OpenCertificateViewer'/>"
+  "  <signal name='AllowTLSCertificate'/>"
   " </interface>"
   "</node>";
 
@@ -1247,12 +1247,12 @@ static const GDBusInterfaceVTable interface_vtable = {
 };
 
 static JSValueRef
-open_certificate_viewer_cb (JSContextRef context,
-                            JSObjectRef function,
-                            JSObjectRef this_object,
-                            size_t argument_count,
-                            const JSValueRef arguments[],
-                            JSValueRef *exception)
+allow_tls_certificate_cb (JSContextRef context,
+                          JSObjectRef function,
+                          JSObjectRef this_object,
+                          size_t argument_count,
+                          const JSValueRef arguments[],
+                          JSValueRef *exception)
 {
   EphyWebExtension *extension;
   GError *error = NULL;
@@ -1266,12 +1266,12 @@ open_certificate_viewer_cb (JSContextRef context,
                                  NULL,
                                  EPHY_WEB_EXTENSION_OBJECT_PATH,
                                  EPHY_WEB_EXTENSION_INTERFACE,
-                                 "OpenCertificateViewer",
+                                 "AllowTLSCertificate",
                                  NULL,
                                  &error);
 
   if (error) {
-    g_warning ("Error emitting signal OpenCertificateViewer: %s\n", error->message);
+    g_warning ("Error emitting signal AllowTLSCertificate: %s\n", error->message);
     g_error_free (error);
   }
 
@@ -1280,15 +1280,15 @@ open_certificate_viewer_cb (JSContextRef context,
 
 static const JSStaticFunction certificate_viewer_static_funcs[] =
 {
-  { "open", open_certificate_viewer_cb, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+  { "allowException", allow_tls_certificate_cb, kJSPropertyAttributeReadOnly | 
kJSPropertyAttributeDontDelete },
   { NULL, NULL, 0 }
 };
 
 static void
-prepare_certificate_viewer_js (WebKitScriptWorld *world,
-                               WebKitWebPage *web_page,
-                               WebKitFrame *frame,
-                               EphyWebExtension *extension)
+prepare_certificate_exception_js (WebKitScriptWorld *world,
+                                  WebKitWebPage *web_page,
+                                  WebKitFrame *frame,
+                                  EphyWebExtension *extension)
 {
   JSGlobalContextRef context;
   JSObjectRef global_object;
@@ -1301,12 +1301,12 @@ prepare_certificate_viewer_js (WebKitScriptWorld *world,
   global_object = JSContextGetGlobalObject (context);
 
   class_def = kJSClassDefinitionEmpty;
-  class_def.className = "CertificateViewer";
+  class_def.className = "EpiphanyTLSCertificateErrorPage";
   class_def.staticFunctions = certificate_viewer_static_funcs;
 
   class = JSClassCreate (&class_def);
   class_object = JSObjectMake (context, class, extension);
-  str = JSStringCreateWithUTF8CString ("CertificateViewer");
+  str = JSStringCreateWithUTF8CString ("EpiphanyTLSCertificateErrorPage");
   JSObjectSetProperty (context, global_object, str, class_object, kJSPropertyAttributeNone, NULL);
 
   JSClassRelease (class);
@@ -1341,8 +1341,8 @@ window_object_cleared_cb (WebKitScriptWorld *world,
     return;
   }
 
-  // FIXME ideally would not be available to all pages...
-  prepare_certificate_viewer_js (world, web_page, frame, extension);
+  /* EphyWebView ensures this JS can only take effect when used from our TLS error page. */
+  prepare_certificate_exception_js (world, web_page, frame, extension);
 }
 
 static void
diff --git a/src/ephy-window.c b/src/ephy-window.c
index e1e5892..1de4ed7 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -3095,41 +3095,16 @@ zoom_to_level_cb (GtkAction *action,
 }
 
 static void
-open_certificate_viewer (EphyWindow *window,
-                         GTlsCertificate *certificate,
-                         GTlsCertificateFlags tls_errors)
-{
-       EphyWindowPrivate *priv = window->priv;
-       GtkWidget *certificate_dialog;
-
-       g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
-
-       certificate_dialog = ephy_certificate_dialog_new (GTK_WINDOW (window),
-                                                         ephy_location_controller_get_address 
(priv->location_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 void
-open_certificate_viewer_request_cb (EphyEmbedShell *embed_shell,
-                                   gpointer user_data)
+allow_tls_certificate_cb (EphyEmbedShell *embed_shell,
+                         gpointer user_data)
 {
        EphyWindow *window = EPHY_WINDOW (user_data);
        EphyWindowPrivate *priv = window->priv;
        EphyWebView *view;
-       GTlsCertificate *certificate;
-       GTlsCertificateFlags tls_errors;
 
-       /* We're on the TLS error page */
        view = ephy_embed_get_web_view (priv->active_embed);
-       ephy_web_view_get_last_tls_error_info (view, &certificate, &tls_errors);
-
-       open_certificate_viewer (window, certificate, tls_errors);
+       ephy_web_view_allow_certificate_exception (view);
+       ephy_web_view_load_url (view, ephy_web_view_get_address (view));
 }
 
 static void
@@ -3138,6 +3113,7 @@ lock_clicked_cb (EphyLocationController *controller,
 {
        EphyWindowPrivate *priv = window->priv;
        EphyWebView *view;
+       GtkWidget *certificate_dialog;
        GTlsCertificate *certificate;
        GTlsCertificateFlags tls_errors;
 
@@ -3147,7 +3123,15 @@ lock_clicked_cb (EphyLocationController *controller,
        g_return_if_fail (certificate);
        g_return_if_fail (G_IS_TLS_CERTIFICATE (certificate));
 
-       open_certificate_viewer (window, certificate, tls_errors);
+       certificate_dialog = ephy_certificate_dialog_new (GTK_WINDOW (window),
+                                                         ephy_location_controller_get_address 
(priv->location_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 *
@@ -3451,8 +3435,8 @@ ephy_window_constructor (GType type,
        ephy_window_set_chrome (window, chrome);
 
         g_signal_connect (ephy_embed_shell_get_default (),
-                         "open-certificate-viewer-request",
-                         G_CALLBACK (open_certificate_viewer_request_cb),
+                         "allow-tls-certificate",
+                         G_CALLBACK (allow_tls_certificate_cb),
                          object);
 
        return object;
diff --git a/src/resources/tls-error.html b/src/resources/tls-error.html
index c91c5e0..2121d75 100644
--- a/src/resources/tls-error.html
+++ b/src/resources/tls-error.html
@@ -23,9 +23,9 @@
   <style type="text/css">%s</style>
   </style>
   <script type="text/javascript">
-    function open_certificate_viewer()
+    function allow_exception()
     {
-      CertificateViewer.open();
+      EpiphanyTLSCertificateErrorPage.allowException();
     }
   </script>
 </head>
@@ -37,7 +37,7 @@
             %s
           </div>
           <div class="buttonbox">
-            <button onclick="javascript:open_certificate_viewer()">%s</button>
+            <button onclick="javascript:allow_exception()">%s</button>
           </div>
       </div>
   </div>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]