summaryrefslogtreecommitdiff
path: root/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp')
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp388
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;
+}