diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp | 199 |
1 files changed, 162 insertions, 37 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp index 757532f7a..f632bc371 100644 --- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp @@ -22,15 +22,14 @@ #include <JavaScriptCore/JSContextRef.h> #include <JavaScriptCore/JSRetainPtr.h> #include <gio/gio.h> +#include <gst/gst.h> #include <stdlib.h> #include <string.h> #include <webkit2/webkit-web-extension.h> #include <wtf/Deque.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> #include <wtf/ProcessID.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> static const char introspectionXML[] = @@ -46,25 +45,26 @@ static const char introspectionXML[] = " <arg type='t' name='pageID' direction='in'/>" " <arg type='s' name='script' direction='in'/>" " </method>" - " <method name='GetInitializationUserData'>" - " <arg type='s' name='userData' direction='out'/>" - " </method>" " <method name='GetProcessIdentifier'>" " <arg type='u' name='identifier' direction='out'/>" " </method>" + " <method name='RemoveAVPluginsFromGSTRegistry'>" + " </method>" " <signal name='DocumentLoaded'/>" + " <signal name='FormControlsAssociated'>" + " <arg type='s' name='formIds' direction='out'/>" + " </signal>" " <signal name='URIChanged'>" " <arg type='s' name='uri' direction='out'/>" " </signal>" " </interface>" "</node>"; -static GRefPtr<GVariant> initializationUserData; - typedef enum { DocumentLoadedSignal, URIChangedSignal, + FormControlsAssociatedSignal, } DelayedSignalType; struct DelayedSignal { @@ -73,17 +73,17 @@ struct DelayedSignal { { } - DelayedSignal(DelayedSignalType type, const char* uri) + DelayedSignal(DelayedSignalType type, const char* str) : type(type) - , uri(uri) + , str(str) { } DelayedSignalType type; - CString uri; + CString str; }; -Deque<OwnPtr<DelayedSignal>> delayedSignalsQueue; +Deque<DelayedSignal> delayedSignalsQueue; static void emitDocumentLoaded(GDBusConnection* connection) { @@ -98,13 +98,17 @@ static void emitDocumentLoaded(GDBusConnection* connection) g_assert(ok); } -static void documentLoadedCallback(WebKitWebPage*, WebKitWebExtension* extension) +static void documentLoadedCallback(WebKitWebPage* webPage, WebKitWebExtension* extension) { + WebKitDOMDocument* document = webkit_web_page_get_dom_document(webPage); + GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(document)); + webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "dom", "DocumentLoaded"); + gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection"); if (data) emitDocumentLoaded(G_DBUS_CONNECTION(data)); else - delayedSignalsQueue.append(adoptPtr(new DelayedSignal(DocumentLoadedSignal))); + delayedSignalsQueue.append(DelayedSignal(DocumentLoadedSignal)); } static void emitURIChanged(GDBusConnection* connection, const char* uri) @@ -126,11 +130,12 @@ static void uriChangedCallback(WebKitWebPage* webPage, GParamSpec* pspec, WebKit if (data) emitURIChanged(G_DBUS_CONNECTION(data), webkit_web_page_get_uri(webPage)); else - delayedSignalsQueue.append(adoptPtr(new DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage)))); + delayedSignalsQueue.append(DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage))); } static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, WebKitURIResponse* redirectResponse, gpointer) { + gboolean returnValue = FALSE; const char* requestURI = webkit_uri_request_get_uri(request); g_assert(requestURI); @@ -153,17 +158,128 @@ static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, W SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(request); g_assert(headers); soup_message_headers_append(headers, "DNT", "1"); + } else if (g_str_has_suffix(requestURI, "/normal-change-request")) { + GUniquePtr<char> prefix(g_strndup(requestURI, strlen(requestURI) - strlen("/normal-change-request"))); + GUniquePtr<char> newURI(g_strdup_printf("%s/request-changed%s", prefix.get(), redirectResponse ? "-on-redirect" : "")); + webkit_uri_request_set_uri(request, newURI.get()); + } else if (g_str_has_suffix(requestURI, "/http-get-method")) { + g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "GET"); + g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_GET); + } else if (g_str_has_suffix(requestURI, "/http-post-method")) { + g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "POST"); + g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_POST); + returnValue = TRUE; } else if (g_str_has_suffix(requestURI, "/cancel-this.js")) + returnValue = TRUE; + + return returnValue; +} + +static GVariant* serializeContextMenu(WebKitContextMenu* menu) +{ + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + GList* items = webkit_context_menu_get_items(menu); + for (GList* it = items; it; it = g_list_next(it)) + g_variant_builder_add(&builder, "u", webkit_context_menu_item_get_stock_action(WEBKIT_CONTEXT_MENU_ITEM(it->data))); + return g_variant_builder_end(&builder); +} + +static GVariant* serializeNode(WebKitDOMNode* node) +{ + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY); + g_variant_builder_add(&builder, "{sv}", "Name", g_variant_new_take_string(webkit_dom_node_get_node_name(node))); + g_variant_builder_add(&builder, "{sv}", "Type", g_variant_new_uint32(webkit_dom_node_get_node_type(node))); + g_variant_builder_add(&builder, "{sv}", "Contents", g_variant_new_take_string(webkit_dom_node_get_text_content(node))); + WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node); + g_variant_builder_add(&builder, "{sv}", "Parent", parent ? g_variant_new_take_string(webkit_dom_node_get_node_name(parent)) : g_variant_new_string("ROOT")); + return g_variant_builder_end(&builder); +} + +static gboolean contextMenuCallback(WebKitWebPage* page, WebKitContextMenu* menu, WebKitWebHitTestResult* hitTestResult, gpointer) +{ + const char* pageURI = webkit_web_page_get_uri(page); + if (!g_strcmp0(pageURI, "ContextMenuTestDefault")) { + webkit_context_menu_set_user_data(menu, serializeContextMenu(menu)); + return FALSE; + } + + if (!g_strcmp0(pageURI, "ContextMenuTestCustom")) { + // Remove Back and Forward, and add Inspector action. + webkit_context_menu_remove(menu, webkit_context_menu_first(menu)); + webkit_context_menu_remove(menu, webkit_context_menu_first(menu)); + webkit_context_menu_append(menu, webkit_context_menu_item_new_separator()); + webkit_context_menu_append(menu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT)); + webkit_context_menu_set_user_data(menu, serializeContextMenu(menu)); + return TRUE; + } + + if (!g_strcmp0(pageURI, "ContextMenuTestClear")) { + webkit_context_menu_remove_all(menu); + return TRUE; + } + + if (!g_strcmp0(pageURI, "ContextMenuTestNode")) { + WebKitDOMNode* node = webkit_web_hit_test_result_get_node(hitTestResult); + g_assert(WEBKIT_DOM_IS_NODE(node)); + webkit_context_menu_set_user_data(menu, serializeNode(node)); return TRUE; + } return FALSE; } +static void consoleMessageSentCallback(WebKitWebPage* webPage, WebKitConsoleMessage* consoleMessage) +{ + g_assert(consoleMessage); + GRefPtr<GVariant> variant = g_variant_new("(uusus)", webkit_console_message_get_source(consoleMessage), + webkit_console_message_get_level(consoleMessage), webkit_console_message_get_text(consoleMessage), + webkit_console_message_get_line(consoleMessage), webkit_console_message_get_source_id(consoleMessage)); + GUniquePtr<char> messageString(g_variant_print(variant.get(), FALSE)); + GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(webkit_web_page_get_dom_document(webPage))); + g_assert(WEBKIT_DOM_IS_DOM_WINDOW(window.get())); + webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "console", messageString.get()); +} + + +static void emitFormControlsAssociated(GDBusConnection* connection, const char* formIds) +{ + bool ok = g_dbus_connection_emit_signal( + connection, + nullptr, + "/org/webkit/gtk/WebExtensionTest", + "org.webkit.gtk.WebExtensionTest", + "FormControlsAssociated", + g_variant_new("(s)", formIds), + nullptr); + g_assert(ok); +} + +static void formControlsAssociatedCallback(WebKitWebPage* webPage, GPtrArray* formElements, WebKitWebExtension* extension) +{ + GString* formIdsBuilder = g_string_new(nullptr); + for (int i = 0; i < formElements->len; ++i) { + g_assert(WEBKIT_DOM_IS_ELEMENT(g_ptr_array_index(formElements, i))); + auto domElement = WEBKIT_DOM_ELEMENT(g_ptr_array_index(formElements, i)); + g_string_append(formIdsBuilder, webkit_dom_element_get_id(domElement)); + } + GUniquePtr<char> formIds(g_string_free(formIdsBuilder, FALSE)); + gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection"); + if (data) + emitFormControlsAssociated(G_DBUS_CONNECTION(data), formIds.get()); + else + delayedSignalsQueue.append(DelayedSignal(FormControlsAssociatedSignal, formIds.get())); +} + static void pageCreatedCallback(WebKitWebExtension* extension, WebKitWebPage* webPage, gpointer) { g_signal_connect(webPage, "document-loaded", G_CALLBACK(documentLoadedCallback), extension); g_signal_connect(webPage, "notify::uri", G_CALLBACK(uriChangedCallback), extension); - g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), 0); + g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), nullptr); + g_signal_connect(webPage, "context-menu", G_CALLBACK(contextMenuCallback), nullptr); + g_signal_connect(webPage, "console-message-sent", G_CALLBACK(consoleMessageSentCallback), nullptr); + g_signal_connect(webPage, "form-controls-associated", G_CALLBACK(formControlsAssociatedCallback), extension); } static JSValueRef echoCallback(JSContextRef jsContext, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef*) @@ -233,14 +349,20 @@ static void methodCallCallback(GDBusConnection* connection, const char* sender, g_dbus_method_invocation_return_value(invocation, 0); } else if (!g_strcmp0(methodName, "AbortProcess")) { abort(); - } else if (!g_strcmp0(methodName, "GetInitializationUserData")) { - g_assert(initializationUserData); - g_assert(g_variant_is_of_type(initializationUserData.get(), G_VARIANT_TYPE_STRING)); - g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)", - g_variant_get_string(initializationUserData.get(), nullptr))); } else if (!g_strcmp0(methodName, "GetProcessIdentifier")) { g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", static_cast<guint32>(getCurrentProcessID()))); + } else if (!g_strcmp0(methodName, "RemoveAVPluginsFromGSTRegistry")) { + gst_init(nullptr, nullptr); + static const char* avPlugins[] = { "libav", "omx", "vaapi", nullptr }; + GstRegistry* registry = gst_registry_get(); + for (unsigned i = 0; avPlugins[i]; ++i) { + if (GstPlugin* plugin = gst_registry_find_plugin(registry, avPlugins[i])) { + gst_registry_remove_plugin(registry, plugin); + gst_object_unref(plugin); + } + } + g_dbus_method_invocation_return_value(invocation, nullptr); } } @@ -268,38 +390,41 @@ static void busAcquiredCallback(GDBusConnection* connection, const char* name, g g_object_set_data(G_OBJECT(userData), "dbus-connection", connection); while (delayedSignalsQueue.size()) { - OwnPtr<DelayedSignal> delayedSignal = delayedSignalsQueue.takeFirst(); - switch (delayedSignal->type) { + DelayedSignal delayedSignal = delayedSignalsQueue.takeFirst(); + switch (delayedSignal.type) { case DocumentLoadedSignal: emitDocumentLoaded(connection); break; case URIChangedSignal: - emitURIChanged(connection, delayedSignal->uri.data()); + emitURIChanged(connection, delayedSignal.str.data()); + break; + case FormControlsAssociatedSignal: + emitFormControlsAssociated(connection, delayedSignal.str.data()); break; } } } -static GUniquePtr<char> makeBusName(GVariant* userData) +static void registerGResource(void) { - // When the web extension is used by TestMultiprocess, an uint32 - // identifier is passed as user data. It uniquely identifies - // the web process, and the UI side expects it added as suffix to - // the bus name. - if (userData && g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32)) - return GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData))); - - return GUniquePtr<char>(g_strdup("org.webkit.gtk.WebExtensionTest")); + GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "resources", "webkit2gtk-tests-resources.gresource", nullptr)); + GResource* resource = g_resource_load(resourcesPath.get(), nullptr); + g_assert(resource); + + g_resources_register(resource); + g_resource_unref(resource); } extern "C" void webkit_web_extension_initialize_with_user_data(WebKitWebExtension* extension, GVariant* userData) { - initializationUserData = userData; - g_signal_connect(extension, "page-created", G_CALLBACK(pageCreatedCallback), extension); g_signal_connect(webkit_script_world_get_default(), "window-object-cleared", G_CALLBACK(windowObjectCleared), 0); - GUniquePtr<char> busName(makeBusName(userData)); + registerGResource(); + + g_assert(userData); + g_assert(g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32)); + GUniquePtr<char> busName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData))); g_bus_own_name( G_BUS_TYPE_SESSION, busName.get(), |