[evolution/wip/mcrha/webkit-jsc-api] Add few automated tests



commit f3384c9cb1404b39e06159bd1a635896ee5eb1a8
Author: Milan Crha <mcrha redhat com>
Date:   Tue Sep 24 16:11:55 2019 +0200

    Add few automated tests

 CMakeLists.txt                       |   2 +-
 src/e-util/CMakeLists.txt            |   7 +-
 src/e-util/e-util.h                  |   3 +-
 src/e-util/e-web-view-jsc-utils.c    | 105 ++++++++++++-
 src/e-util/e-web-view-jsc-utils.h    |   4 +-
 src/e-util/e-web-view.c              |   3 +-
 src/e-util/test-web-view.c           | 284 ++++++++++++++++++++++++++++++++---
 src/web-extensions/CMakeLists.txt    |   8 +
 src/web-extensions/e-web-extension.c |  38 +++++
 src/web-extensions/ext-utils.js      |  34 ++++-
 10 files changed, 454 insertions(+), 34 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2a325ef261..b4c1f3757e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -82,7 +82,7 @@ set(gsettings_desktop_schemas_minimum_version 2.91.92)
 set(libpst_minimum_version 0.6.54)
 set(libxml_minimum_version 2.7.3)
 set(shared_mime_info_minimum_version 0.22)
-set(webkit2gtk_minimum_version 2.16.0)
+set(webkit2gtk_minimum_version 2.26.0)
 
 # Optional Packages
 set(champlain_minimum_version 0.12)
diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt
index 81ae3cd72c..2af4135366 100644
--- a/src/e-util/CMakeLists.txt
+++ b/src/e-util/CMakeLists.txt
@@ -270,8 +270,9 @@ set(SOURCES
        e-util-private.h
        e-webdav-browser.c
        e-web-extension-container.c
-       e-web-view-preview.c
        e-web-view.c
+       e-web-view-jsc-utils.c
+       e-web-view-preview.c
        e-widget-undo.c
        e-xml-utils.c
        ea-calendar-cell.c
@@ -543,8 +544,9 @@ set(HEADERS
        e-util-enums.h
        e-webdav-browser.h
        e-web-extension-container.h
-       e-web-view-preview.h
        e-web-view.h
+       e-web-view-jsc-utils.h
+       e-web-view-preview.h
        e-widget-undo.h
        e-xml-utils.h
        ea-calendar-cell.h
@@ -808,6 +810,7 @@ add_private_programs_simple(
        test-source-config
        test-source-selector
        test-tree-view-frame
+       test-web-view
 )
 
 add_private_program(test-html-editor-units
diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h
index 84db520bed..fa0d82b540 100644
--- a/src/e-util/e-util.h
+++ b/src/e-util/e-util.h
@@ -266,8 +266,9 @@
 #include <e-util/e-webdav-browser.h>
 #include <e-util/e-web-extension-container.h>
 #ifndef E_UTIL_INCLUDE_WITHOUT_WEBKIT
-#include <e-util/e-web-view-preview.h>
 #include <e-util/e-web-view.h>
+#include <e-util/e-web-view-jsc-utils.h>
+#include <e-util/e-web-view-preview.h>
 #endif
 #include <e-util/e-widget-undo.h>
 #include <e-util/e-xml-utils.h>
diff --git a/src/e-util/e-web-view-jsc-utils.c b/src/e-util/e-web-view-jsc-utils.c
index 7ab1f3dd9e..59028b67c1 100644
--- a/src/e-util/e-web-view-jsc-utils.c
+++ b/src/e-util/e-web-view-jsc-utils.c
@@ -21,6 +21,87 @@
 
 #include "e-web-view-jsc-utils.h"
 
+gchar *
+e_web_view_jsc_strdup_call (const gchar *call_format,
+                           ...)
+{
+       GString *script;
+       const gchar *ptr;
+       va_list va;
+
+       g_return_val_if_fail (call_format != NULL, NULL);
+
+       script = g_string_sized_new (128);
+       va_start (va, call_format);
+
+       for (ptr = call_format; *ptr; ptr++) {
+               if (*ptr == '\\') {
+                       g_warn_if_fail (ptr[1]);
+
+                       g_string_append_c (script, ptr[0]);
+                       g_string_append_c (script, ptr[1]);
+
+                       ptr++;
+               } else if (*ptr == '%') {
+                       g_warn_if_fail (ptr[1]);
+
+                       switch (ptr[1]) {
+                       case '%':
+                               g_string_append_c (script, ptr[1]);
+                               break;
+                       case 's': {
+                               const gchar *arg = va_arg (va, const gchar *);
+
+                               /* Enclose strings into double-quotes */
+                               g_string_append_c (script, '\"');
+
+                               /* Escape significant characters */
+                               if (arg && (strchr (arg, '\"') ||
+                                   strchr (arg, '\\') ||
+                                   strchr (arg, '\n') ||
+                                   strchr (arg, '\r') ||
+                                   strchr (arg, '\t'))) {
+                                       const gchar *ptr2;
+
+                                       for (ptr2 = arg; *ptr2; ptr2++) {
+                                               if (*ptr2 == '\\' || *ptr2 == '\"')
+                                                       g_string_append_c (script, '\\');
+                                               else if (*ptr2 == '\r')
+                                                       g_string_append (script, "\\r");
+                                               else if (*ptr2 == '\n')
+                                                       g_string_append (script, "\\n");
+                                               else if (*ptr2 == '\t')
+                                                       g_string_append (script, "\\t");
+                                               g_string_append_c (script, *ptr2);
+                                       }
+                               } else if (arg && *arg) {
+                                       g_string_append (script, arg);
+                               }
+
+                               g_string_append_c (script, '\"');
+
+                               } break;
+                       case 'd': {
+                               gint arg = va_arg (va, gint);
+
+                               g_string_append_printf (script, "%d", arg);
+                               } break;
+                       default:
+                               g_warning ("%s: Unknown percent tag '%c'", G_STRFUNC, *ptr);
+                               break;
+                       }
+
+                       ptr++;
+               } else {
+                       g_string_append_c (script, *ptr);
+               }
+       }
+
+       va_end (va);
+
+       return g_string_free (script, FALSE);
+}
+
 static void
 ewv_jsc_call_done_cb (GObject *source,
                      GAsyncResult *result,
@@ -66,8 +147,8 @@ e_web_view_jsc_set_element_hidden (WebKitWebView *web_view,
        g_return_if_fail (WEBKIT_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id != NULL);
 
-       script = g_strdup_printf ("evo.SetElementHidden(%s,%s,%d)",
-               iframe_id ? iframe_id : "",
+       script = e_web_view_jsc_strdup_call ("Evo.SetElementHidden(%s,%s,%d)",
+               iframe_id,
                element_id,
                value ? 1 : 0);
 
@@ -80,13 +161,21 @@ e_web_view_jsc_set_element_style_property (WebKitWebView *web_view,
                                           const gchar *element_id,
                                           const gchar *property_name,
                                           const gchar *value,
-                                          const gchar *priority,
                                           GCancellable *cancellable)
 {
+       gchar *script;
+
        g_return_if_fail (WEBKIT_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id != NULL);
        g_return_if_fail (property_name != NULL);
 
+       script = e_web_view_jsc_strdup_call ("Evo.SetElementStyleProperty(%s,%s,%s,%s)",
+               iframe_id,
+               element_id,
+               property_name,
+               value);
+
+       webkit_web_view_run_javascript (web_view, script, cancellable, ewv_jsc_call_done_cb, script);
 }
 
 void
@@ -98,8 +187,18 @@ e_web_view_jsc_set_element_attribute (WebKitWebView *web_view,
                                      const gchar *value,
                                      GCancellable *cancellable)
 {
+       gchar *script;
+
        g_return_if_fail (WEBKIT_IS_WEB_VIEW (web_view));
        g_return_if_fail (element_id != NULL);
        g_return_if_fail (qualified_name != NULL);
 
+       script = e_web_view_jsc_strdup_call ("Evo.SetElementAttribute(%s,%s,%s,%s,%s)",
+               iframe_id,
+               element_id,
+               namespace_uri,
+               qualified_name,
+               value);
+
+       webkit_web_view_run_javascript (web_view, script, cancellable, ewv_jsc_call_done_cb, script);
 }
diff --git a/src/e-util/e-web-view-jsc-utils.h b/src/e-util/e-web-view-jsc-utils.h
index e36a6ee7b4..5f382a455a 100644
--- a/src/e-util/e-web-view-jsc-utils.h
+++ b/src/e-util/e-web-view-jsc-utils.h
@@ -26,6 +26,9 @@
 
 G_BEGIN_DECLS
 
+gchar *                e_web_view_jsc_strdup_call      (const gchar *call_format,
+                                                ...) G_GNUC_PRINTF (1, 2);
+
 void           e_web_view_jsc_set_element_hidden
                                                (WebKitWebView *web_view,
                                                 const gchar *iframe_id,
@@ -38,7 +41,6 @@ void          e_web_view_jsc_set_element_style_property
                                                 const gchar *element_id,
                                                 const gchar *property_name,
                                                 const gchar *value,
-                                                const gchar *priority,
                                                 GCancellable *cancellable);
 void           e_web_view_jsc_set_element_attribute
                                                (WebKitWebView *web_view,
diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
index 5caa586a6c..9ff2d79549 100644
--- a/src/e-util/e-web-view.c
+++ b/src/e-util/e-web-view.c
@@ -4025,7 +4025,8 @@ e_web_view_get_default_webkit_settings (void)
                "enable-dns-prefetching", FALSE,
                "enable-html5-local-storage", FALSE,
                "enable-java", FALSE,
-               "enable-javascript", FALSE,
+               "enable-javascript", TRUE, /* Needed for JavaScriptCore API to work */
+               "enable-javascript-markup", FALSE, /* Discards user-provided javascript in HTML */
                "enable-offline-web-application-cache", FALSE,
                "enable-page-cache", FALSE,
                "enable-plugins", FALSE,
diff --git a/src/e-util/test-web-view.c b/src/e-util/test-web-view.c
index b5282d68e1..a1e2fdd5cc 100644
--- a/src/e-util/test-web-view.c
+++ b/src/e-util/test-web-view.c
@@ -72,7 +72,7 @@ test_flag_set (TestFlag *flag)
 
 typedef struct _TestFixture {
        GtkWidget *window;
-       GtkWidget *web_view;
+       WebKitWebView *web_view;
 
        TestFlag *flag;
 } TestFixture;
@@ -126,9 +126,9 @@ test_utils_fixture_set_up (TestFixture *fixture,
 
        fixture->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
-       gtk_window_set_default_size (GTK_WINDOW (fixture->window), 1280, 1024);
+       gtk_window_set_default_size (GTK_WINDOW (fixture->window), 1280, 600);
 
-       fixture->web_view = e_web_view_new ();
+       fixture->web_view = WEBKIT_WEB_VIEW (e_web_view_new ());
        g_object_set (G_OBJECT (fixture->web_view),
                "halign", GTK_ALIGN_FILL,
                "hexpand", TRUE,
@@ -136,9 +136,9 @@ test_utils_fixture_set_up (TestFixture *fixture,
                "vexpand", TRUE,
                NULL);
 
-       gtk_container_add (GTK_CONTAINER (fixture->window), fixture->web_view);
+       gtk_container_add (GTK_CONTAINER (fixture->window), GTK_WIDGET (fixture->web_view));
 
-       settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (fixture->web_view));
+       settings = webkit_web_view_get_settings (fixture->web_view);
        webkit_settings_set_enable_developer_extras (settings, TRUE);
 
        g_signal_connect (
@@ -287,7 +287,7 @@ test_utils_jsc_call (TestFixture *fixture,
        g_return_if_fail (fixture->web_view != NULL);
        g_return_if_fail (script != NULL);
 
-       webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (fixture->web_view), script, NULL, 
test_utils_jsc_call_done_cb, g_strdup (script));
+       webkit_web_view_run_javascript (fixture->web_view, script, NULL, test_utils_jsc_call_done_cb, 
g_strdup (script));
 }
 
 static void
@@ -308,11 +308,75 @@ test_utils_jsc_call_sync (TestFixture *fixture,
        jcd.script = script;
        jcd.out_result = out_result;
 
-       webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (fixture->web_view), script, NULL, 
test_utils_jsc_call_sync_done_cb, &jcd);
+       webkit_web_view_run_javascript (fixture->web_view, script, NULL, test_utils_jsc_call_sync_done_cb, 
&jcd);
 
        test_utils_wait (fixture);
 }
 
+static gboolean
+test_utils_jsc_call_bool_sync (TestFixture *fixture,
+                              const gchar *script)
+{
+       JSCValue *result = NULL;
+       gboolean res;
+
+       test_utils_jsc_call_sync (fixture, script, &result);
+
+       g_assert_nonnull (result);
+       g_assert (jsc_value_is_boolean (result));
+
+       res = jsc_value_to_boolean (result);
+
+       g_clear_object (&result);
+
+       return res;
+}
+
+static gchar *
+test_utils_jsc_call_string_sync (TestFixture *fixture,
+                                const gchar *script)
+{
+       JSCValue *result = NULL;
+       gchar *res;
+
+       test_utils_jsc_call_sync (fixture, script, &result);
+
+       g_assert_nonnull (result);
+       g_assert (jsc_value_is_null (result) || jsc_value_is_string (result));
+
+       if (jsc_value_is_null (result))
+               res = NULL;
+       else
+               res = jsc_value_to_string (result);
+
+       g_clear_object (&result);
+
+       return res;
+}
+
+static void
+test_utils_jsc_call_string_and_verify (TestFixture *fixture,
+                                      const gchar *script,
+                                      const gchar *expected_value)
+{
+       gchar *value;
+
+       value = test_utils_jsc_call_string_sync (fixture, script);
+
+       if (!expected_value)
+               g_assert_null (value);
+       else
+               g_assert_cmpstr (value, ==, expected_value);
+
+       g_free (value);
+}
+
+static void
+test_utils_wait_noop (TestFixture *fixture)
+{
+       test_utils_jsc_call_sync (fixture, "document.title", NULL);
+}
+
 static void
 test_utils_iframe_loaded_cb (WebKitUserContentManager *manager,
                             WebKitJavascriptResult *js_result,
@@ -336,31 +400,28 @@ test_utils_load_iframe_content (TestFixture *fixture,
                                const gchar *content)
 {
        WebKitUserContentManager *manager;
-       GString *escaped_content;
        gchar *script;
        gulong handler_id;
 
-       manager = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (fixture->web_view));
+       manager = webkit_web_view_get_user_content_manager (fixture->web_view);
 
        handler_id = g_signal_connect (manager, "script-message-received::iframeLoaded",
                G_CALLBACK (test_utils_iframe_loaded_cb), fixture);
 
        webkit_user_content_manager_register_script_message_handler (manager, "iframeLoaded");
 
-       script = g_strdup_printf (
-               "Evo.findIFrame(\"%s\").onload = 
window.webkit.messageHandlers.iframeLoaded.postMessage(\"%s\");\n",
+       script = e_web_view_jsc_strdup_call (
+               "Evo.findIFrame(%s).onload = window.webkit.messageHandlers.iframeLoaded.postMessage(%s);\n",
                iframe_id, iframe_id);
 
        test_utils_jsc_call (fixture, script);
 
        g_free (script);
 
-       escaped_content = e_str_replace_string (content, "\"", "\\\"");
-       script = g_strdup_printf ("Evo.SetIFrameContent(\"%s\", \"%s\")", iframe_id, escaped_content->str);
+       script = e_web_view_jsc_strdup_call ("Evo.SetIFrameContent(%s,%s)", iframe_id, content);
 
        test_utils_jsc_call (fixture, script);
 
-       g_string_free (escaped_content, TRUE);
        g_free (script);
 
        test_utils_wait (fixture);
@@ -399,10 +460,195 @@ test_utils_load_string (TestFixture *fixture,
 }
 
 static void
-test_basic (TestFixture *fixture)
+test_utils_load_body (TestFixture *fixture)
+{
+       test_utils_load_string (fixture,
+               "<html><body>"
+               "Top<br>"
+               "<input id=\"btn1\" type=\"button\" value=\"Button1\"><br>"
+               "<iframe id=\"frm1\" src=\"empty:///\"></iframe><br>"
+               "<iframe id=\"frm2\" src=\"empty:///\"></iframe><br>"
+               "<input id=\"btn3\" type=\"button\" value=\"Button3\">"
+               "</body></html>");
+
+       test_utils_load_iframe_content (fixture, "frm1",
+               "<html><body>"
+               "frm1<br>"
+               "<iframe id=\"frm1_1\" src=\"empty:///\"></iframe><br>"
+               "<input id=\"btn1\" type=\"button\" value=\"Button1\">"
+               "</body></html>");
+
+       test_utils_load_iframe_content (fixture, "frm1_1",
+               "<html><body>"
+               "frm1_1<br>"
+               "<input id=\"btn1\" type=\"button\" value=\"Button1\">"
+               "</body></html>");
+
+       test_utils_load_iframe_content (fixture, "frm2",
+               "<html><body>"
+               "frm2<br>"
+               "<input id=\"btn1\" type=\"button\" value=\"Button1\">"
+               "<input id=\"btn2\" type=\"button\" value=\"Button2\">"
+               "</body></html>");
+}
+
+static void
+test_set_element_hidden (TestFixture *fixture)
+{
+       test_utils_load_body (fixture);
+
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "", "btn1", TRUE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "frm1_1", "btn1", TRUE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "frm2", "btn2", TRUE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "", "btn1", FALSE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "frm1", "btn1", FALSE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+
+       e_web_view_jsc_set_element_hidden (fixture->web_view, "frm1_1", "btn1", FALSE, NULL);
+       test_utils_wait_noop (fixture);
+
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"\", \"btn3\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm1_1\", \"btn1\").hidden"));
+       g_assert (!test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn1\").hidden"));
+       g_assert (test_utils_jsc_call_bool_sync (fixture, "Evo.findElement(\"frm2\", \"btn2\").hidden"));
+}
+
+static void
+test_set_element_style_property (TestFixture *fixture)
+{
+       test_utils_load_body (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn3\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").style.getPropertyValue(\"color\")", "");
+
+       e_web_view_jsc_set_element_style_property (fixture->web_view, "", "btn1", "color", "blue", NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn1\").style.getPropertyValue(\"color\")", "blue");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn3\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").style.getPropertyValue(\"color\")", "");
+
+       e_web_view_jsc_set_element_style_property (fixture->web_view, "frm2", "btn1", "color", "green", NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn1\").style.getPropertyValue(\"color\")", "blue");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn3\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").style.getPropertyValue(\"color\")", "green");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").style.getPropertyValue(\"color\")", "");
+
+       e_web_view_jsc_set_element_style_property (fixture->web_view, "frm2", "btn1", "color", NULL, NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn1\").style.getPropertyValue(\"color\")", "blue");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", 
\"btn3\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").style.getPropertyValue(\"color\")", "");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").style.getPropertyValue(\"color\")", "");
+}
+
+static void
+test_set_element_attribute (TestFixture *fixture)
 {
-       test_utils_load_string (fixture, "<html><body>Pre<br><iframe id=\"first\" 
src=\"empty:///\"></iframe><br>Pos</body></html>");
-       test_utils_load_iframe_content (fixture, "first", "<html><body>second<iframe id=\"second\" 
src=\"empty:///\"></iframe></body></html>");
+       test_utils_load_body (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn1\").getAttributeNS(\"\", 
\"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn3\").getAttributeNS(\"\", 
\"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").getAttributeNS(\"\", \"myattr\")", NULL);
+
+       e_web_view_jsc_set_element_attribute (fixture->web_view, "", "btn1", NULL, "myattr", "val1", NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn1\").getAttributeNS(\"\", 
\"myattr\")", "val1");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn3\").getAttributeNS(\"\", 
\"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").getAttributeNS(\"\", \"myattr\")", NULL);
+
+       e_web_view_jsc_set_element_attribute (fixture->web_view, "frm2", "btn1", NULL, "myattr", "val2", 
NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn1\").getAttributeNS(\"\", 
\"myattr\")", "val1");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn3\").getAttributeNS(\"\", 
\"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", "val2");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").getAttributeNS(\"\", \"myattr\")", NULL);
+
+       e_web_view_jsc_set_element_attribute (fixture->web_view, "frm2", "btn1", NULL, "myattr", NULL, NULL);
+       test_utils_wait_noop (fixture);
+
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn1\").getAttributeNS(\"\", 
\"myattr\")", "val1");
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"\", \"btn3\").getAttributeNS(\"\", 
\"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm1_1\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn1\").getAttributeNS(\"\", \"myattr\")", NULL);
+       test_utils_jsc_call_string_and_verify (fixture, "Evo.findElement(\"frm2\", 
\"btn2\").getAttributeNS(\"\", \"myattr\")", NULL);
 
        test_utils_wait (fixture);
 }
@@ -423,7 +669,9 @@ main (gint argc,
        e_util_init_main_thread (NULL);
        e_passwords_init ();
 
-       test_utils_add_test ("/basic", test_basic);
+       test_utils_add_test ("/EWebView/SetElementHidden", test_set_element_hidden);
+       test_utils_add_test ("/EWebView/SetElementStyleProperty", test_set_element_style_property);
+       test_utils_add_test ("/EWebView/SetElementAttribute", test_set_element_attribute);
 
        res = g_test_run ();
 
diff --git a/src/web-extensions/CMakeLists.txt b/src/web-extensions/CMakeLists.txt
index 82ba059de0..ae6425e77a 100644
--- a/src/web-extensions/CMakeLists.txt
+++ b/src/web-extensions/CMakeLists.txt
@@ -1,3 +1,9 @@
+set(GRESOURCE_FILES
+       ext-utils.js
+)
+
+glib_compile_resources(${CMAKE_CURRENT_SOURCE_DIR} evolution-web-extension-resource 
evolution_web_extension_resource evolution-web-process-extension.gresource.xml ${GRESOURCE_FILES})
+
 set(DEPENDENCIES
        evolution-util
 )
@@ -53,6 +59,8 @@ set(SOURCES
        e-web-extension.c
        e-web-extension-main.c
        e-web-extension-names.h
+       ${CMAKE_CURRENT_BINARY_DIR}/evolution-web-extension-resource.c
+       ${CMAKE_CURRENT_BINARY_DIR}/evolution-web-extension-resource.h
 )
 
 add_library(ewebextension MODULE
diff --git a/src/web-extensions/e-web-extension.c b/src/web-extensions/e-web-extension.c
index 9d85388a13..c091bf03b2 100644
--- a/src/web-extensions/e-web-extension.c
+++ b/src/web-extensions/e-web-extension.c
@@ -2181,10 +2181,43 @@ web_page_created_cb (WebKitWebExtension *wk_extension,
                extension, 0);
 }
 
+static void
+window_object_cleared_cb (WebKitScriptWorld *world,
+                         WebKitWebPage *page,
+                         WebKitFrame *frame,
+                         gpointer user_data)
+{
+       JSCContext *jsc_context;
+       JSCValue *result;
+       GBytes *bytes;
+       gconstpointer data;
+       gsize data_size = 0;
+       GError *error = NULL;
+
+       bytes = g_resources_lookup_data ("/org/gnome/evolution-web-process-extension/js/ext-utils.js", 
G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
+       if (!bytes) {
+               g_warning ("Failed to load ext-utils.js: %s", error ? error->message : "Unknown error");
+               g_clear_error (&error);
+               return;
+       }
+
+       jsc_context = webkit_frame_get_js_context (frame);
+       data = g_bytes_get_data (bytes, &data_size);
+
+       /* Preload utility functions */
+       result = jsc_context_evaluate_with_source_uri (jsc_context, data, data_size, 
"resource:///org/gnome/evolution-web-process-extension/js/ext-utils.js", 1);
+
+       g_clear_pointer (&bytes, g_bytes_unref);
+       g_clear_object (&result);
+       g_clear_object (&jsc_context);
+}
+
 void
 e_web_extension_initialize (EWebExtension *extension,
                             WebKitWebExtension *wk_extension)
 {
+       WebKitScriptWorld *script_world;
+
        g_return_if_fail (E_IS_WEB_EXTENSION (extension));
 
        if (extension->priv->initialized)
@@ -2197,6 +2230,11 @@ e_web_extension_initialize (EWebExtension *extension,
        g_signal_connect (
                wk_extension, "page-created",
                G_CALLBACK (web_page_created_cb), extension);
+
+       script_world = webkit_script_world_get_default ();
+
+       g_signal_connect (script_world, "window-object-cleared",
+               G_CALLBACK (window_object_cleared_cb), NULL);
 }
 
 void
diff --git a/src/web-extensions/ext-utils.js b/src/web-extensions/ext-utils.js
index dc17545f81..7151f31297 100644
--- a/src/web-extensions/ext-utils.js
+++ b/src/web-extensions/ext-utils.js
@@ -49,28 +49,48 @@ Evo.findElement = function(iframe_id, element_id)
 
 Evo.SetElementHidden = function(iframe_id, element_id, value)
 {
-       var elem;
-
-       elem = Evo.findElement(iframe_id, element_id);
+       var elem = Evo.findElement(iframe_id, element_id);
 
        if (elem)
                elem.hidden = value;
 }
 
+Evo.SetElementStyleProperty = function(iframe_id, element_id, property_name, value)
+{
+       var elem = Evo.findElement(iframe_id, element_id);
+
+       if (elem) {
+               if (value != "")
+                       elem.style.setProperty(property_name, value);
+               else
+                       elem.style.removeProperty(property_name);
+       }
+}
+
+Evo.SetElementAttribute = function(iframe_id, element_id, namespace_uri, qualified_name, value)
+{
+       var elem = Evo.findElement(iframe_id, element_id);
+
+       if (elem) {
+               if (value != "")
+                       elem.setAttributeNS(namespace_uri, qualified_name, value);
+               else
+                       elem.removeAttributeNS(namespace_uri, qualified_name);
+       }
+}
+
 Evo.SetIFrameSrc = function(iframe_id, src_uri)
 {
-       var iframe;
+       var iframe = Evo.findIFrame(iframe_id);
 
-       iframe = Evo.findIFrame(iframe_id);
        if (iframe)
                iframe.src = src_uri;
 }
 
 Evo.SetIFrameContent = function(iframe_id, content)
 {
-       var iframe;
+       var iframe = Evo.findIFrame(iframe_id);
 
-       iframe = Evo.findIFrame(iframe_id);
        if (iframe)
                iframe.contentDocument.documentElement.innerHTML = content;
 }


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