diff options
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp')
-rw-r--r-- | Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp new file mode 100644 index 000000000..e84cb5c20 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2013-2014 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2,1 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 "WebKitTestServer.h" +#include "WebViewTest.h" +#include <cstdarg> +#include <gtk/gtk.h> +#include <webkit2/webkit2.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> + +class UserContentManagerTest : public WebViewTest { +public: + MAKE_GLIB_TEST_FIXTURE(UserContentManagerTest); + + UserContentManagerTest() + : WebViewTest(webkit_user_content_manager_new()) + { + // A reference is leaked when passing the result of webkit_user_content_manager_new() + // directly to webkit_web_view_new_with_user_content_manager() above. Adopting the + // reference here avoids the leak. + m_userContentManager = adoptGRef(webkit_web_view_get_user_content_manager(m_webView)); + assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_userContentManager.get())); + } + + GRefPtr<WebKitUserContentManager> m_userContentManager; +}; + +static WebKitTestServer* kServer; + +// These are all here so that they can be changed easily, if necessary. +static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>"; +static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }"; +static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']"; +static const char* kStyleSheetTestScriptResult = "bold"; +static const char* kInjectedScript = "document.write('<div id=\"item\">Generated by a script</div>')"; +static const char* kScriptTestScript = "document.getElementById('item').innerText"; +static const char* kScriptTestScriptResult = "Generated by a script"; + +static void testWebViewNewWithUserContentManager(Test* test, gconstpointer) +{ + GRefPtr<WebKitUserContentManager> userContentManager1 = adoptGRef(webkit_user_content_manager_new()); + test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(userContentManager1.get())); + GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(userContentManager1.get())); + g_assert(webkit_web_view_get_user_content_manager(webView1.get()) == userContentManager1.get()); + + GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new()); + g_assert(webkit_web_view_get_user_content_manager(webView2.get()) != userContentManager1.get()); +} + +static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path) +{ + test->loadURI(kServer->getURIForPath(path).data()); + test->waitUntilLoadFinished(); + + GUniqueOutPtr<GError> error; + WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + + GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult)); + return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult); +} + +static bool isScriptInjectedForURLAtPath(WebViewTest* test, const char* path) +{ + test->loadURI(kServer->getURIForPath(path).data()); + test->waitUntilLoadFinished(); + + GUniqueOutPtr<GError> error; + if (WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kScriptTestScript, &error.outPtr())) { + g_assert(!error.get()); + + GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult)); + return !g_strcmp0(resultString.get(), kScriptTestScriptResult); + } + return false; +} + +static void fillURLListFromPaths(char** list, const char* path, ...) +{ + va_list argumentList; + va_start(argumentList, path); + + int i = 0; + while (path) { + // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed. + // Until that time patterns with port numbers in them will not properly match URLs with port numbers. + list[i++] = g_strdup_printf("http://*/%s*", path); + path = va_arg(argumentList, const char*); + } +} + +static void removeOldInjectedContentAndResetLists(WebKitUserContentManager* userContentManager, char** whitelist, char** blacklist) +{ + webkit_user_content_manager_remove_all_style_sheets(userContentManager); + webkit_user_content_manager_remove_all_scripts(userContentManager); + + while (*whitelist) { + g_free(*whitelist); + *whitelist = 0; + whitelist++; + } + + while (*blacklist) { + g_free(*blacklist); + *blacklist = 0; + blacklist++; + } +} + +static void testUserContentManagerInjectedStyleSheet(UserContentManagerTest* test, gconstpointer) +{ + char* whitelist[3] = { 0, 0, 0 }; + char* blacklist[3] = { 0, 0, 0 }; + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + // Without a whitelist or a blacklist all URLs should have the injected style sheet. + static const char* randomPath = "somerandompath"; + g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath)); + WebKitUserStyleSheet* styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, nullptr); + webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); + webkit_user_style_sheet_unref(styleSheet); + g_assert(isStyleSheetInjectedForURLAtPath(test, randomPath)); + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + fillURLListFromPaths(blacklist, randomPath, 0); + styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, blacklist); + webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); + webkit_user_style_sheet_unref(styleSheet); + g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath)); + g_assert(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath")); + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + static const char* inTheWhiteList = "inthewhitelist"; + static const char* notInWhitelist = "notinthewhitelist"; + static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist"; + + fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0); + fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0); + styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, whitelist, blacklist); + webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); + webkit_user_style_sheet_unref(styleSheet); + g_assert(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList)); + g_assert(!isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList)); + g_assert(!isStyleSheetInjectedForURLAtPath(test, notInWhitelist)); + + // It's important to clean up the environment before other tests. + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); +} + +static void testUserContentManagerInjectedScript(UserContentManagerTest* test, gconstpointer) +{ + char* whitelist[3] = { 0, 0, 0 }; + char* blacklist[3] = { 0, 0, 0 }; + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + // Without a whitelist or a blacklist all URLs should have the injected script. + static const char* randomPath = "somerandompath"; + g_assert(!isScriptInjectedForURLAtPath(test, randomPath)); + WebKitUserScript* script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, nullptr); + webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); + webkit_user_script_unref(script); + g_assert(isScriptInjectedForURLAtPath(test, randomPath)); + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + fillURLListFromPaths(blacklist, randomPath, 0); + script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, blacklist); + webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); + webkit_user_script_unref(script); + g_assert(!isScriptInjectedForURLAtPath(test, randomPath)); + g_assert(isScriptInjectedForURLAtPath(test, "someotherrandompath")); + + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); + + static const char* inTheWhiteList = "inthewhitelist"; + static const char* notInWhitelist = "notinthewhitelist"; + static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist"; + + fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0); + fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0); + script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, whitelist, blacklist); + webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); + webkit_user_script_unref(script); + g_assert(isScriptInjectedForURLAtPath(test, inTheWhiteList)); + g_assert(!isScriptInjectedForURLAtPath(test, inTheWhiteListAndBlackList)); + g_assert(!isScriptInjectedForURLAtPath(test, notInWhitelist)); + + // It's important to clean up the environment before other tests. + removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); +} + +class UserScriptMessageTest : public UserContentManagerTest { +public: + MAKE_GLIB_TEST_FIXTURE(UserScriptMessageTest); + + UserScriptMessageTest() + : UserContentManagerTest() + , m_userScriptMessage(nullptr) + { + } + + ~UserScriptMessageTest() + { + if (m_userScriptMessage) + webkit_javascript_result_unref(m_userScriptMessage); + } + + bool registerHandler(const char* handlerName) + { + return webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), handlerName); + } + + void unregisterHandler(const char* handlerName) + { + webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), handlerName); + } + + static void scriptMessageReceived(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* jsResult, UserScriptMessageTest* test) + { + g_signal_handlers_disconnect_by_func(userContentManager, reinterpret_cast<gpointer>(scriptMessageReceived), test); + g_main_loop_quit(test->m_mainLoop); + + g_assert(!test->m_userScriptMessage); + test->m_userScriptMessage = webkit_javascript_result_ref(jsResult); + } + + WebKitJavascriptResult* waitUntilMessageReceived(const char* handlerName) + { + if (m_userScriptMessage) { + webkit_javascript_result_unref(m_userScriptMessage); + m_userScriptMessage = nullptr; + } + + GUniquePtr<char> signalName(g_strdup_printf("script-message-received::%s", handlerName)); + g_signal_connect(m_userContentManager.get(), signalName.get(), G_CALLBACK(scriptMessageReceived), this); + + g_main_loop_run(m_mainLoop); + g_assert(m_userScriptMessage); + return m_userScriptMessage; + } + + WebKitJavascriptResult* postMessageAndWaitUntilReceived(const char* handlerName, const char* javascriptValueAsText) + { + GUniquePtr<char> javascriptSnippet(g_strdup_printf("window.webkit.messageHandlers.%s.postMessage(%s);", handlerName, javascriptValueAsText)); + webkit_web_view_run_javascript(m_webView, javascriptSnippet.get(), nullptr, nullptr, nullptr); + return waitUntilMessageReceived(handlerName); + } + +private: + WebKitJavascriptResult* m_userScriptMessage; +}; + +static void testUserContentManagerScriptMessageReceived(UserScriptMessageTest* test, gconstpointer) +{ + g_assert(test->registerHandler("msg")); + + // Trying to register the same handler a second time must fail. + g_assert(!test->registerHandler("msg")); + + test->loadHtml("<html></html>", nullptr); + test->waitUntilLoadFinished(); + + // Check that the "window.webkit.messageHandlers" namespace exists. + GUniqueOutPtr<GError> error; + WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "y"); + + // Check that the "document.webkit.messageHandlers.msg" namespace exists. + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "y"); + + valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'user message'"))); + g_assert_cmpstr(valueString.get(), ==, "user message"); + + // Messages should arrive despite of other handlers being registered. + g_assert(test->registerHandler("anotherHandler")); + + // Check that the "document.webkit.messageHandlers.msg" namespace still exists. + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "y"); + + // Check that the "document.webkit.messageHandlers.anotherHandler" namespace exists. + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.anotherHandler ? 'y' : 'n';", &error.outPtr()); + g_assert(javascriptResult); + g_assert(!error.get()); + valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "y"); + + valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'"))); + g_assert_cmpstr(valueString.get(), ==, "handler: msg"); + + valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("anotherHandler", "'handler: anotherHandler'"))); + g_assert_cmpstr(valueString.get(), ==, "handler: anotherHandler"); + + // Unregistering a handler and re-registering again under the same name should work. + test->unregisterHandler("msg"); + + javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg.postMessage('42');", &error.outPtr()); + g_assert(!javascriptResult); + g_assert(error.get()); + + // Re-registering a handler that has been unregistered must work + g_assert(test->registerHandler("msg")); + valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'"))); + g_assert_cmpstr(valueString.get(), ==, "handler: msg"); + + test->unregisterHandler("anotherHandler"); +} + +static void testUserContentManagerScriptMessageFromDOMBindings(UserScriptMessageTest* test, gconstpointer) +{ + g_assert(test->registerHandler("dom")); + + test->loadHtml("<html>1</html>", nullptr); + WebKitJavascriptResult* javascriptResult = test->waitUntilMessageReceived("dom"); + g_assert(javascriptResult); + GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded"); + + test->unregisterHandler("dom"); + + g_assert(test->registerHandler("dom-convenience")); + + test->loadHtml("<html>2</html>", nullptr); + javascriptResult = test->waitUntilMessageReceived("dom-convenience"); + g_assert(javascriptResult); + valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); + g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded"); + + test->unregisterHandler("dom-convenience"); +} + +static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) +{ + soup_message_set_status(message, SOUP_STATUS_OK); + soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML)); + soup_message_body_complete(message->response_body); +} + +void beforeAll() +{ + kServer = new WebKitTestServer(); + kServer->run(serverCallback); + + Test::add("WebKitWebView", "new-with-user-content-manager", testWebViewNewWithUserContentManager); + UserContentManagerTest::add("WebKitUserContentManager", "injected-style-sheet", testUserContentManagerInjectedStyleSheet); + UserContentManagerTest::add("WebKitUserContentManager", "injected-script", testUserContentManagerInjectedScript); + UserScriptMessageTest::add("WebKitUserContentManager", "script-message-received", testUserContentManagerScriptMessageReceived); + UserScriptMessageTest::add("WebKitUserContentManager", "script-message-from-dom-bindings", testUserContentManagerScriptMessageFromDOMBindings); +} + +void afterAll() +{ + delete kServer; +} |