[CMake] Properly test if compiler supports compiler flags
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitGLib / TestWebExtensions.cpp
1 /*
2  * Copyright (C) 2012 Igalia S.L.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2,1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21
22 #include "WebKitTestBus.h"
23 #include "WebViewTest.h"
24 #include <wtf/glib/GRefPtr.h>
25
26 static WebKitTestBus* bus;
27 static GUniquePtr<char> scriptDialogResult;
28
29 #define INPUT_ID "input-id"
30 #define FORM_ID "form-id"
31 #define FORM2_ID "form2-id"
32
33 static void testWebExtensionGetTitle(WebViewTest* test, gconstpointer)
34 {
35     test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
36     test->waitUntilLoadFinished();
37
38     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
39     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
40         "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
41     GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
42         proxy.get(),
43         "GetTitle",
44         g_variant_new("(t)", webkit_web_view_get_page_id(test->m_webView)),
45         G_DBUS_CALL_FLAGS_NONE,
46         -1, 0, 0));
47     g_assert(result);
48
49     const char* title;
50     g_variant_get(result.get(), "(&s)", &title);
51     g_assert_cmpstr(title, ==, "WebKitGTK+ Web Extensions Test");
52 }
53
54 static void documentLoadedCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant*, WebViewTest* test)
55 {
56     g_main_loop_quit(test->m_mainLoop);
57 }
58
59 static void testDocumentLoadedSignal(WebViewTest* test, gconstpointer)
60 {
61     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
62     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
63         "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
64     GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
65     guint id = g_dbus_connection_signal_subscribe(connection,
66         0,
67         "org.webkit.gtk.WebExtensionTest",
68         "DocumentLoaded",
69         "/org/webkit/gtk/WebExtensionTest",
70         0,
71         G_DBUS_SIGNAL_FLAGS_NONE,
72         reinterpret_cast<GDBusSignalCallback>(documentLoadedCallback),
73         test,
74         0);
75     g_assert(id);
76
77     test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
78     g_main_loop_run(test->m_mainLoop);
79     g_dbus_connection_signal_unsubscribe(connection, id);
80 }
81
82 static gboolean webProcessCrashedCallback(WebKitWebView*, WebViewTest* test)
83 {
84     test->quitMainLoop();
85
86     return FALSE;
87 }
88
89 static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
90 {
91     test->loadHtml("<html></html>", 0);
92     test->waitUntilLoadFinished();
93
94     g_signal_connect_after(test->m_webView, "web-process-crashed",
95         G_CALLBACK(webProcessCrashedCallback), test);
96
97     test->m_expectedWebProcessCrash = true;
98
99     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
100     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
101         "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
102
103     GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
104         proxy.get(),
105         "AbortProcess",
106         0,
107         G_DBUS_CALL_FLAGS_NONE,
108         -1, 0, 0));
109     g_assert(!result);
110     g_main_loop_run(test->m_mainLoop);
111     test->m_expectedWebProcessCrash = false;
112 }
113
114 static void testWebExtensionWindowObjectCleared(WebViewTest* test, gconstpointer)
115 {
116     test->loadHtml("<html><header></header><body></body></html>", 0);
117     test->waitUntilLoadFinished();
118
119     GUniqueOutPtr<GError> error;
120     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.echo('Foo');", &error.outPtr());
121     g_assert(javascriptResult);
122     g_assert(!error.get());
123     GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
124     g_assert_cmpstr(valueString.get(), ==, "Foo");
125 }
126
127 static gboolean scriptDialogCallback(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
128 {
129     g_assert_cmpuint(webkit_script_dialog_get_dialog_type(dialog), ==, WEBKIT_SCRIPT_DIALOG_ALERT);
130     scriptDialogResult.reset(g_strdup(webkit_script_dialog_get_message(dialog)));
131     return TRUE;
132 }
133
134 static void runJavaScriptInIsolatedWorldFinishedCallback(GDBusProxy* proxy, GAsyncResult* result, WebViewTest* test)
135 {
136     g_dbus_proxy_call_finish(proxy, result, 0);
137     g_main_loop_quit(test->m_mainLoop);
138 }
139
140 static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
141 {
142     test->loadHtml("<html><header></header><body><div id='console'></div></body></html>", 0);
143     test->waitUntilLoadFinished();
144
145     gulong scriptDialogID = g_signal_connect(test->m_webView, "script-dialog", G_CALLBACK(scriptDialogCallback), nullptr);
146
147     static const char* mainWorldScript =
148         "top.foo = 'Foo';\n"
149         "document.getElementById('console').innerHTML = top.foo;\n"
150         "window.open = function () { alert('Main World'); }\n"
151         "document.open(1, 2, 3);";
152     test->runJavaScriptAndWaitUntilFinished(mainWorldScript, 0);
153     g_assert_cmpstr(scriptDialogResult.get(), ==, "Main World");
154
155     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
156     g_assert(javascriptResult);
157     GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
158     g_assert_cmpstr(valueString.get(), ==, "Foo");
159
160     static const char* isolatedWorldScript =
161         "document.getElementById('console').innerHTML = top.foo;\n"
162         "window.open = function () { alert('Isolated World'); }\n"
163         "document.open(1, 2, 3);";
164     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
165     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
166         "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
167     g_dbus_proxy_call(proxy.get(),
168         "RunJavaScriptInIsolatedWorld",
169         g_variant_new("(t&s)", webkit_web_view_get_page_id(test->m_webView), isolatedWorldScript),
170         G_DBUS_CALL_FLAGS_NONE,
171         -1, 0,
172         reinterpret_cast<GAsyncReadyCallback>(runJavaScriptInIsolatedWorldFinishedCallback),
173         test);
174     g_main_loop_run(test->m_mainLoop);
175     g_assert_cmpstr(scriptDialogResult.get(), ==, "Isolated World");
176
177     // Check that 'top.foo' defined in main world is not visible in isolated world.
178     javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
179     g_assert(javascriptResult);
180     valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
181     g_assert_cmpstr(valueString.get(), ==, "undefined");
182
183     g_signal_handler_disconnect(test->m_webView, scriptDialogID);
184 }
185
186 #if PLATFORM(GTK)
187 static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest* request, WebViewTest* test)
188 {
189     if (!WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request))
190         return FALSE;
191
192     test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
193     WebKitInstallMissingMediaPluginsPermissionRequest* missingPluginsRequest = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request);
194     g_assert(webkit_install_missing_media_plugins_permission_request_get_description(missingPluginsRequest));
195     webkit_permission_request_deny(request);
196     test->quitMainLoop();
197
198     return TRUE;
199 }
200
201 static void testInstallMissingPluginsPermissionRequest(WebViewTest* test, gconstpointer)
202 {
203     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
204     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
205         "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
206     GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(proxy.get(), "RemoveAVPluginsFromGSTRegistry",
207         nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr));
208
209     test->showInWindowAndWaitUntilMapped();
210
211     gulong permissionRequestSignalID = g_signal_connect(test->m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), test);
212     // FIXME: the base URI needs to finish with / to work, that shouldn't happen.
213     GUniquePtr<char> baseURI(g_strconcat("file://", Test::getResourcesDir(Test::WebKit2Resources).data(), "/", nullptr));
214     test->loadHtml("<html><body><video src=\"test.mp4\" autoplay></video></body></html>", baseURI.get());
215     g_main_loop_run(test->m_mainLoop);
216     g_signal_handler_disconnect(test->m_webView, permissionRequestSignalID);
217 }
218
219 static void didAssociateFormControlsCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebViewTest* test)
220 {
221     const char* formIds;
222     g_variant_get(result, "(&s)", &formIds);
223     g_assert(!g_strcmp0(formIds, FORM_ID FORM2_ID) || !g_strcmp0(formIds, INPUT_ID));
224
225     test->quitMainLoop();
226 }
227
228 static void testWebExtensionFormControlsAssociated(WebViewTest* test, gconstpointer)
229 {
230     GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
231     GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
232         "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
233     GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
234     guint id = g_dbus_connection_signal_subscribe(connection,
235         nullptr,
236         "org.webkit.gtk.WebExtensionTest",
237         "FormControlsAssociated",
238         "/org/webkit/gtk/WebExtensionTest",
239         nullptr,
240         G_DBUS_SIGNAL_FLAGS_NONE,
241         reinterpret_cast<GDBusSignalCallback>(didAssociateFormControlsCallback),
242         test,
243         nullptr);
244     g_assert(id);
245
246     test->loadHtml("<!DOCTYPE html><head><title>WebKitGTK+ Web Extensions Test</title></head><div id=\"placeholder\"/>", 0);
247     test->waitUntilLoadFinished();
248
249     static const char* addFormScript =
250         "var input = document.createElement(\"input\");"
251         "input.id = \"" INPUT_ID "\";"
252         "input.type = \"password\";"
253         "var form = document.createElement(\"form\");"
254         "form.id = \"" FORM_ID "\";"
255         "form.appendChild(input);"
256         "var form2 = document.createElement(\"form\");"
257         "form2.id = \"" FORM2_ID "\";"
258         "var placeholder = document.getElementById(\"placeholder\");"
259         "placeholder.appendChild(form);"
260         "placeholder.appendChild(form2);";
261
262     webkit_web_view_run_javascript(test->m_webView, addFormScript, nullptr, nullptr, nullptr);
263     g_main_loop_run(test->m_mainLoop);
264
265     static const char* moveFormElementScript =
266         "var form = document.getElementById(\"" FORM_ID "\");"
267         "var form2 = document.getElementById(\"" FORM2_ID "\");"
268         "var input = document.getElementById(\"" INPUT_ID "\");"
269         "form.removeChild(input);"
270         "form2.appendChild(input);";
271
272     webkit_web_view_run_javascript(test->m_webView, moveFormElementScript, nullptr, nullptr, nullptr);
273     g_main_loop_run(test->m_mainLoop);
274
275     g_dbus_connection_signal_unsubscribe(connection, id);
276 }
277 #endif // PLATFORM(GTK)
278
279 void beforeAll()
280 {
281     bus = new WebKitTestBus();
282     if (!bus->run())
283         return;
284
285     // FIXME: Use JSC API in the extension to get the title from JavaScript.
286 #if PLATFORM(GTK)
287     WebViewTest::add("WebKitWebExtension", "dom-document-title", testWebExtensionGetTitle);
288 #endif
289     WebViewTest::add("WebKitWebExtension", "document-loaded-signal", testDocumentLoadedSignal);
290     WebViewTest::add("WebKitWebView", "web-process-crashed", testWebKitWebViewProcessCrashed);
291     WebViewTest::add("WebKitWebExtension", "window-object-cleared", testWebExtensionWindowObjectCleared);
292     WebViewTest::add("WebKitWebExtension", "isolated-world", testWebExtensionIsolatedWorld);
293 #if PLATFORM(GTK)
294     WebViewTest::add("WebKitWebView", "install-missing-plugins-permission-request", testInstallMissingPluginsPermissionRequest);
295     WebViewTest::add("WebKitWebExtension", "form-controls-associated-signal", testWebExtensionFormControlsAssociated);
296 #endif
297 }
298
299 void afterAll()
300 {
301     delete bus;
302 }