[GTK] Add webkit_web_view_run_javascript() to WebKit2 GTK+
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Mar 2012 08:44:23 +0000 (08:44 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 21 Mar 2012 08:44:23 +0000 (08:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=75543

Reviewed by Martin Robinson.

Source/WebKit2:

* GNUmakefile.am: Add new files to compilation.
* UIProcess/API/gtk/WebKitError.cpp:
(webkit_javascript_error_quark): Add new error domain for
Javascript errors.
* UIProcess/API/gtk/WebKitError.h:
* UIProcess/API/gtk/WebKitJavascriptResult.cpp: Added.
(webkitJavascriptResultCreate): Create a WebKitJavascriptResult
for the given WKSerializedScriptValueRef.
(webkit_javascript_result_ref): Increment reference count of
WebKitJavascriptResult.
(webkit_javascript_result_unref): Decrement reference count of
WebKitJavascriptResult.
(webkit_javascript_result_get_global_context): Get global
javascript context of the result.
(webkit_javascript_result_get_value): Get the JSValueRef of the
result.
* UIProcess/API/gtk/WebKitJavascriptResult.h: Added.
* UIProcess/API/gtk/WebKitJavascriptResultPrivate.h: Added.
* UIProcess/API/gtk/WebKitPrivate.h:
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewFinalize): Release the global javascript context.
(webkit_web_view_get_javascript_global_context): Get or create the
global javascript context.
(webkitWebViewRunJavaScriptCallback): Callback called by C API when
javascript execution finishes.
(webkit_web_view_run_javascript): Asynchronously run a given
javascript.
(webkit_web_view_run_javascript_finish): Finish async operation
started by webkit_web_view_run_javascript().
* UIProcess/API/gtk/WebKitWebView.h:
* UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
* UIProcess/API/gtk/docs/webkit2gtk.types: Add
webkit_javascript_result_get_type().
* UIProcess/API/gtk/tests/TestWebKitWebView.cpp:
(testWebViewRunJavaScript):
(beforeAll):
* UIProcess/API/gtk/tests/WebViewTest.cpp:
(WebViewTest::WebViewTest):
(WebViewTest::~WebViewTest):
(runJavaScriptReadyCallback):
(WebViewTest::runJavaScriptAndWaitUntilFinished):
(jsValueToCString):
(WebViewTest::javascriptResultToCString):
(WebViewTest::javascriptResultToNumber):
(WebViewTest::javascriptResultToBoolean):
(WebViewTest::javascriptResultIsNull):
(WebViewTest::javascriptResultIsUndefined):
* UIProcess/API/gtk/tests/WebViewTest.h:
* UIProcess/API/gtk/webkit2.h:

Tools:

* MiniBrowser/gtk/GNUmakefile.am: Add javascriptcore_cppflags to
MiniBrowser CPP flags.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111510 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/GNUmakefile.am
Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitError.h
Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h [new file with mode: 0644]
Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp
Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
Source/WebKit2/UIProcess/API/gtk/webkit2.h
Tools/ChangeLog
Tools/MiniBrowser/gtk/GNUmakefile.am

index a43f6faa79986bbfed9eb9c8412d8ac147a050d1..1f0815ab81152eacb1b465daebbe8e568a27db2e 100644 (file)
@@ -1,3 +1,60 @@
+2012-03-21  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Add webkit_web_view_run_javascript() to WebKit2 GTK+
+        https://bugs.webkit.org/show_bug.cgi?id=75543
+
+        Reviewed by Martin Robinson.
+
+        * GNUmakefile.am: Add new files to compilation.
+        * UIProcess/API/gtk/WebKitError.cpp:
+        (webkit_javascript_error_quark): Add new error domain for
+        Javascript errors.
+        * UIProcess/API/gtk/WebKitError.h:
+        * UIProcess/API/gtk/WebKitJavascriptResult.cpp: Added.
+        (webkitJavascriptResultCreate): Create a WebKitJavascriptResult
+        for the given WKSerializedScriptValueRef.
+        (webkit_javascript_result_ref): Increment reference count of
+        WebKitJavascriptResult.
+        (webkit_javascript_result_unref): Decrement reference count of
+        WebKitJavascriptResult.
+        (webkit_javascript_result_get_global_context): Get global
+        javascript context of the result.
+        (webkit_javascript_result_get_value): Get the JSValueRef of the
+        result.
+        * UIProcess/API/gtk/WebKitJavascriptResult.h: Added.
+        * UIProcess/API/gtk/WebKitJavascriptResultPrivate.h: Added.
+        * UIProcess/API/gtk/WebKitPrivate.h:
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkitWebViewFinalize): Release the global javascript context.
+        (webkit_web_view_get_javascript_global_context): Get or create the
+        global javascript context.
+        (webkitWebViewRunJavaScriptCallback): Callback called by C API when
+        javascript execution finishes.
+        (webkit_web_view_run_javascript): Asynchronously run a given
+        javascript.
+        (webkit_web_view_run_javascript_finish): Finish async operation
+        started by webkit_web_view_run_javascript().
+        * UIProcess/API/gtk/WebKitWebView.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
+        * UIProcess/API/gtk/docs/webkit2gtk.types: Add
+        webkit_javascript_result_get_type().
+        * UIProcess/API/gtk/tests/TestWebKitWebView.cpp:
+        (testWebViewRunJavaScript):
+        (beforeAll):
+        * UIProcess/API/gtk/tests/WebViewTest.cpp:
+        (WebViewTest::WebViewTest):
+        (WebViewTest::~WebViewTest):
+        (runJavaScriptReadyCallback):
+        (WebViewTest::runJavaScriptAndWaitUntilFinished):
+        (jsValueToCString):
+        (WebViewTest::javascriptResultToCString):
+        (WebViewTest::javascriptResultToNumber):
+        (WebViewTest::javascriptResultToBoolean):
+        (WebViewTest::javascriptResultIsNull):
+        (WebViewTest::javascriptResultIsUndefined):
+        * UIProcess/API/gtk/tests/WebViewTest.h:
+        * UIProcess/API/gtk/webkit2.h:
+
 2012-03-20  Eric Seidel  <eric@webkit.org>
 
         Move wtf/Platform.h from JavaScriptCore to Source/WTF/wtf
index 6a10f98c7286010b3005bca72c6f56031e6af0eb..6d517743437789fb07ef072e099eb762527c0a7b 100644 (file)
@@ -92,6 +92,7 @@ libwebkit2gtkinclude_HEADERS = \
        $(WebKit2)/UIProcess/API/gtk/WebKitError.h \
        $(WebKit2)/UIProcess/API/gtk/WebKitFindController.h \
        $(WebKit2)/UIProcess/API/gtk/WebKitHitTestResult.h \
+       $(WebKit2)/UIProcess/API/gtk/WebKitJavascriptResult.h \
        $(WebKit2)/UIProcess/API/gtk/WebKitNavigationPolicyDecision.h \
        $(WebKit2)/UIProcess/API/gtk/WebKitPolicyDecision.h \
        $(WebKit2)/UIProcess/API/gtk/WebKitPrintOperation.h \
@@ -555,6 +556,9 @@ webkit2_sources += \
        Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.cpp \
        Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.h \
        Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResultPrivate.h \
+       Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp \
+       Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h \
+       Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h \
        Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.h \
        Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp \
        Source/WebKit2/UIProcess/API/gtk/WebKitFindController.h \
index 30ae684e56b090fe4fe65277a4711f7f2ab0a006..daf09ecc2a1aaf5c97953ec9554edbb08c258444 100644 (file)
@@ -77,3 +77,8 @@ GQuark webkit_print_error_quark()
 COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_GENERAL, PrintErrorGeneral);
 COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_PRINTER_NOT_FOUND, PrintErrorPrinterNotFound);
 COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE, PrintErrorInvalidPageRange);
+
+GQuark webkit_javascript_error_quark()
+{
+    return g_quark_from_static_string("WebKitJavascriptError");
+}
index 073c41de762ca9d54dc3134a67891779be420957..c20581683d47890804853a4871460141cac4a0fc 100644 (file)
 
 G_BEGIN_DECLS
 
-#define WEBKIT_NETWORK_ERROR  webkit_network_error_quark ()
-#define WEBKIT_POLICY_ERROR   webkit_policy_error_quark ()
-#define WEBKIT_PLUGIN_ERROR   webkit_plugin_error_quark ()
-#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark ()
-#define WEBKIT_PRINT_ERROR    webkit_print_error_quark ()
+#define WEBKIT_NETWORK_ERROR    webkit_network_error_quark ()
+#define WEBKIT_POLICY_ERROR     webkit_policy_error_quark ()
+#define WEBKIT_PLUGIN_ERROR     webkit_plugin_error_quark ()
+#define WEBKIT_DOWNLOAD_ERROR   webkit_download_error_quark ()
+#define WEBKIT_PRINT_ERROR      webkit_print_error_quark ()
+#define WEBKIT_JAVASCRIPT_ERROR webkit_print_error_quark ()
 
 /**
  * WebKitNetworkError:
@@ -119,20 +120,33 @@ typedef enum {
     WEBKIT_PRINT_ERROR_INVALID_PAGE_RANGE = 501
 } WebKitPrintError;
 
+/**
+ * WebKitJavascriptError:
+ * @WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED: An exception was raised in Javascript execution
+ *
+ * Enum values used to denote errors happending when executing Javascript
+ */
+typedef enum {
+    WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED = 699
+} WebKitJavascriptError;
+
+WEBKIT_API GQuark
+webkit_network_error_quark    (void);
+
 WEBKIT_API GQuark
-webkit_network_error_quark  (void);
+webkit_policy_error_quark     (void);
 
 WEBKIT_API GQuark
-webkit_policy_error_quark   (void);
+webkit_plugin_error_quark     (void);
 
 WEBKIT_API GQuark
-webkit_plugin_error_quark   (void);
+webkit_download_error_quark   (void);
 
 WEBKIT_API GQuark
-webkit_download_error_quark (void);
+webkit_print_error_quark      (void);
 
 WEBKIT_API GQuark
-webkit_print_error_quark    (void);
+webkit_javascript_error_quark (void);
 
 G_END_DECLS
 
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.cpp
new file mode 100644 (file)
index 0000000..84ad04d
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "WebKitJavascriptResult.h"
+
+#include "WebKitJavascriptResultPrivate.h"
+#include <wtf/gobject/GRefPtr.h>
+
+struct _WebKitJavascriptResult {
+    _WebKitJavascriptResult(WebKitWebView* view, WKSerializedScriptValueRef wkSerializedScriptValue)
+        : webView(view)
+        , referenceCount(1)
+        {
+            value = WKSerializedScriptValueDeserialize(wkSerializedScriptValue, webkit_web_view_get_javascript_global_context(view), 0);
+        }
+
+    GRefPtr<WebKitWebView> webView;
+    JSValueRef value;
+
+    int referenceCount;
+};
+
+G_DEFINE_BOXED_TYPE(WebKitJavascriptResult, webkit_javascript_result, webkit_javascript_result_ref, webkit_javascript_result_unref)
+
+WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView* webView, WKSerializedScriptValueRef wkSerializedScriptValue)
+{
+    WebKitJavascriptResult* result = g_slice_new(WebKitJavascriptResult);
+    new (result) WebKitJavascriptResult(webView, wkSerializedScriptValue);
+    return result;
+}
+
+/**
+ * webkit_javascript_result_ref:
+ * @js_result: a #WebKitJavascriptResult
+ *
+ * Atomically increments the reference count of @js_result by one. This
+ * function is MT-safe and may be called from any thread.
+ *
+ * Returns: The passed in #WebKitJavascriptResult
+ */
+WebKitJavascriptResult* webkit_javascript_result_ref(WebKitJavascriptResult* javascriptResult)
+{
+    g_atomic_int_inc(&javascriptResult->referenceCount);
+    return javascriptResult;
+}
+
+/**
+ * webkit_javascript_result_unref:
+ * @js_result: a #WebKitJavascriptResult
+ *
+ * Atomically decrements the reference count of @js_result by one. If the
+ * reference count drops to 0, all memory allocated by the #WebKitJavascriptResult is
+ * released. This function is MT-safe and may be called from any
+ * thread.
+ */
+void webkit_javascript_result_unref(WebKitJavascriptResult* javascriptResult)
+{
+    if (g_atomic_int_dec_and_test(&javascriptResult->referenceCount)) {
+        javascriptResult->~WebKitJavascriptResult();
+        g_slice_free(WebKitJavascriptResult, javascriptResult);
+    }
+}
+
+/**
+ * webkit_javascript_result_get_global_context:
+ * @js_result: a #WebKitJavascriptResult
+ *
+ * Get the global Javascript context that should be used with the
+ * <function>JSValueRef</function> returned by webkit_javascript_result_get_value().
+ *
+ * Returns: the <function>JSGlobalContextRef</function> for the #WebKitJavascriptResult
+ */
+JSGlobalContextRef webkit_javascript_result_get_global_context(WebKitJavascriptResult* javascriptResult)
+{
+    return webkit_web_view_get_javascript_global_context(javascriptResult->webView.get());
+}
+
+/**
+ * webkit_javascript_result_get_value:
+ * @js_result: a #WebKitJavascriptResult
+ *
+ * Get the value of @js_result. You should use the <function>JSGlobalContextRef</function>
+ * returned by webkit_javascript_result_get_global_context() to use the <function>JSValueRef</function>.
+ *
+ * Returns: the <function>JSValueRef</function> of the #WebKitJavascriptResult
+ */
+JSValueRef webkit_javascript_result_get_value(WebKitJavascriptResult* javascriptResult)
+{
+    return javascriptResult->value;
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResult.h
new file mode 100644 (file)
index 0000000..5a9f738
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
+#error "Only <webkit2/webkit2.h> can be included directly."
+#endif
+
+#ifndef WebKitJavascriptResult_h
+#define WebKitJavascriptResult_h
+
+#include <JavaScriptCore/JSBase.h>
+#include <glib-object.h>
+#include <webkit2/WebKitDefines.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_JAVASCRIPT_RESULT (webkit_javascript_result_get_type())
+
+typedef struct _WebKitJavascriptResult WebKitJavascriptResult;
+
+
+WEBKIT_API GType
+webkit_javascript_result_get_type           (void);
+
+WEBKIT_API WebKitJavascriptResult *
+webkit_javascript_result_ref                (WebKitJavascriptResult *js_result);
+
+WEBKIT_API void
+webkit_javascript_result_unref              (WebKitJavascriptResult *js_result);
+
+WEBKIT_API JSGlobalContextRef
+webkit_javascript_result_get_global_context (WebKitJavascriptResult *js_result);
+
+WEBKIT_API JSValueRef
+webkit_javascript_result_get_value          (WebKitJavascriptResult *js_result);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitJavascriptResultPrivate.h
new file mode 100644 (file)
index 0000000..840ead0
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WebKitJavascriptResultPrivate_h
+#define WebKitJavascriptResultPrivate_h
+
+#include "WebKitJavascriptResult.h"
+#include "WebKitPrivate.h"
+#include "WebKitWebView.h"
+
+WebKitJavascriptResult* webkitJavascriptResultCreate(WebKitWebView*, WKSerializedScriptValueRef);
+
+#endif // WebKitJavascriptResultPrivate_h
index e785c3638350d84a808c0fad50ee82bb06164676..f63480a18c30cf12178db893cb8dded21779e170 100644 (file)
@@ -30,6 +30,7 @@
 #include <WebKit2/WKDownload.h>
 #include <WebKit2/WKFindOptions.h>
 #include <WebKit2/WKRetainPtr.h>
+#include <WebKit2/WKSerializedScriptValue.h>
 #include <WebKit2/WKString.h>
 #include <WebKit2/WebKit2.h>
 #include <glib.h>
index 4f17d466903676394c466b5227c5fe81d04e8789..30bc1ee641892620a85e7862637ac976b4a978cd 100644 (file)
@@ -25,6 +25,7 @@
 #include "WebKitEnumTypes.h"
 #include "WebKitError.h"
 #include "WebKitHitTestResultPrivate.h"
+#include "WebKitJavascriptResultPrivate.h"
 #include "WebKitLoaderClient.h"
 #include "WebKitMarshal.h"
 #include "WebKitPolicyClient.h"
@@ -38,6 +39,7 @@
 #include "WebKitWebViewPrivate.h"
 #include "WebKitWindowPropertiesPrivate.h"
 #include "WebPageProxy.h"
+#include <JavaScriptCore/APICast.h>
 #include <WebCore/DragIcon.h>
 #include <WebCore/GtkUtilities.h>
 #include <glib/gi18n-lib.h>
@@ -100,6 +102,7 @@ struct _WebKitWebViewPrivate {
     unsigned mouseTargetModifiers;
 
     GRefPtr<WebKitFindController> findController;
+    JSGlobalContextRef javascriptGlobalContext;
 };
 
 static guint signals[LAST_SIGNAL] = { 0, };
@@ -255,7 +258,10 @@ static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* valu
 
 static void webkitWebViewFinalize(GObject* object)
 {
-    WEBKIT_WEB_VIEW(object)->priv->~WebKitWebViewPrivate();
+    WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv;
+    if (priv->javascriptGlobalContext)
+        JSGlobalContextRelease(priv->javascriptGlobalContext);
+    priv->~WebKitWebViewPrivate();
     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
 }
 
@@ -1466,3 +1472,140 @@ WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView
 
     return webView->priv->findController.get();
 }
+
+/**
+ * webkit_web_view_get_javascript_global_context:
+ * @web_view: a #WebKitWebView
+ *
+ * Get the global JavaScript context used by @web_view to deserialize the
+ * result values of scripts executed with webkit_web_view_run_javascript().
+ *
+ * Returns: the <function>JSGlobalContextRef</function> used by @web_view to deserialize
+ *    the result values of scripts.
+ */
+JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+
+    if (!webView->priv->javascriptGlobalContext)
+        webView->priv->javascriptGlobalContext = JSGlobalContextCreate(0);
+    return webView->priv->javascriptGlobalContext;
+}
+
+static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context)
+{
+    GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
+    if (wkSerializedScriptValue) {
+        GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get()))));
+        WebKitJavascriptResult* scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue);
+        g_simple_async_result_set_op_res_gpointer(result.get(), scriptResult, reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref));
+    } else {
+        GError* error = 0;
+        g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript"));
+        g_simple_async_result_take_error(result.get(), error);
+    }
+    g_simple_async_result_complete(result.get());
+}
+
+/**
+ * webkit_web_view_run_javascript:
+ * @web_view: a #WebKitWebView
+ * @script: the script to run
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Asynchronously run @script in the context of the current page in @web_view.
+ *
+ * When the operation is finished, @callback will be called. You can then call
+ * webkit_web_view_run_javascript_finish() to get the result of the operation.
+ */
+void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GAsyncReadyCallback callback, gpointer userData)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
+    g_return_if_fail(script);
+
+    WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
+    WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script));
+    GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
+                                                           reinterpret_cast<gpointer>(webkit_web_view_run_javascript));
+    WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback);
+}
+
+/**
+ * webkit_web_view_run_javascript_finish:
+ * @web_view: a #WebKitWebView
+ * @result: a #GAsyncResult
+ * @error: return location for error or %NULL to ignore
+ *
+ * Finish an asynchronous operation started with webkit_web_view_run_javascript().
+ *
+ * This is an example of using webkit_web_view_run_javascript() with a script returning
+ * a string:
+ *
+ * <informalexample><programlisting>
+ * static void
+ * web_view_javascript_finished (GObject      *object,
+ *                               GAsyncResult *result,
+ *                               gpointer      user_data)
+ * {
+ *     WebKitJavascriptResult *js_result;
+ *     JSValueRef              value;
+ *     JSGlobalContextRef      context;
+ *     GError                 *error = NULL;
+ *
+ *     js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
+ *     if (!js_result) {
+ *         g_warning ("Error running javascript: %s", error->message);
+ *         g_error_free (error);
+ *         return;
+ *     }
+ *
+ *     context = webkit_javascript_result_get_global_context (js_result);
+ *     value = webkit_javascript_result_get_value (js_result);
+ *     if (JSValueIsString (context, value)) {
+ *         JSStringRef *js_str_value;
+ *         gchar       *str_value;
+ *         gsize        str_length;
+ *
+ *         js_str_value = JSValueToStringCopy (context, value, NULL));
+ *         str_length = JSStringGetMaximumUTF8CStringSize (js_str_value);
+ *         str_value = (gchar *)g_malloc (str_length));
+ *         JSStringGetUTF8CString (js_str_value, str_value, str_length);
+ *         JSStringRelease (js_str_value);
+ *         g_print ("Script result: %s\n", str_value);
+ *         g_free (str_value);
+ *     } else {
+ *         g_warning ("Error running javascript: unexpected return value");
+ *     }
+ *     webkit_javascript_result_unref (js_result);
+ * }
+ *
+ * static void
+ * web_view_get_link_url (WebKitWebView *web_view,
+ *                        const gchar   *link_id)
+ * {
+ *     gchar *script;
+ *
+ *     script = g_strdup_printf ("window.document.getElementById('%s').href;", link_id);
+ *     webkit_web_view_run_javascript (web_view, script, web_view_javascript_finished, NULL);
+ *     g_free (script);
+ * }
+ * </programlisting></informalexample>
+ *
+ * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script
+ *    or %NULL in case of error
+ */
+WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+    g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0);
+
+    GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result);
+    g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript);
+
+    if (g_simple_async_result_propagate_error(simpleResult, error))
+        return 0;
+
+    WebKitJavascriptResult* scriptResult = static_cast<WebKitJavascriptResult*>(g_simple_async_result_get_op_res_gpointer(simpleResult));
+    return scriptResult ? webkit_javascript_result_ref(scriptResult) : 0;
+}
index fb4c48a2dd39b1b49aa6f402479a2f6cfca77230..6a55e0b9c4982981a87e261e6850fa3766812e2c 100644 (file)
 #ifndef WebKitWebView_h
 #define WebKitWebView_h
 
+#include <JavaScriptCore/JSBase.h>
 #include <webkit2/WebKitBackForwardList.h>
 #include <webkit2/WebKitDefines.h>
 #include <webkit2/WebKitFindController.h>
 #include <webkit2/WebKitHitTestResult.h>
+#include <webkit2/WebKitJavascriptResult.h>
 #include <webkit2/WebKitScriptDialog.h>
 #include <webkit2/WebKitSettings.h>
 #include <webkit2/WebKitURIRequest.h>
@@ -267,6 +269,18 @@ webkit_web_view_execute_editing_command            (WebKitWebView             *w
 WEBKIT_API WebKitFindController *
 webkit_web_view_get_find_controller                (WebKitWebView             *web_view);
 
+WEBKIT_API JSGlobalContextRef
+webkit_web_view_get_javascript_global_context      (WebKitWebView             *web_view);
+
+WEBKIT_API void
+webkit_web_view_run_javascript                     (WebKitWebView             *web_view,
+                                                    const gchar               *script,
+                                                    GAsyncReadyCallback        callback,
+                                                    gpointer                   user_data);
+WEBKIT_API WebKitJavascriptResult *
+webkit_web_view_run_javascript_finish              (WebKitWebView             *web_view,
+                                                    GAsyncResult              *result,
+                                                    GError                   **error);
 G_END_DECLS
 
 #endif
index d33f8ae0fb895e326ec7f6cae716235d0eeb9754..0e6149316089a910aa4707bab5832cfd39151bcb 100644 (file)
@@ -49,8 +49,6 @@ webkit_web_context_get_type
 WebKitWebView
 WebKitLoadEvent
 WebKitPolicyDecisionType
-WebKitScriptDialog
-WebKitScriptDialogType
 
 <SUBSECTION Editing Commands>
 WEBKIT_EDITING_COMMAND_CUT
@@ -89,6 +87,20 @@ webkit_web_view_can_execute_editing_command
 webkit_web_view_can_execute_editing_command_finish
 webkit_web_view_execute_editing_command
 webkit_web_view_get_find_controller
+webkit_web_view_get_javascript_global_context
+webkit_web_view_run_javascript
+webkit_web_view_run_javascript_finish
+
+<SUBSECTION WebKitJavascriptResult>
+WebKitJavascriptResult
+webkit_javascript_result_ref
+webkit_javascript_result_unref
+webkit_javascript_result_get_global_context
+webkit_javascript_result_get_value
+
+<SUBSECTION WebKitScriptDialog>
+WebKitScriptDialog
+WebKitScriptDialogType
 webkit_script_dialog_get_dialog_type
 webkit_script_dialog_get_message
 webkit_script_dialog_confirm_set_confirmed
@@ -103,10 +115,12 @@ WEBKIT_TYPE_WEB_VIEW
 WEBKIT_WEB_VIEW_CLASS
 WEBKIT_IS_WEB_VIEW_CLASS
 WEBKIT_WEB_VIEW_GET_CLASS
+WEBKIT_TYPE_JAVASCRIPT_RESULT
 WEBKIT_TYPE_SCRIPT_DIALOG
 
 <SUBSECTION Private>
 webkit_web_view_get_type
+webkit_javascript_result_get_type
 webkit_script_dialog_get_type
 WebKitWebViewPrivate
 </SECTION>
@@ -466,16 +480,19 @@ WEBKIT_PLUGIN_ERROR
 WEBKIT_POLICY_ERROR
 WEBKIT_DOWNLOAD_ERROR
 WEBKIT_PRINT_ERROR
+WEBKIT_JAVASCRIPT_ERROR
 WebKitNetworkError
 WebKitPluginError
 WebKitPolicyError
 WebKitDownloadError
 WebKitPrintError
+WebKitJavascriptError
 webkit_network_error_quark
 webkit_plugin_error_quark
 webkit_policy_error_quark
 webkit_download_error_quark
 webkit_print_error_quark
+webkit_javascript_error_quark
 </SECTION>
 
 <SECTION>
index 8e8d7b13a0e94af5e02556c12c87dcfacec501dd..ef34b49234f11acaace3f6cd416d59404e559244 100644 (file)
@@ -11,3 +11,4 @@ webkit_window_properties_get_type
 webkit_download_get_type
 webkit_find_controller_get_type
 webkit_script_dialog_get_type
+webkit_javascript_result_get_type
index bfeda169f3c8a3ebdf09cea5c5a81fe134dc8c4d..787796c534beabcf5614ecd61c773c393aedb2d4 100644 (file)
@@ -452,6 +452,66 @@ static void testWebViewZoomLevel(WebViewTest* test, gconstpointer)
     g_assert_cmpfloat(webkit_web_view_get_zoom_level(test->m_webView), ==, 2.5);
 }
 
+static void testWebViewRunJavaScript(WebViewTest* test, gconstpointer)
+{
+    static const char* html = "<html><body><a id='WebKitLink' href='http://www.webkitgtk.org/' title='WebKitGTK+ Title'>WebKitGTK+ Website</a></body></html>";
+    test->loadHtml(html, 0);
+    test->waitUntilLoadFinished();
+
+    GOwnPtr<GError> error;
+    WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').title;", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    GOwnPtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+    g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Title");
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').href;", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    valueString.set(WebViewTest::javascriptResultToCString(javascriptResult));
+    g_assert_cmpstr(valueString.get(), ==, "http://www.webkitgtk.org/");
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementById('WebKitLink').textContent", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    valueString.set(WebViewTest::javascriptResultToCString(javascriptResult));
+    g_assert_cmpstr(valueString.get(), ==, "WebKitGTK+ Website");
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 25;", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 25);
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = 2.5;", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 2.5);
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = true", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert(WebViewTest::javascriptResultToBoolean(javascriptResult));
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = false", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert(!WebViewTest::javascriptResultToBoolean(javascriptResult));
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("a = null", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert(WebViewTest::javascriptResultIsNull(javascriptResult));
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("function Foo() { a = 25; } Foo();", &error.outPtr());
+    g_assert(javascriptResult);
+    g_assert(!error.get());
+    g_assert(WebViewTest::javascriptResultIsUndefined(javascriptResult));
+
+    javascriptResult = test->runJavaScriptAndWaitUntilFinished("foo();", &error.outPtr());
+    g_assert(!javascriptResult);
+    g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED);
+}
+
 void beforeAll()
 {
     WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext);
@@ -463,6 +523,7 @@ void beforeAll()
     UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties);
     UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget);
     WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel);
+    WebViewTest::add("WebKitWebView", "run-javascript", testWebViewRunJavaScript);
 }
 
 void afterAll()
index 60bf7fbc5399684183312ababbbd805294d1db33..09f97f6456e16632efc73db8c170d992e007d77f 100644 (file)
 #include "config.h"
 #include "WebViewTest.h"
 
+#include <JavaScriptCore/JSRetainPtr.h>
 #include <WebCore/GOwnPtrGtk.h>
 
 WebViewTest::WebViewTest()
     : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new())))
     , m_mainLoop(g_main_loop_new(0, TRUE))
     , m_parentWindow(0)
+    , m_javascriptResult(0)
 {
     assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
 }
@@ -35,6 +37,8 @@ WebViewTest::~WebViewTest()
 {
     if (m_parentWindow)
         gtk_widget_destroy(m_parentWindow);
+    if (m_javascriptResult)
+        webkit_javascript_result_unref(m_javascriptResult);
     g_object_unref(m_webView);
     g_main_loop_unref(m_mainLoop);
 }
@@ -194,3 +198,84 @@ void WebViewTest::mouseMoveTo(int x, int y, unsigned int mouseModifiers)
     gtk_main_do_event(event.get());
 }
 
+static void runJavaScriptReadyCallback(GObject*, GAsyncResult* result, WebViewTest* test)
+{
+    test->m_javascriptResult = webkit_web_view_run_javascript_finish(test->m_webView, result, test->m_javascriptError);
+    g_main_loop_quit(test->m_mainLoop);
+}
+
+WebKitJavascriptResult* WebViewTest::runJavaScriptAndWaitUntilFinished(const char* javascript, GError** error)
+{
+    if (m_javascriptResult)
+        webkit_javascript_result_unref(m_javascriptResult);
+    m_javascriptResult = 0;
+    m_javascriptError = error;
+    webkit_web_view_run_javascript(m_webView, javascript, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptReadyCallback), this);
+    g_main_loop_run(m_mainLoop);
+
+    return m_javascriptResult;
+}
+
+static char* jsValueToCString(JSGlobalContextRef context, JSValueRef value)
+{
+    g_assert(value);
+    g_assert(JSValueIsString(context, value));
+
+    JSRetainPtr<JSStringRef> stringValue(Adopt, JSValueToStringCopy(context, value, 0));
+    g_assert(stringValue);
+
+    size_t cStringLength = JSStringGetMaximumUTF8CStringSize(stringValue.get());
+    char* cString = static_cast<char*>(g_malloc(cStringLength));
+    JSStringGetUTF8CString(stringValue.get(), cString, cStringLength);
+    return cString;
+}
+
+char* WebViewTest::javascriptResultToCString(WebKitJavascriptResult* javascriptResult)
+{
+    JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult);
+    g_assert(context);
+    return jsValueToCString(context, webkit_javascript_result_get_value(javascriptResult));
+}
+
+double WebViewTest::javascriptResultToNumber(WebKitJavascriptResult* javascriptResult)
+{
+    JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult);
+    g_assert(context);
+    JSValueRef value = webkit_javascript_result_get_value(javascriptResult);
+    g_assert(value);
+    g_assert(JSValueIsNumber(context, value));
+
+    return JSValueToNumber(context, value, 0);
+}
+
+bool WebViewTest::javascriptResultToBoolean(WebKitJavascriptResult* javascriptResult)
+{
+    JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult);
+    g_assert(context);
+    JSValueRef value = webkit_javascript_result_get_value(javascriptResult);
+    g_assert(value);
+    g_assert(JSValueIsBoolean(context, value));
+
+    return JSValueToBoolean(context, value);
+}
+
+bool WebViewTest::javascriptResultIsNull(WebKitJavascriptResult* javascriptResult)
+{
+    JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult);
+    g_assert(context);
+    JSValueRef value = webkit_javascript_result_get_value(javascriptResult);
+    g_assert(value);
+
+    return JSValueIsNull(context, value);
+}
+
+bool WebViewTest::javascriptResultIsUndefined(WebKitJavascriptResult* javascriptResult)
+{
+    JSGlobalContextRef context = webkit_javascript_result_get_global_context(javascriptResult);
+    g_assert(context);
+    JSValueRef value = webkit_javascript_result_get_value(javascriptResult);
+    g_assert(value);
+
+    return JSValueIsUndefined(context, value);
+}
+
index 01f468562bb9829e4bae0766f8d468c0f64218d1..34afb0431fdd6e5c68e3848f2043c089effc8cc4 100644 (file)
@@ -48,11 +48,22 @@ public:
 
     void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0);
 
+    WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**);
+
+    // Javascript result helpers.
+    static char* javascriptResultToCString(WebKitJavascriptResult*);
+    static double javascriptResultToNumber(WebKitJavascriptResult*);
+    static bool javascriptResultToBoolean(WebKitJavascriptResult*);
+    static bool javascriptResultIsNull(WebKitJavascriptResult*);
+    static bool javascriptResultIsUndefined(WebKitJavascriptResult*);
+
     WebKitWebView* m_webView;
     GMainLoop* m_mainLoop;
     CString m_activeURI;
     GtkWidget* m_parentWindow;
     CString m_expectedTitle;
+    WebKitJavascriptResult* m_javascriptResult;
+    GError** m_javascriptError;
 };
 
 #endif // WebViewTest_h
index 0a807bc3d99891ecceaff7cc40192c8cade3c89a..f55776c3eb8913aae831906714d85257146fa861 100644 (file)
@@ -32,6 +32,7 @@
 #include <webkit2/WebKitError.h>
 #include <webkit2/WebKitFindController.h>
 #include <webkit2/WebKitHitTestResult.h>
+#include <webkit2/WebKitJavascriptResult.h>
 #include <webkit2/WebKitPrintOperation.h>
 #include <webkit2/WebKitScriptDialog.h>
 #include <webkit2/WebKitSettings.h>
index d637f93ccd09121cbaab90a02c7d2b7de783b37d..66c2774c74665da09ff9c6da06698a3d13ad6896 100644 (file)
@@ -1,3 +1,13 @@
+2012-03-21  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Add webkit_web_view_run_javascript() to WebKit2 GTK+
+        https://bugs.webkit.org/show_bug.cgi?id=75543
+
+        Reviewed by Martin Robinson.
+
+        * MiniBrowser/gtk/GNUmakefile.am: Add javascriptcore_cppflags to
+        MiniBrowser CPP flags.
+
 2012-03-20  Eric Seidel  <eric@webkit.org>
 
         Move wtf/Platform.h from JavaScriptCore to Source/WTF/wtf
index 9e42e194fb5716dcde97098fcfe613905cabc427..d28d9e4fe96d945db25f2d4e148dbd4f4779e5f0 100644 (file)
@@ -10,6 +10,7 @@ Programs_MiniBrowser_CPPFLAGS = \
        -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/include \
        -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs/\" \
        $(global_cppflags) \
+       $(javascriptcore_cppflags) \
        $(GLIB_CFLAGS) \
        $(GTK_CFLAGS)