[evolution/wip-webkit2] Move Prefer-plain module to WK2



commit fd42435cde3036c86fc9eeb171b251baccc118c5
Author: Tomas Popela <tpopela redhat com>
Date:   Tue Oct 29 16:08:31 2013 +0100

    Move Prefer-plain module to WK2

 configure.ac                                       |    1 +
 .../e-mail-display-popup-prefer-plain.c            |  179 ++++++++++++++++---
 modules/prefer-plain/web-extension/Makefile.am     |   18 ++
 .../module-prefer-plain-web-extension.c            |  187 ++++++++++++++++++++
 .../module-prefer-plain-web-extension.h            |   26 +++
 5 files changed, 383 insertions(+), 28 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0576c6a..f3223a0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1548,6 +1548,7 @@ modules/plugin-lib/Makefile
 modules/plugin-manager/Makefile
 modules/prefer-plain/Makefile
 modules/prefer-plain/plugin/Makefile
+modules/prefer-plain/web-extension/Makefile
 modules/settings/Makefile
 modules/spamassassin/Makefile
 modules/startup-wizard/Makefile
diff --git a/modules/prefer-plain/e-mail-display-popup-prefer-plain.c 
b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
index f9d8a9d..293cb1a 100644
--- a/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
+++ b/modules/prefer-plain/e-mail-display-popup-prefer-plain.c
@@ -24,6 +24,8 @@
 #include <shell/e-shell-window.h>
 #include "mail/e-mail-browser.h"
 
+#include "web-extension/module-prefer-plain-web-extension.h"
+
 #include <libebackend/libebackend.h>
 
 #include <glib/gi18n-lib.h>
@@ -36,12 +38,13 @@ typedef struct _EMailDisplayPopupPreferPlainClass EMailDisplayPopupPreferPlainCl
 struct _EMailDisplayPopupPreferPlain {
        EExtension parent;
 
-       WebKitDOMDocument *document;
        gchar *text_plain_id;
        gchar *text_html_id;
 
        GtkActionGroup *action_group;
 
+       GDBusProxy *web_extension;
+       gint web_extension_watch_name_id;
 };
 
 struct _EMailDisplayPopupPreferPlainClass {
@@ -91,20 +94,94 @@ static const gchar *ui_reader =
 "</ui>";
 
 static void
+web_extension_proxy_created_cb (GDBusProxy *proxy,
+                                GAsyncResult *result,
+                                EMailDisplayPopupPreferPlain *pp_extension)
+{
+       GError *error = NULL;
+
+       pp_extension->web_extension = g_dbus_proxy_new_finish (result, &error);
+       if (!pp_extension->web_extension) {
+               g_warning ("Error creating web extension proxy: %s\n", error->message);
+               g_error_free (error);
+       }
+}
+
+static void
+web_extension_appeared_cb (GDBusConnection *connection,
+                           const gchar *name,
+                           const gchar *name_owner,
+                           EMailDisplayPopupPreferPlain *pp_extension)
+{
+       g_dbus_proxy_new (
+               connection,
+               G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
+               G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+               G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+               NULL,
+               name,
+               MODULE_PREFER_PLAIN_WEB_EXTENSION_OBJECT_PATH,
+               MODULE_PREFER_PLAIN_WEB_EXTENSION_INTERFACE,
+               NULL,
+               (GAsyncReadyCallback)web_extension_proxy_created_cb,
+               pp_extension);
+}
+
+static void
+web_extension_vanished_cb (GDBusConnection *connection,
+                           const gchar *name,
+                           EMailDisplayPopupPreferPlain *pp_extension)
+{
+       g_clear_object (&pp_extension->web_extension);
+}
+
+static void
+mail_display_popup_prefer_plain_watch_web_extension (EMailDisplayPopupPreferPlain *pp_extension)
+{
+       char *service_name;
+
+       service_name = g_strdup_printf ("%s-%u", MODULE_PREFER_PLAIN_WEB_EXTENSION_SERVICE_NAME, getpid ());
+       pp_extension->web_extension_watch_name_id =
+               g_bus_watch_name (
+                       G_BUS_TYPE_SESSION,
+                       service_name,
+                       G_BUS_NAME_WATCHER_FLAGS_NONE,
+                       (GBusNameAppearedCallback) web_extension_appeared_cb,
+                       (GBusNameVanishedCallback) web_extension_vanished_cb,
+                       pp_extension, NULL);
+
+       g_free (service_name);
+}
+
+static void
 toggle_part (GtkAction *action,
              EMailDisplayPopupExtension *extension)
 {
        EMailDisplayPopupPreferPlain *pp_extension = (EMailDisplayPopupPreferPlain *) extension;
-       WebKitDOMDocument *doc = pp_extension->document;
-       WebKitDOMDOMWindow *window;
-       WebKitDOMElement *frame_element;
        SoupURI *soup_uri;
        GHashTable *query;
+       const gchar *document_uri;
        gchar *uri;
 
-       uri = webkit_dom_document_get_document_uri (doc);
-       soup_uri = soup_uri_new (uri);
-       g_free (uri);
+       if (pp_extension->web_extension) {
+               GVariant *result;
+
+               /* Get URI from saved document */
+               result = g_dbus_proxy_call_sync (
+                               pp_extension->web_extension,
+                               "GetDocumentURI",
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL);
+               if (result) {
+                       document_uri = g_variant_get_string (result, NULL);
+                       g_variant_unref (result);
+               }
+       }
+
+       soup_uri = soup_uri_new (document_uri);
 
        query = soup_form_decode (soup_uri->query);
        g_hash_table_replace (
@@ -125,10 +202,20 @@ toggle_part (GtkAction *action,
        soup_uri_free (soup_uri);
 
        /* Get frame's window and from the window the actual <iframe> element */
-       window = webkit_dom_document_get_default_view (doc);
-       frame_element = webkit_dom_dom_window_get_frame_element (window);
-       webkit_dom_html_iframe_element_set_src (
-               WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame_element), uri);
+       if (pp_extension->web_extension) {
+               GVariant *result;
+
+               result = g_dbus_proxy_call_sync (
+                               pp_extension->web_extension,
+                               "ChangeIFrameSource",
+                               g_variant_new ("(s)", uri),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL);
+               if (result)
+                       g_variant_unref (result);
+       }
 
        g_free (uri);
 }
@@ -223,8 +310,8 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
 {
        EMailDisplay *display;
        GtkAction *action;
-       WebKitDOMNode *node;
-       gchar *uri, *part_id, *pos, *prefix;
+       gchar *part_id, *pos, *prefix;
+       const gchar *document_uri;
        SoupURI *soup_uri;
        GHashTable *query;
        EMailPartList *part_list;
@@ -233,6 +320,9 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
        EMailDisplayPopupPreferPlain *pp_extension;
        GQueue queue = G_QUEUE_INIT;
        GList *head, *link;
+       gint32 x, y;
+       GdkDeviceManager *device_manager;
+       GdkDevice *pointer;
 
        display = E_MAIL_DISPLAY (e_extension_get_extensible (
                        E_EXTENSION (extension)));
@@ -242,22 +332,52 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
        if (!pp_extension->action_group)
                pp_extension->action_group = create_group (extension);
 
-       g_object_get (context, "inner-node", &node, NULL);
-
-       if (!node) {
-               gtk_action_group_set_visible (pp_extension->action_group, FALSE);
-               return;
+       /* In WK2 you can't get the node on what WebKitHitTest was performed,
+        * we have to use other way */
+       device_manager = gdk_display_get_device_manager (
+               gtk_widget_get_display (GTK_WIDGET(display)));
+       pointer = gdk_device_manager_get_client_pointer (device_manager);
+       gdk_window_get_device_position (
+               gtk_widget_get_window (GTK_WIDGET (display)), pointer, &x, &y, NULL);
+
+       if (pp_extension->web_extension) {
+               GVariant *result;
+
+               result = g_dbus_proxy_call_sync (
+                               pp_extension->web_extension,
+                               "SaveDocumentFromPoint",
+                               g_variant_new (
+                                       "(tii)",
+                                       webkit_web_view_get_page_id (
+                                               WEBKIT_WEB_VIEW (display)),
+                                       x, y),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL);
+               if (result)
+                       g_variant_unref (result);
+
+               /* Get URI from saved document */
+               result = g_dbus_proxy_call_sync (
+                               pp_extension->web_extension,
+                               "GetDocumentURI",
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL);
+               if (result) {
+                       document_uri = g_variant_get_string (result, NULL);
+                       g_variant_unref (result);
+               }
        }
 
-       pp_extension->document = webkit_dom_node_get_owner_document (node);
-       uri = webkit_dom_document_get_document_uri (pp_extension->document);
-
-       soup_uri = soup_uri_new (uri);
+       soup_uri = soup_uri_new (document_uri);
        if (!soup_uri || !soup_uri->query) {
                gtk_action_group_set_visible (pp_extension->action_group, FALSE);
                if (soup_uri)
                        soup_uri_free (soup_uri);
-               g_free (uri);
                return;
        }
 
@@ -267,7 +387,6 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
                gtk_action_group_set_visible (pp_extension->action_group, FALSE);
                g_hash_table_destroy (query);
                soup_uri_free (soup_uri);
-               g_free (uri);
                return;
        }
 
@@ -276,7 +395,6 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
                gtk_action_group_set_visible (pp_extension->action_group, FALSE);
                g_hash_table_destroy (query);
                soup_uri_free (soup_uri);
-               g_free (uri);
                return;
        }
 
@@ -285,7 +403,6 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
                gtk_action_group_set_visible (pp_extension->action_group, FALSE);
                g_hash_table_destroy (query);
                soup_uri_free (soup_uri);
-               g_free (uri);
                return;
        }
 
@@ -356,7 +473,6 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte
        g_free (prefix);
        g_hash_table_destroy (query);
        soup_uri_free (soup_uri);
-       g_free (uri);
 }
 
 void
@@ -377,6 +493,11 @@ e_mail_display_popup_prefer_plain_dispose (GObject *object)
                extension->action_group = NULL;
        }
 
+       if (extension->web_extension_watch_name_id > 0) {
+               g_bus_unwatch_name (extension->web_extension_watch_name_id);
+               extension->web_extension_watch_name_id = 0;
+       }
+
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (e_mail_display_popup_prefer_plain_parent_class)->
                dispose (object);
@@ -429,5 +550,7 @@ e_mail_display_popup_prefer_plain_init (EMailDisplayPopupPreferPlain *extension)
        extension->action_group = NULL;
        extension->text_html_id = NULL;
        extension->text_plain_id = NULL;
-       extension->document = NULL;
+       extension->web_extension = NULL;
+
+       mail_display_popup_prefer_plain_watch_web_extension (extension);
 }
diff --git a/modules/prefer-plain/web-extension/Makefile.am b/modules/prefer-plain/web-extension/Makefile.am
new file mode 100644
index 0000000..b7202d9
--- /dev/null
+++ b/modules/prefer-plain/web-extension/Makefile.am
@@ -0,0 +1,18 @@
+webextensions_LTLIBRARIES = libmodulepreferplainwebextension.la
+
+libmodulepreferplainwebextension_la_SOURCES =          \
+       module-preferplain-web-extension.c              \
+       module-preferplain-web-extension.h
+
+libmodulepreferplainwebextension_la_CPPFLAGS =         \
+       -DWEBEXTENSIONS_COMPILATION                     \
+       $(GNOME_PLATFORM_CFLAGS)                        \
+       $(AM_CPPFLAGS)                                  \
+       $(WEB_EXTENSIONS_CFLAGS)
+
+libmodulepreferplainwebextension_la_LIBADD =           \
+       $(GNOME_PLATFORM_LIBS)                          \
+       $(WEB_EXTENSIONS_LIBS)
+
+libmodulepreferplainwebextension_la_LDFLAGS =          \
+       -module -avoid-version -no-undefined
diff --git a/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.c 
b/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.c
new file mode 100644
index 0000000..68c2b10
--- /dev/null
+++ b/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.c
@@ -0,0 +1,187 @@
+/*
+ * module-prefer-plain-web-extension.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "module-prefer-plain-web-extension.h"
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <webkit2/webkit-web-extension.h>
+
+/* FIXME Clean it */
+static GDBusConnection *dbus_connection;
+
+static const char introspection_xml[] =
+"<node>"
+"  <interface name='org.gnome.Evolution.Module.PreferPlain.WebExtension'>"
+"    <method name='ChangeIFrameSource'>"
+"      <arg type='s' name='new_uri' direction='in'/>"
+"    </method>"
+"    <method name='SaveDocumentFromPoint'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"      <arg type='i' name='x' direction='in'/>"
+"      <arg type='i' name='y' direction='in'/>"
+"    </method>"
+"    <method name='GetDocumentURI'>"
+"      <arg type='s' name='document_uri' direction='out'/>"
+"    </method>"
+"  </interface>"
+"</node>";
+
+static WebKitDOMDocument *document_saved = NULL;
+
+static WebKitWebPage *
+get_webkit_web_page_or_return_dbus_error (GDBusMethodInvocation *invocation,
+                                          WebKitWebExtension *web_extension,
+                                          guint64 page_id)
+{
+       WebKitWebPage *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 web_page;
+}
+
+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;
+       WebKitDOMDocument *document;
+       guint64 page_id;
+
+       if (g_strcmp0 (interface_name, MODULE_PREFER_PLAIN_WEB_EXTENSION_INTERFACE) != 0)
+               return;
+
+       if (g_strcmp0 (method_name, "ChangeIFrameSource") == 0) {
+               WebKitDOMDOMWindow *window;
+               WebKitDOMElement *frame_element;
+               const gchar *new_uri;
+
+               g_variant_get (parameters, "(t&s)", &page_id, &new_uri);
+
+               /* Get frame's window and from the window the actual <iframe> element */
+               window = webkit_dom_document_get_default_view (document_saved);
+               frame_element = webkit_dom_dom_window_get_frame_element (window);
+               webkit_dom_html_iframe_element_set_src (
+                       WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame_element), new_uri);
+
+               g_dbus_method_invocation_return_value (invocation, NULL);
+       } else if (g_strcmp0 (method_name, "SaveDocumentFromPoint") == 0) {
+               gint32 x = 0, y = 0;
+               WebKitDOMElement *active_element;
+
+               g_variant_get (parameters, "(tii)", &page_id, &x, &y);
+               web_page = get_webkit_web_page_or_return_dbus_error (invocation, web_extension, page_id);
+               if (!web_page)
+                       return;
+
+               document = webkit_web_page_get_dom_document (web_page);
+               document_saved = document;
+
+               if (x == 0 && y == 0)
+                       active_element = webkit_dom_html_document_get_active_element 
(WEBKIT_DOM_HTML_DOCUMENT (document));
+               else
+                       active_element = webkit_dom_document_element_from_point (document, x,y);
+
+               if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (active_element)) {
+                       document_saved =
+                               webkit_dom_html_iframe_element_get_content_document (
+                                       WEBKIT_DOM_HTML_IFRAME_ELEMENT (active_element));
+               }
+
+               g_dbus_method_invocation_return_value (invocation, NULL);
+       } else if (g_strcmp0 (method_name, "GetDocumentURI") == 0) {
+               gchar *document_uri;
+
+               document_uri = webkit_dom_document_get_document_uri (document_saved);
+
+               g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", document_uri));
+       }
+}
+
+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,
+                       MODULE_PREFER_PLAIN_WEB_EXTENSION_OBJECT_PATH,
+                       introspection_data->interfaces[0],
+                       &interface_vtable,
+                       g_object_ref (user_data),
+                       g_object_unref,
+                       &error);
+
+       if (!registration_id) {
+               g_warning ("Failed to register object: %s\n", error->message);
+               g_error_free (error);
+       } else {
+               dbus_connection = connection;
+               g_object_add_weak_pointer (G_OBJECT (connection), (gpointer *)&dbus_connection);
+       }
+}
+
+/* Forward declaration */
+G_MODULE_EXPORT void webkit_web_extension_initialize (WebKitWebExtension *extension);
+
+G_MODULE_EXPORT void
+webkit_web_extension_initialize (WebKitWebExtension *extension)
+{
+       char *service_name;
+
+       service_name =
+               g_strdup_printf (
+                       "%s-%s",
+                       MODULE_PREFER_PLAIN_WEB_EXTENSION_SERVICE_NAME,
+                       g_getenv ("MODULE_PREFER_PLAIN_WEB_EXTENSION_ID"));
+
+       g_bus_own_name (
+               G_BUS_TYPE_SESSION,
+               service_name,
+               G_BUS_NAME_OWNER_FLAGS_NONE,
+               bus_acquired_cb,
+               NULL, NULL,
+               g_object_ref (extension),
+               g_object_unref);
+
+       g_free (service_name);
+}
diff --git a/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.h 
b/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.h
new file mode 100644
index 0000000..a50a992
--- /dev/null
+++ b/modules/prefer-plain/web-extension/module-prefer-plain-web-extension.h
@@ -0,0 +1,26 @@
+/*
+ * module-prefer-plain-web-extension.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef MODULE_PREFER_PLAIN_WEB_EXTENSION_H
+#define MODULE_PREFER_PLAIN_WEB_EXTENSION_H
+
+#define MODULE_PREFER_PLAIN_WEB_EXTENSION_SERVICE_NAME "org.gnome.Evolution.Module.PreferPlain.WebExtension"
+#define MODULE_PREFER_PLAIN_WEB_EXTENSION_OBJECT_PATH  "/org/gnome/Evolution/Module/PreferPlain/WebExtension"
+#define MODULE_PREFER_PLAIN_WEB_EXTENSION_INTERFACE    "org.gnome.Evolution.Module.PreferPlain.WebExtension"
+
+#endif /* MODULE_PREFER_PLAIN_WEB_EXTENSION_H */


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