Changeset 154545 in webkit


Ignore:
Timestamp:
Aug 24, 2013 5:02:04 AM (11 years ago)
Author:
Carlos Garcia Campos
Message:

[GTK] Add WebKit2 API for isolated worlds
https://bugs.webkit.org/show_bug.cgi?id=103377

Reviewed by Anders Carlsson.

  • GNUmakefile.list.am: Add new files to compilation.
  • UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
  • UIProcess/API/gtk/tests/TestWebExtensions.cpp:

(testWebExtensionWindowObjectCleared):
(scriptDialogCallback):
(runJavaScriptInIsolatedWorldFinishedCallback):
(testWebExtensionIsolatedWorld):
(beforeAll):

  • UIProcess/API/gtk/tests/WebExtensionTest.cpp:

(echoCallback):
(windowObjectCleared):
(getWebPage):
(methodCallCallback):

  • WebProcess/InjectedBundle/API/gtk/WebKitFrame.cpp:

(webkit_frame_get_javascript_context_for_script_world): New public
method to tget the JavaScript execution context for a given script
world.

  • WebProcess/InjectedBundle/API/gtk/WebKitFrame.h:
  • WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.cpp: Added.

(scriptWorlds): Global WebKitScriptWorld map.
(_WebKitScriptWorldPrivate::~_WebKitScriptWorldPrivate):
(webkitScriptWorldGet): Get the WebKitScriptWorld wrapping the
given injected bundle script world.
(webkitScriptWorldGetInjectedBundleScriptWorld): Get the injected
bundle script world wrapped by the given WebKitScriptWorld.
(webkitScriptWorldWindowObjectCleared): Emit
WebKitScriptWorld::window-object-cleared signal.
(webkitScriptWorldCreate): Create a new WebKitScriptWorld wrapping
the given injected bundle script world.
(createDefaultScriptWorld): Create the default WebKitScriptWorld
wrapping the normal world.
(webkit_script_world_get_default): Return the default WebKitScriptWorld.
(webkit_script_world_new): Create a new isolated WebKitScriptWorld.

  • WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.h: Added.
  • WebProcess/InjectedBundle/API/gtk/WebKitScriptWorldPrivate.h: Added.
  • WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp:

(didClearWindowObjectForFrame): Call webkitScriptWorldWindowObjectCleared().
(webkitWebPageCreate): Add implementation for callback
didClearWindowObjectForFrame in injected bundle loader client.

  • WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h:

Include WebKitScriptWorld.h.

Location:
trunk/Source/WebKit2
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r154540 r154545  
     12013-08-24  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK] Add WebKit2 API for isolated worlds
     4        https://bugs.webkit.org/show_bug.cgi?id=103377
     5
     6        Reviewed by Anders Carlsson.
     7
     8        * GNUmakefile.list.am: Add new files to compilation.
     9        * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
     10        * UIProcess/API/gtk/tests/TestWebExtensions.cpp:
     11        (testWebExtensionWindowObjectCleared):
     12        (scriptDialogCallback):
     13        (runJavaScriptInIsolatedWorldFinishedCallback):
     14        (testWebExtensionIsolatedWorld):
     15        (beforeAll):
     16        * UIProcess/API/gtk/tests/WebExtensionTest.cpp:
     17        (echoCallback):
     18        (windowObjectCleared):
     19        (getWebPage):
     20        (methodCallCallback):
     21        * WebProcess/InjectedBundle/API/gtk/WebKitFrame.cpp:
     22        (webkit_frame_get_javascript_context_for_script_world): New public
     23        method to tget the JavaScript execution context for a given script
     24        world.
     25        * WebProcess/InjectedBundle/API/gtk/WebKitFrame.h:
     26        * WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.cpp: Added.
     27        (scriptWorlds): Global WebKitScriptWorld map.
     28        (_WebKitScriptWorldPrivate::~_WebKitScriptWorldPrivate):
     29        (webkitScriptWorldGet): Get the WebKitScriptWorld wrapping the
     30        given injected bundle script world.
     31        (webkitScriptWorldGetInjectedBundleScriptWorld): Get the injected
     32        bundle script world wrapped by the given WebKitScriptWorld.
     33        (webkitScriptWorldWindowObjectCleared): Emit
     34        WebKitScriptWorld::window-object-cleared signal.
     35        (webkitScriptWorldCreate): Create a new WebKitScriptWorld wrapping
     36        the given injected bundle script world.
     37        (createDefaultScriptWorld): Create the default WebKitScriptWorld
     38        wrapping the normal world.
     39        (webkit_script_world_get_default): Return the default WebKitScriptWorld.
     40        (webkit_script_world_new): Create a new isolated WebKitScriptWorld.
     41        * WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.h: Added.
     42        * WebProcess/InjectedBundle/API/gtk/WebKitScriptWorldPrivate.h: Added.
     43        * WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp:
     44        (didClearWindowObjectForFrame): Call webkitScriptWorldWindowObjectCleared().
     45        (webkitWebPageCreate): Add implementation for callback
     46        didClearWindowObjectForFrame in injected bundle loader client.
     47        * WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h:
     48        Include WebKitScriptWorld.h.
     49
    1502013-08-24  Carlos Garcia Campos  <cgarcia@igalia.com>
    251
  • trunk/Source/WebKit2/GNUmakefile.list.am

    r154540 r154545  
    141141        $(WebKit2)/WebProcess/InjectedBundle/API/gtk/WebKitFrame.h \
    142142        $(WebKit2)/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.h \
     143        $(WebKit2)/WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.h \
    143144        $(WebKit2)/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h
    144145
     
    10641065        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitFrame.h \
    10651066        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitFramePrivate.h \
     1067        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.cpp \
     1068        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.h \
     1069        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitScriptWorldPrivate.h \
    10661070        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp \
    10671071        Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.h \
  • trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt

    r154540 r154545  
    10631063webkit_frame_get_uri
    10641064webkit_frame_get_javascript_global_context
     1065webkit_frame_get_javascript_context_for_script_world
    10651066
    10661067<SUBSECTION Standard>
     
    10771078webkit_frame_get_type
    10781079</SECTION>
     1080
     1081<SECTION>
     1082<FILE>WebKitScriptWorld</FILE>
     1083WebKitScriptWorld
     1084webkit_script_world_get_default
     1085webkit_script_world_new
     1086
     1087<SUBSECTION Standard>
     1088WebKitScriptWorldClass
     1089WEBKIT_TYPE_SCRIPT_WORLD
     1090WEBKIT_SCRIPT_WORLD
     1091WEBKIT_IS_SCRIPT_WORLD
     1092WEBKIT_SCRIPT_WORLD_CLASS
     1093WEBKIT_IS_SCRIPT_WORLD_CLASS
     1094WEBKIT_SCRIPT_WORLD_GET_CLASS
     1095
     1096<SUBSECTION Private>
     1097WebKitScriptWorldPrivate
     1098webkit_script_world_get_type
     1099</SECTION>
  • trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebExtensions.cpp

    r148665 r154545  
    101101}
    102102
     103static void testWebExtensionWindowObjectCleared(WebViewTest* test, gconstpointer)
     104{
     105    test->loadHtml("<html><header></header><body></body></html>", 0);
     106    test->waitUntilLoadFinished();
     107
     108    GOwnPtr<GError> error;
     109    WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.echo('Foo');", &error.outPtr());
     110    g_assert(javascriptResult);
     111    g_assert(!error.get());
     112    GOwnPtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
     113    g_assert_cmpstr(valueString.get(), ==, "Foo");
     114}
     115
     116static gboolean scriptDialogCallback(WebKitWebView*, WebKitScriptDialog* dialog, char** result)
     117{
     118    g_assert_cmpuint(webkit_script_dialog_get_dialog_type(dialog), ==, WEBKIT_SCRIPT_DIALOG_ALERT);
     119    g_assert(!*result);
     120    *result = g_strdup(webkit_script_dialog_get_message(dialog));
     121    return TRUE;
     122}
     123
     124static void runJavaScriptInIsolatedWorldFinishedCallback(GDBusProxy* proxy, GAsyncResult* result, WebViewTest* test)
     125{
     126    g_dbus_proxy_call_finish(proxy, result, 0);
     127    g_main_loop_quit(test->m_mainLoop);
     128}
     129
     130static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
     131{
     132    test->loadHtml("<html><header></header><body><div id='console'></div></body></html>", 0);
     133    test->waitUntilLoadFinished();
     134
     135    GOwnPtr<char> result;
     136    gulong scriptDialogID = g_signal_connect(test->m_webView, "script-dialog", G_CALLBACK(scriptDialogCallback), &result.outPtr());
     137
     138    static const char *mainWorldScript =
     139        "top.foo = 'Foo';\n"
     140        "document.getElementById('console').innerHTML = top.foo;\n"
     141        "window.open = function () { alert('Main World'); }\n"
     142        "document.open(1, 2, 3);";
     143    test->runJavaScriptAndWaitUntilFinished(mainWorldScript, 0);
     144    g_assert_cmpstr(result.get(), ==, "Main World");
     145    result.clear();
     146
     147    WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
     148    g_assert(javascriptResult);
     149    GOwnPtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
     150    g_assert_cmpstr(valueString.get(), ==, "Foo");
     151
     152    static const char *isolatedWorldScript =
     153        "document.getElementById('console').innerHTML = top.foo;\n"
     154        "window.open = function () { alert('Isolated World'); }\n"
     155        "document.open(1, 2, 3);";
     156    GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
     157        "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
     158    g_dbus_proxy_call(proxy.get(),
     159        "RunJavaScriptInIsolatedWorld",
     160        g_variant_new("(t&s)", webkit_web_view_get_page_id(test->m_webView), isolatedWorldScript),
     161        G_DBUS_CALL_FLAGS_NONE,
     162        -1, 0,
     163        reinterpret_cast<GAsyncReadyCallback>(runJavaScriptInIsolatedWorldFinishedCallback),
     164        test);
     165    g_main_loop_run(test->m_mainLoop);
     166    g_assert_cmpstr(result.get(), ==, "Isolated World");
     167    result.clear();
     168
     169    // Check that 'top.foo' defined in main world is not visible in isolated world.
     170    javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
     171    g_assert(javascriptResult);
     172    valueString.set(WebViewTest::javascriptResultToCString(javascriptResult));
     173    g_assert_cmpstr(valueString.get(), ==, "undefined");
     174
     175    g_signal_handler_disconnect(test->m_webView, scriptDialogID);
     176}
     177
    103178void beforeAll()
    104179{
     
    111186    WebViewTest::add("WebKitWebExtension", "document-loaded-signal", testDocumentLoadedSignal);
    112187    WebViewTest::add("WebKitWebView", "web-process-crashed", testWebKitWebViewProcessCrashed);
     188    WebViewTest::add("WebKitWebExtension", "window-object-cleared", testWebExtensionWindowObjectCleared);
     189    WebViewTest::add("WebKitWebExtension", "isolated-world", testWebExtensionIsolatedWorld);
    113190}
    114191
  • trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebExtensionTest.cpp

    r152095 r154545  
    2020#include "config.h"
    2121
     22#include <JavaScriptCore/JSContextRef.h>
     23#include <JavaScriptCore/JSRetainPtr.h>
    2224#include <gio/gio.h>
    2325#include <stdlib.h>
    2426#include <string.h>
    25 
    2627#include <webkit2/webkit-web-extension.h>
    2728#include <wtf/gobject/GOwnPtr.h>
     29#include <wtf/gobject/GRefPtr.h>
    2830
    2931static const char introspectionXML[] =
     
    3537    "  </method>"
    3638    "  <method name='AbortProcess'>"
     39    "  </method>"
     40    "  <method name='RunJavaScriptInIsolatedWorld'>"
     41    "   <arg type='t' name='pageID' direction='in'/>"
     42    "   <arg type='s' name='script' direction='in'/>"
    3743    "  </method>"
    3844    "  <signal name='DocumentLoaded'/>"
     
    94100}
    95101
     102static JSValueRef echoCallback(JSContextRef jsContext, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
     103{
     104    if (argumentCount <= 0)
     105        return JSValueMakeUndefined(jsContext);
     106
     107    JSRetainPtr<JSStringRef> string(Adopt, JSValueToStringCopy(jsContext, arguments[0], 0));
     108    return JSValueMakeString(jsContext, string.get());
     109}
     110
     111static void windowObjectCleared(WebKitScriptWorld* world, WebKitWebPage* page, WebKitFrame* frame, gpointer)
     112{
     113    JSGlobalContextRef jsContext = webkit_frame_get_javascript_context_for_script_world(frame, world);
     114    g_assert(jsContext);
     115    JSObjectRef globalObject = JSContextGetGlobalObject(jsContext);
     116    g_assert(globalObject);
     117
     118    JSRetainPtr<JSStringRef> functionName(Adopt, JSStringCreateWithUTF8CString("echo"));
     119    JSObjectRef function = JSObjectMakeFunctionWithCallback(jsContext, functionName.get(), echoCallback);
     120    JSObjectSetProperty(jsContext, globalObject, functionName.get(), function, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
     121}
     122
     123static WebKitWebPage* getWebPage(WebKitWebExtension* extension, uint64_t pageID, GDBusMethodInvocation* invocation)
     124{
     125    WebKitWebPage* page = webkit_web_extension_get_page(extension, pageID);
     126    if (!page) {
     127        g_dbus_method_invocation_return_error(
     128            invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
     129            "Invalid page ID: %" G_GUINT64_FORMAT, pageID);
     130        return 0;
     131    }
     132
     133    g_assert_cmpuint(webkit_web_page_get_id(page), ==, pageID);
     134    return page;
     135}
     136
    96137static void methodCallCallback(GDBusConnection* connection, const char* sender, const char* objectPath, const char* interfaceName, const char* methodName, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData)
    97138{
     
    102143        uint64_t pageID;
    103144        g_variant_get(parameters, "(t)", &pageID);
    104 
    105         WebKitWebExtension* extension = WEBKIT_WEB_EXTENSION(userData);
    106         WebKitWebPage* page = webkit_web_extension_get_page(extension, pageID);
    107         if (!page) {
    108             g_dbus_method_invocation_return_error(
    109                 invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
    110                 "Invalid page ID: %" G_GUINT64_FORMAT, pageID);
     145        WebKitWebPage* page = getWebPage(WEBKIT_WEB_EXTENSION(userData), pageID, invocation);
     146        if (!page)
    111147            return;
    112         }
    113         g_assert_cmpuint(webkit_web_page_get_id(page), ==, pageID);
    114148
    115149        WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
    116150        GOwnPtr<char> title(webkit_dom_document_get_title(document));
    117151        g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", title.get()));
     152    } else if (!g_strcmp0(methodName, "RunJavaScriptInIsolatedWorld")) {
     153        uint64_t pageID;
     154        const char* script;
     155        g_variant_get(parameters, "(t&s)", &pageID, &script);
     156        WebKitWebPage* page = getWebPage(WEBKIT_WEB_EXTENSION(userData), pageID, invocation);
     157        if (!page)
     158            return;
     159
     160        GRefPtr<WebKitScriptWorld> world = adoptGRef(webkit_script_world_new());
     161        g_assert(webkit_script_world_get_default() != world.get());
     162        WebKitFrame* frame = webkit_web_page_get_main_frame(page);
     163        JSGlobalContextRef jsContext = webkit_frame_get_javascript_context_for_script_world(frame, world.get());
     164        JSRetainPtr<JSStringRef> jsScript(Adopt, JSStringCreateWithUTF8CString(script));
     165        JSEvaluateScript(jsContext, jsScript.get(), 0, 0, 0, 0);
     166        g_dbus_method_invocation_return_value(invocation, 0);
    118167    } else if (!g_strcmp0(methodName, "AbortProcess")) {
    119168        abort();
     
    144193
    145194    g_signal_connect(WEBKIT_WEB_EXTENSION(userData), "page-created", G_CALLBACK(pageCreatedCallback), connection);
     195    g_signal_connect(webkit_script_world_get_default(), "window-object-cleared", G_CALLBACK(windowObjectCleared), 0);
    146196}
    147197
  • trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitFrame.cpp

    r154540 r154545  
    2323#include "WebKitFramePrivate.h"
    2424#include "WebKitPrivate.h"
     25#include "WebKitScriptWorldPrivate.h"
    2526#include <wtf/text/CString.h>
    2627
     
    102103    return frame->priv->webFrame->jsContext();
    103104}
     105
     106/**
     107 * webkit_frame_get_javascript_context_for_script_world:
     108 * @frame: a #WebKitFrame
     109 * @world: a #WebKitScriptWorld
     110 *
     111 * Gets the JavaScript execution context of @frame for the given #WebKitScriptWorld.
     112 *
     113 * Returns: (transfer none): the JavaScript context of @frame for @world
     114 *
     115 * Since: 2.2
     116 */
     117JSGlobalContextRef webkit_frame_get_javascript_context_for_script_world(WebKitFrame* frame, WebKitScriptWorld* world)
     118{
     119    g_return_val_if_fail(WEBKIT_IS_FRAME(frame), 0);
     120    g_return_val_if_fail(WEBKIT_IS_SCRIPT_WORLD(world), 0);
     121
     122    return frame->priv->webFrame->jsContextForWorld(webkitScriptWorldGetInjectedBundleScriptWorld(world));
     123}
  • trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitFrame.h

    r154540 r154545  
    2828#include <glib-object.h>
    2929#include <webkit2/WebKitDefines.h>
     30#include <webkit2/WebKitScriptWorld.h>
    3031
    3132G_BEGIN_DECLS
     
    5354
    5455WEBKIT_API GType
    55 webkit_frame_get_type                      (void);
     56webkit_frame_get_type                                (void);
    5657
    5758WEBKIT_API gboolean
    58 webkit_frame_is_main_frame                 (WebKitFrame *frame);
     59webkit_frame_is_main_frame                           (WebKitFrame      *frame);
    5960
    6061WEBKIT_API const gchar *
    61 webkit_frame_get_uri                       (WebKitFrame *frame);
     62webkit_frame_get_uri                                 (WebKitFrame      *frame);
    6263
    6364WEBKIT_API JSGlobalContextRef
    64 webkit_frame_get_javascript_global_context (WebKitFrame *frame);
     65webkit_frame_get_javascript_global_context           (WebKitFrame       *frame);
     66
     67WEBKIT_API JSGlobalContextRef
     68webkit_frame_get_javascript_context_for_script_world (WebKitFrame       *frame,
     69                                                      WebKitScriptWorld *world);
    6570
    6671G_END_DECLS
  • trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp

    r154540 r154545  
    3131#include "WebKitMarshal.h"
    3232#include "WebKitPrivate.h"
     33#include "WebKitScriptWorldPrivate.h"
    3334#include "WebKitURIRequestPrivate.h"
    3435#include "WebKitURIResponsePrivate.h"
     
    142143{
    143144    webFrameMap().remove(toImpl(frame));
     145}
     146
     147static void didClearWindowObjectForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKBundleScriptWorldRef wkWorld, const void* clientInfo)
     148{
     149    if (WebKitScriptWorld* world = webkitScriptWorldGet(toImpl(wkWorld)))
     150        webkitScriptWorldWindowObjectCleared(world, WEBKIT_WEB_PAGE(clientInfo), webkitFrameGetOrCreate(toImpl(frame)));
    144151}
    145152
     
    320327        0, // didDisplayInsecureContentForFrame
    321328        0, // didRunInsecureContentForFrame
    322         0, // didClearWindowObjectForFrame
     329        didClearWindowObjectForFrame,
    323330        0, // didCancelClientRedirectForFrame
    324331        0, // willPerformClientRedirectForFrame
  • trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h

    r154540 r154545  
    2424
    2525#include <webkit2/WebKitFrame.h>
     26#include <webkit2/WebKitScriptWorld.h>
    2627#include <webkit2/WebKitURIRequest.h>
    2728#include <webkit2/WebKitURIResponse.h>
Note: See TracChangeset for help on using the changeset viewer.