aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2012-12-29 00:39:40 +0800
committerCarlos Garcia Campos <carlosgc@gnome.org>2013-02-19 19:59:33 +0800
commit86615e3298fa53736a6a2b722be7d45ecffd36db (patch)
tree56a041705b541760e4c04c7a4d7137f790b64d05
parent8acf5ae0ecaf38ce2b0e1529d88a8fde9803b7e4 (diff)
downloadgsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar.gz
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar.bz2
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar.lz
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar.xz
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.tar.zst
gsoc2013-epiphany-86615e3298fa53736a6a2b722be7d45ecffd36db.zip
embed: Implement unsubmitted modified forms warning in WebKit2
Installing a web extension to access the DOM. https://bugzilla.gnome.org/show_bug.cgi?id=684437
-rw-r--r--configure.ac7
-rw-r--r--embed/Makefile.am15
-rw-r--r--embed/ephy-embed-shell.c33
-rw-r--r--embed/ephy-embed-shell.h3
-rw-r--r--embed/ephy-web-view.c20
-rw-r--r--embed/web-extension/Makefile.am20
-rw-r--r--embed/web-extension/ephy-web-extension.c169
-rw-r--r--embed/web-extension/ephy-web-extension.h26
-rw-r--r--src/Makefile.am1
-rw-r--r--src/ephy-main.c6
10 files changed, 292 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index aa5fb3b55..bb13d628a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,7 +83,7 @@ GLIB_REQUIRED=2.35.6
GTK_REQUIRED=3.5.4
LIBXML_REQUIRED=2.6.12
LIBXSLT_REQUIRED=1.1.7
-WEBKIT_GTK_REQUIRED=1.11.2
+WEBKIT_GTK_REQUIRED=1.11.5
LIBSOUP_REQUIRED=2.41.3
GNOME_DESKTOP_REQUIRED=2.91.2
GNOME_KEYRING_REQUIRED=2.26.0
@@ -137,6 +137,10 @@ PKG_CHECK_MODULES([DEPENDENCIES], [
avahi-client >= $AVAHI_REQUIRED
])
+PKG_CHECK_MODULES(WEB_EXTENSION, [$WEBKIT_GTK_PC_NAME >= $WEBKIT_GTK_REQUIRED])
+AC_SUBST(WEB_EXTENSION_CFLAGS)
+AC_SUBST(WEB_EXTENSION_LIBS)
+
# ******************
# Portability checks
# ******************
@@ -255,6 +259,7 @@ lib/egg/Makefile
lib/history/Makefile
lib/widgets/Makefile
embed/Makefile
+embed/web-extension/Makefile
src/Makefile
src/bookmarks/Makefile
po/Makefile.in
diff --git a/embed/Makefile.am b/embed/Makefile.am
index 2df16223d..467cc5453 100644
--- a/embed/Makefile.am
+++ b/embed/Makefile.am
@@ -1,5 +1,9 @@
NULL =
+if WITH_WEBKIT2
+SUBDIRS = web-extension
+endif
+
noinst_LTLIBRARIES = libephyembed.la
NOINST_H_FILES = \
@@ -58,11 +62,12 @@ nodist_libephyembed_la_SOURCES = \
$(BUILT_SOURCES)
libephyembed_la_CPPFLAGS = \
- -I$(top_builddir)/lib \
- -I$(top_srcdir)/lib \
- -I$(top_srcdir)/lib/egg \
- -I$(top_srcdir)/lib/history \
- -I$(top_srcdir)/lib/widgets \
+ -I$(top_srcdir)/embed/web-extension \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/lib/egg \
+ -I$(top_srcdir)/lib/history \
+ -I$(top_srcdir)/lib/widgets \
$(AM_CPPFLAGS)
if WITH_WEBKIT2
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index b4366b2f4..7f48f7c2e 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -33,6 +33,9 @@
#include "ephy-history-service.h"
#include "ephy-profile-utils.h"
#include "ephy-snapshot-service.h"
+#ifdef HAVE_WEBKIT2
+#include "ephy-web-extension.h"
+#endif
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -55,6 +58,9 @@ struct _EphyEmbedShellPrivate
EphyEmbedShellMode mode;
EphyFrecentStore *frecent_store;
guint single_initialised : 1;
+#ifdef HAVE_WEBKIT2
+ GDBusProxy *web_extension;
+#endif
};
enum
@@ -93,6 +99,9 @@ ephy_embed_shell_dispose (GObject *object)
g_clear_object (&priv->global_history_service);
g_clear_object (&priv->embed_single);
g_clear_object (&priv->adblock_manager);
+#ifdef HAVE_WEBKIT2
+ g_clear_object (&priv->web_extension);
+#endif
G_OBJECT_CLASS (ephy_embed_shell_parent_class)->dispose (object);
}
@@ -677,3 +686,27 @@ ephy_embed_shell_launch_handler (EphyEmbedShell *shell,
return ret;
}
+
+#ifdef HAVE_WEBKIT2
+GDBusProxy *
+ephy_embed_shell_get_web_extension_proxy (EphyEmbedShell *shell)
+{
+ EphyEmbedShellPrivate *priv;
+
+ g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL);
+
+ priv = shell->priv;
+ if (!priv->web_extension) {
+ priv->web_extension = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ EPHY_WEB_EXTENSION_SERVICE_NAME,
+ EPHY_WEB_EXTENSION_OBJECT_PATH,
+ EPHY_WEB_EXTENSION_INTERFACE,
+ NULL,
+ NULL);
+ }
+
+ return priv->web_extension;
+}
+#endif
diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h
index 45261e93b..85e7df52c 100644
--- a/embed/ephy-embed-shell.h
+++ b/embed/ephy-embed-shell.h
@@ -102,6 +102,9 @@ gboolean ephy_embed_shell_launch_handler (EphyEmbedShell
GFile *file,
const char *mime_type,
guint32 user_time);
+#ifdef HAVE_WEBKIT2
+GDBusProxy *ephy_embed_shell_get_web_extension_proxy (EphyEmbedShell *shell);
+#endif
G_END_DECLS
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index e65358026..eced9f1ad 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -3417,7 +3417,23 @@ gboolean
ephy_web_view_has_modified_forms (EphyWebView *view)
{
#ifdef HAVE_WEBKIT2
- /* TODO: DOM Bindings */
+ GVariant *result;
+ gboolean retval = FALSE;
+
+ /* FIXME: This should be async */
+ result = g_dbus_proxy_call_sync (ephy_embed_shell_get_web_extension_proxy (ephy_embed_shell_get_default ()),
+ "HasModifiedForms",
+ g_variant_new("(t)", webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (view))),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+
+
+ g_variant_get (result, "(b)", &retval);
+ g_variant_unref (result);
+
+ return retval;
#else
WebKitDOMHTMLCollection *forms = NULL;
WebKitDOMDocument *document = NULL;
@@ -3472,8 +3488,8 @@ ephy_web_view_has_modified_forms (EphyWebView *view)
}
}
}
-#endif
return FALSE;
+#endif
}
/**
diff --git a/embed/web-extension/Makefile.am b/embed/web-extension/Makefile.am
new file mode 100644
index 000000000..fe7277288
--- /dev/null
+++ b/embed/web-extension/Makefile.am
@@ -0,0 +1,20 @@
+webextension_LTLIBRARIES = libephywebextension.la
+
+webextensiondir = \
+ $(libdir)/epiphany/$(EPIPHANY_MAJOR)/web-extensions
+
+libephywebextension_la_SOURCES = \
+ ephy-web-extension.c \
+ ephy-web-extension.h
+
+libephywebextension_la_CPPFLAG = \
+ $(AM_CPPFLAGS)
+
+libephywebextension_la_CFLAGS = \
+ $(WEB_EXTENSION_CFLAGS)
+
+libephywebextension_la_LIBADD = \
+ $(WEB_EXTENSION_LIBS)
+
+libephywebextension_la_LDFLAGS = \
+ -module -avoid-version -no-undefined
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
new file mode 100644
index 000000000..1650026a3
--- /dev/null
+++ b/embed/web-extension/ephy-web-extension.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * 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-web-extension.h"
+
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+
+static const char introspection_xml[] =
+ "<node>"
+ " <interface name='org.gnome.Epiphany.WebExtension'>"
+ " <method name='HasModifiedForms'>"
+ " <arg type='t' name='page_id' direction='in'/>"
+ " <arg type='b' name='has_modified_forms' direction='out'/>"
+ " </method>"
+ " </interface>"
+ "</node>";
+
+#define MIN_INPUT_LENGTH 50
+
+static gboolean
+ephy_web_extension_page_has_modified_forms (WebKitWebPage *web_page)
+{
+ WebKitDOMHTMLCollection *forms = NULL;
+ WebKitDOMDocument *document = NULL;
+ gulong forms_n;
+ int i;
+
+ document = webkit_web_page_get_dom_document (web_page);
+ forms = webkit_dom_document_get_forms (document);
+ forms_n = webkit_dom_html_collection_get_length (forms);
+
+ for (i = 0; i < forms_n; i++) {
+ WebKitDOMHTMLCollection *elements;
+ WebKitDOMNode *form_element = webkit_dom_html_collection_item (forms, i);
+ gulong elements_n;
+ int j;
+ gboolean modified_input_element = FALSE;
+
+ elements = webkit_dom_html_form_element_get_elements (WEBKIT_DOM_HTML_FORM_ELEMENT (form_element));
+ elements_n = webkit_dom_html_collection_get_length (elements);
+
+ for (j = 0; j < elements_n; j++) {
+ WebKitDOMNode *element;
+
+ element = webkit_dom_html_collection_item (elements, j);
+
+ if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT (element))
+ if (webkit_dom_html_text_area_element_is_edited (WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT (element)))
+ return TRUE;
+
+ if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element))
+ if (webkit_dom_html_input_element_is_edited (WEBKIT_DOM_HTML_INPUT_ELEMENT (element))) {
+ glong length;
+ char *text;
+
+ /* A small heuristic here. If there's only one input element
+ * modified and it does not have a lot of text the user is
+ * likely not very interested in saving this work, so do
+ * nothing (eg, google search input). */
+ if (modified_input_element)
+ return TRUE;
+
+ modified_input_element = TRUE;
+
+ text = webkit_dom_html_input_element_get_value (WEBKIT_DOM_HTML_INPUT_ELEMENT (element));
+ length = g_utf8_strlen (text, -1);
+ g_free (text);
+
+ if (length > MIN_INPUT_LENGTH)
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const char *sender,
+ const char *object_path,
+ const char *interface_name,
+ const char *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ WebKitWebExtension *web_extension = WEBKIT_WEB_EXTENSION (user_data);
+ WebKitWebPage *web_page;
+ guint64 page_id;
+
+ if (g_strcmp0 (interface_name, EPHY_WEB_EXTENSION_INTERFACE) != 0)
+ return;
+
+ g_variant_get(parameters, "(t)", &page_id);
+ web_page = webkit_web_extension_get_page (web_extension, page_id);
+ if (!web_page) {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
+ "Invalid page ID: %"G_GUINT64_FORMAT, page_id);
+ return;
+ }
+
+ if (g_strcmp0 (method_name, "HasModifiedForms") == 0) {
+ gboolean has_modifed_forms;
+
+ has_modifed_forms = ephy_web_extension_page_has_modified_forms (web_page);
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", has_modifed_forms));
+ }
+}
+
+static const GDBusInterfaceVTable interface_vtable = {
+ handle_method_call,
+ NULL,
+ NULL
+};
+
+static void
+bus_acquired_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ guint registration_id;
+ GError *error = NULL;
+ static GDBusNodeInfo *introspection_data = NULL;
+ if (!introspection_data)
+ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+
+ registration_id = g_dbus_connection_register_object (connection,
+ EPHY_WEB_EXTENSION_OBJECT_PATH,
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ g_object_ref (user_data),
+ (GDestroyNotify)g_object_unref,
+ &error);
+ if (!registration_id) {
+ g_warning ("Failed to register object: %s\n", error->message);
+ g_error_free (error);
+ }
+}
+
+G_MODULE_EXPORT void
+webkit_web_extension_initialize (WebKitWebExtension *extension)
+{
+ g_bus_own_name (G_BUS_TYPE_SESSION,
+ EPHY_WEB_EXTENSION_SERVICE_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ bus_acquired_cb,
+ NULL, NULL,
+ g_object_ref (extension),
+ (GDestroyNotify)g_object_unref);
+}
diff --git a/embed/web-extension/ephy-web-extension.h b/embed/web-extension/ephy-web-extension.h
new file mode 100644
index 000000000..7792480a5
--- /dev/null
+++ b/embed/web-extension/ephy-web-extension.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#ifndef EPHY_WEB_EXTENSION_H
+#define EPHY_WEB_EXTENSION_H
+
+#define EPHY_WEB_EXTENSION_SERVICE_NAME "org.gnome.Epiphany.WebExtension"
+#define EPHY_WEB_EXTENSION_OBJECT_PATH "/org/gnome/Epiphany/WebExtension"
+#define EPHY_WEB_EXTENSION_INTERFACE "org.gnome.Epiphany.WebExtension"
+
+#endif /* EPHY_WEB_EXTENSION_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index 910851b4d..a901b8b8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -140,6 +140,7 @@ epiphany_CPPFLAGS = \
-I$(top_srcdir)/src/bookmarks \
-DDATADIR=\""$(datadir)"\" \
-DGNOMELOCALEDIR=\"$(datadir)/locale\" \
+ -DEPHY_WEB_EXTENSIONS_DIR=\""$(libdir)/epiphany/$(EPIPHANY_MAJOR)/web-extensions"\" \
$(INCINTL) \
$(AM_CPPFLAGS)
diff --git a/src/ephy-main.c b/src/ephy-main.c
index 3a464e476..7c38fd952 100644
--- a/src/ephy-main.c
+++ b/src/ephy-main.c
@@ -458,6 +458,12 @@ main (int argc,
gtk_window_set_default_icon_name ("web-browser");
}
+#ifdef HAVE_WEBKIT2
+ /* Set the web extensions dir ASAP before the process is launched */
+ webkit_web_context_set_web_extensions_directory (webkit_web_context_get_default (),
+ EPHY_WEB_EXTENSIONS_DIR);
+#endif
+
ephy_embed_prefs_init ();
_ephy_shell_create_instance (mode);