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
26static WebKitTestBus* bus;
27static GUniquePtr<char> scriptDialogResult;
28
29#define INPUT_ID "input-id"
30#define FORM_ID "form-id"
31#define FORM2_ID "form2-id"
32
33#define FORM_SUBMISSION_TEST_ID "form-submission-test-id"
34
35static void testWebExtensionGetTitle(WebViewTest* test, gconstpointer)
36{
37 test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
38 test->waitUntilLoadFinished();
39
40 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
41 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
42 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
43 GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
44 proxy.get(),
45 "GetTitle",
46 g_variant_new("(t)", webkit_web_view_get_page_id(test->m_webView)),
47 G_DBUS_CALL_FLAGS_NONE,
48 -1, 0, 0));
49 g_assert_nonnull(result);
50
51 const char* title;
52 g_variant_get(result.get(), "(&s)", &title);
53 g_assert_cmpstr(title, ==, "WebKitGTK+ Web Extensions Test");
54}
55
56#if PLATFORM(GTK)
57static gboolean inputElementIsUserEdited(GDBusProxy* proxy, uint64_t pageID, const char* elementID)
58{
59 GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
60 proxy,
61 "InputElementIsUserEdited",
62 g_variant_new("(t&s)", pageID, elementID),
63 G_DBUS_CALL_FLAGS_NONE,
64 -1, nullptr, nullptr));
65 g_assert_nonnull(result);
66
67 gboolean retval;
68 g_variant_get(result.get(), "(b)", &retval);
69 return retval;
70}
71
72static void testWebExtensionInputElementIsUserEdited(WebViewTest* test, gconstpointer)
73{
74 test->showInWindowAndWaitUntilMapped();
75 test->loadHtml("<html><body id='body'><input id='input'></input><textarea id='textarea'></textarea></body></html>", nullptr);
76 test->waitUntilLoadFinished();
77
78 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
79 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
80 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
81
82 uint64_t pageID = webkit_web_view_get_page_id(test->m_webView);
83 g_assert_false(inputElementIsUserEdited(proxy.get(), pageID, "input"));
84 test->runJavaScriptAndWaitUntilFinished("document.getElementById('input').focus()", nullptr);
85 test->keyStroke(GDK_KEY_a);
86 while (gtk_events_pending())
87 gtk_main_iteration();
88 GUniquePtr<char> resultString;
89 do {
90 auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('input').value", nullptr);
91 resultString.reset(WebViewTest::javascriptResultToCString(result));
92 } while (g_strcmp0(resultString.get(), "a"));
93 g_assert_true(inputElementIsUserEdited(proxy.get(), pageID, "input"));
94
95 g_assert_false(inputElementIsUserEdited(proxy.get(), pageID, "textarea"));
96 test->runJavaScriptAndWaitUntilFinished("document.getElementById('textarea').focus()", nullptr);
97 test->keyStroke(GDK_KEY_b);
98 while (gtk_events_pending())
99 gtk_main_iteration();
100 do {
101 auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('textarea').value", nullptr);
102 resultString.reset(WebViewTest::javascriptResultToCString(result));
103 } while (g_strcmp0(resultString.get(), "b"));
104 g_assert_true(inputElementIsUserEdited(proxy.get(), pageID, "textarea"));
105
106 g_assert_false(inputElementIsUserEdited(proxy.get(), pageID, "body"));
107}
108#endif
109
110static void documentLoadedCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant*, WebViewTest* test)
111{
112 g_main_loop_quit(test->m_mainLoop);
113}
114
115static void testDocumentLoadedSignal(WebViewTest* test, gconstpointer)
116{
117 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
118 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
119 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
120 GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
121 guint id = g_dbus_connection_signal_subscribe(connection,
122 0,
123 "org.webkit.gtk.WebExtensionTest",
124 "DocumentLoaded",
125 "/org/webkit/gtk/WebExtensionTest",
126 0,
127 G_DBUS_SIGNAL_FLAGS_NONE,
128 reinterpret_cast<GDBusSignalCallback>(documentLoadedCallback),
129 test,
130 0);
131 g_assert_cmpuint(id, !=, 0);
132
133 test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
134 g_main_loop_run(test->m_mainLoop);
135 g_dbus_connection_signal_unsubscribe(connection, id);
136}
137
138static gboolean webProcessTerminatedCallback(WebKitWebView*, WebKitWebProcessTerminationReason reason, WebViewTest* test)
139{
140 g_assert_cmpuint(reason, ==, WEBKIT_WEB_PROCESS_CRASHED);
141 test->quitMainLoop();
142
143 return FALSE;
144}
145
146static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
147{
148 test->loadHtml("<html></html>", 0);
149 test->waitUntilLoadFinished();
150
151 g_signal_connect_after(test->m_webView, "web-process-terminated",
152 G_CALLBACK(webProcessTerminatedCallback), test);
153
154 test->m_expectedWebProcessCrash = true;
155
156 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
157 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
158 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
159
160 GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
161 proxy.get(),
162 "AbortProcess",
163 0,
164 G_DBUS_CALL_FLAGS_NONE,
165 -1, 0, 0));
166 g_assert_null(result);
167 g_main_loop_run(test->m_mainLoop);
168 test->m_expectedWebProcessCrash = false;
169}
170
171static void testWebExtensionWindowObjectCleared(WebViewTest* test, gconstpointer)
172{
173 test->loadHtml("<html><header></header><body></body></html>", 0);
174 test->waitUntilLoadFinished();
175
176 GUniqueOutPtr<GError> error;
177 WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.echo('Foo');", &error.outPtr());
178 g_assert_nonnull(javascriptResult);
179 g_assert_no_error(error.get());
180 GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
181 g_assert_cmpstr(valueString.get(), ==, "Foo");
182}
183
184static gboolean scriptDialogCallback(WebKitWebView*, WebKitScriptDialog* dialog, gpointer)
185{
186 g_assert_cmpuint(webkit_script_dialog_get_dialog_type(dialog), ==, WEBKIT_SCRIPT_DIALOG_ALERT);
187 scriptDialogResult.reset(g_strdup(webkit_script_dialog_get_message(dialog)));
188 return TRUE;
189}
190
191static void runJavaScriptInIsolatedWorldFinishedCallback(GDBusProxy* proxy, GAsyncResult* result, WebViewTest* test)
192{
193 g_dbus_proxy_call_finish(proxy, result, 0);
194 g_main_loop_quit(test->m_mainLoop);
195}
196
197static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
198{
199 test->loadHtml("<html><header></header><body><div id='console'></div></body></html>", 0);
200 test->waitUntilLoadFinished();
201
202 gulong scriptDialogID = g_signal_connect(test->m_webView, "script-dialog", G_CALLBACK(scriptDialogCallback), nullptr);
203
204 static const char* mainWorldScript =
205 "top.foo = 'Foo';\n"
206 "document.getElementById('console').innerHTML = top.foo;\n"
207 "window.open = function () { alert('Main World'); }\n"
208 "window.open();";
209 test->runJavaScriptAndWaitUntilFinished(mainWorldScript, 0);
210 g_assert_cmpstr(scriptDialogResult.get(), ==, "Main World");
211
212 WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
213 g_assert_nonnull(javascriptResult);
214 GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
215 g_assert_cmpstr(valueString.get(), ==, "Foo");
216
217 static const char* isolatedWorldScript =
218 "document.getElementById('console').innerHTML = top.foo;\n"
219 "window.open = function () { alert('Isolated World'); }\n"
220 "window.open();";
221 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
222 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
223 "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
224 g_dbus_proxy_call(proxy.get(),
225 "RunJavaScriptInIsolatedWorld",
226 g_variant_new("(t&s)", webkit_web_view_get_page_id(test->m_webView), isolatedWorldScript),
227 G_DBUS_CALL_FLAGS_NONE,
228 -1, 0,
229 reinterpret_cast<GAsyncReadyCallback>(runJavaScriptInIsolatedWorldFinishedCallback),
230 test);
231 g_main_loop_run(test->m_mainLoop);
232 g_assert_cmpstr(scriptDialogResult.get(), ==, "Isolated World");
233
234 // Check that 'top.foo' defined in main world is not visible in isolated world.
235 javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementById('console').innerHTML", 0);
236 g_assert_nonnull(javascriptResult);
237 valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
238 g_assert_cmpstr(valueString.get(), ==, "undefined");
239
240 g_signal_handler_disconnect(test->m_webView, scriptDialogID);
241}
242
243#if PLATFORM(GTK)
244static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest* request, WebViewTest* test)
245{
246 if (!WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request))
247 return FALSE;
248
249 test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
250 WebKitInstallMissingMediaPluginsPermissionRequest* missingPluginsRequest = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request);
251 g_assert_nonnull(webkit_install_missing_media_plugins_permission_request_get_description(missingPluginsRequest));
252 webkit_permission_request_deny(request);
253 test->quitMainLoop();
254
255 return TRUE;
256}
257
258static void testInstallMissingPluginsPermissionRequest(WebViewTest* test, gconstpointer)
259{
260 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
261 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
262 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
263 GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(proxy.get(), "RemoveAVPluginsFromGSTRegistry",
264 nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr));
265
266 test->showInWindowAndWaitUntilMapped();
267
268 gulong permissionRequestSignalID = g_signal_connect(test->m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), test);
269 // FIXME: the base URI needs to finish with / to work, that shouldn't happen.
270 GUniquePtr<char> baseURI(g_strconcat("file://", Test::getResourcesDir(Test::WebKit2Resources).data(), "/", nullptr));
271 test->loadHtml("<html><body><video src=\"test.mp4\" autoplay></video></body></html>", baseURI.get());
272 g_main_loop_run(test->m_mainLoop);
273 g_signal_handler_disconnect(test->m_webView, permissionRequestSignalID);
274}
275#endif // PLATFORM(GTK)
276
277static void didAssociateFormControlsCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebViewTest* test)
278{
279 const char* formIds;
280 g_variant_get(result, "(&s)", &formIds);
281 g_assert_true(!g_strcmp0(formIds, FORM_ID FORM2_ID) || !g_strcmp0(formIds, FORM2_ID FORM_ID) || !g_strcmp0(formIds, INPUT_ID));
282
283 test->quitMainLoop();
284}
285
286static void testWebExtensionFormControlsAssociated(WebViewTest* test, gconstpointer)
287{
288 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
289 GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
290 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
291 GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
292 guint id = g_dbus_connection_signal_subscribe(connection,
293 nullptr,
294 "org.webkit.gtk.WebExtensionTest",
295 "FormControlsAssociated",
296 "/org/webkit/gtk/WebExtensionTest",
297 nullptr,
298 G_DBUS_SIGNAL_FLAGS_NONE,
299 reinterpret_cast<GDBusSignalCallback>(didAssociateFormControlsCallback),
300 test,
301 nullptr);
302 g_assert_cmpuint(id, !=, 0);
303
304 test->loadHtml("<!DOCTYPE html><head><title>WebKitGTK+ Web Extensions Test</title></head><div id=\"placeholder\"/>", 0);
305 test->waitUntilLoadFinished();
306
307 static const char* addFormScript =
308 "var input = document.createElement(\"input\");"
309 "input.id = \"" INPUT_ID "\";"
310 "input.type = \"password\";"
311 "var form = document.createElement(\"form\");"
312 "form.id = \"" FORM_ID "\";"
313 "form.appendChild(input);"
314 "var form2 = document.createElement(\"form\");"
315 "form2.id = \"" FORM2_ID "\";"
316 "var placeholder = document.getElementById(\"placeholder\");"
317 "placeholder.appendChild(form);"
318 "placeholder.appendChild(form2);";
319
320 webkit_web_view_run_javascript(test->m_webView, addFormScript, nullptr, nullptr, nullptr);
321 g_main_loop_run(test->m_mainLoop);
322
323 static const char* moveFormElementScript =
324 "var form = document.getElementById(\"" FORM_ID "\");"
325 "var form2 = document.getElementById(\"" FORM2_ID "\");"
326 "var input = document.getElementById(\"" INPUT_ID "\");"
327 "form.removeChild(input);"
328 "form2.appendChild(input);";
329
330 webkit_web_view_run_javascript(test->m_webView, moveFormElementScript, nullptr, nullptr, nullptr);
331 g_main_loop_run(test->m_mainLoop);
332
333 g_dbus_connection_signal_unsubscribe(connection, id);
334}
335
336class FormSubmissionTest : public WebViewTest {
337public:
338 MAKE_GLIB_TEST_FIXTURE(FormSubmissionTest);
339
340 FormSubmissionTest()
341 {
342 GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", s_webExtensionID));
343 m_proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
344 "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", m_mainLoop));
345 GDBusConnection* connection = g_dbus_proxy_get_connection(m_proxy.get());
346
347 m_willSendDOMEventCallbackID = g_dbus_connection_signal_subscribe(connection,
348 nullptr,
349 "org.webkit.gtk.WebExtensionTest",
350 "FormSubmissionWillSendDOMEvent",
351 "/org/webkit/gtk/WebExtensionTest",
352 nullptr,
353 G_DBUS_SIGNAL_FLAGS_NONE,
354 reinterpret_cast<GDBusSignalCallback>(willSendDOMEventCallback),
355 this,
356 nullptr);
357 g_assert_cmpuint(m_willSendDOMEventCallbackID, !=, 0);
358
359 m_willCompleteCallbackID = g_dbus_connection_signal_subscribe(connection,
360 nullptr,
361 "org.webkit.gtk.WebExtensionTest",
362 "FormSubmissionWillComplete",
363 "/org/webkit/gtk/WebExtensionTest",
364 nullptr,
365 G_DBUS_SIGNAL_FLAGS_NONE,
366 reinterpret_cast<GDBusSignalCallback>(willCompleteCallback),
367 this,
368 nullptr);
369 g_assert_cmpuint(m_willCompleteCallbackID, !=, 0);
370 }
371
372 ~FormSubmissionTest()
373 {
374 GDBusConnection* connection = g_dbus_proxy_get_connection(m_proxy.get());
375 g_dbus_connection_signal_unsubscribe(connection, m_willSendDOMEventCallbackID);
376 g_dbus_connection_signal_unsubscribe(connection, m_willCompleteCallbackID);
377 }
378
379 static void testFormSubmissionResult(GVariant* result)
380 {
381 const char* formID;
382 const char* concatenatedTextFieldNames;
383 const char* concatenatedTextFieldValues;
384 gboolean targetFrameIsMainFrame;
385 gboolean sourceFrameIsMainFrame;
386 g_variant_get(result, "(&s&s&sbb)", &formID, &concatenatedTextFieldNames, &concatenatedTextFieldValues, &targetFrameIsMainFrame, &sourceFrameIsMainFrame);
387
388 g_assert_cmpstr(formID, ==, FORM_SUBMISSION_TEST_ID);
389 g_assert_cmpstr(concatenatedTextFieldNames, ==, "foo,bar,");
390 g_assert_cmpstr(concatenatedTextFieldValues, ==, "first,second,");
391 g_assert_false(targetFrameIsMainFrame);
392 g_assert_true(sourceFrameIsMainFrame);
393 }
394
395 static void willSendDOMEventCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, FormSubmissionTest* test)
396 {
397 test->m_willSendDOMEventCallbackExecuted = true;
398 testFormSubmissionResult(result);
399 }
400
401 static void willCompleteCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, FormSubmissionTest* test)
402 {
403 test->m_willCompleteCallbackExecuted = true;
404 testFormSubmissionResult(result);
405 test->quitMainLoop();
406 }
407
408 void runJavaScriptAndWaitUntilFormSubmitted(const char* js)
409 {
410 webkit_web_view_run_javascript(m_webView, js, nullptr, nullptr, nullptr);
411 g_main_loop_run(m_mainLoop);
412 }
413
414 GRefPtr<GDBusProxy> m_proxy;
415 guint m_willSendDOMEventCallbackID { 0 };
416 guint m_willCompleteCallbackID { 0 };
417 bool m_willSendDOMEventCallbackExecuted { false };
418 bool m_willCompleteCallbackExecuted { false };
419};
420
421static void testWebExtensionFormSubmissionSteps(FormSubmissionTest* test, gconstpointer)
422{
423 test->loadHtml("<form id=\"" FORM_SUBMISSION_TEST_ID "\" target=\"target_frame\">"
424 "<input type=\"text\" name=\"foo\" value=\"first\">"
425 "<input type=\"text\" name=\"bar\" value=\"second\">"
426 "<input type=\"submit\" id=\"submit_button\">"
427 "</form>"
428 "<iframe name=\"target_frame\"></iframe>", nullptr);
429 test->waitUntilLoadFinished();
430
431 static const char* submitFormScript =
432 "var form = document.getElementById(\"" FORM_SUBMISSION_TEST_ID "\");"
433 "form.submit();";
434 test->runJavaScriptAndWaitUntilFormSubmitted(submitFormScript);
435 // Submit must not be emitted when the form is submitted via JS.
436 // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
437 g_assert_false(test->m_willSendDOMEventCallbackExecuted);
438 g_assert_true(test->m_willCompleteCallbackExecuted);
439 test->m_willCompleteCallbackExecuted = false;
440
441 static const char* manuallySubmitFormScript =
442 "var button = document.getElementById(\"submit_button\");"
443 "button.click();";
444 test->runJavaScriptAndWaitUntilFormSubmitted(manuallySubmitFormScript);
445 g_assert_true(test->m_willSendDOMEventCallbackExecuted);
446 g_assert_true(test->m_willCompleteCallbackExecuted);
447 test->m_willSendDOMEventCallbackExecuted = false;
448 test->m_willCompleteCallbackExecuted = false;
449
450 test->loadHtml("<form id=\"" FORM_SUBMISSION_TEST_ID "\" target=\"target_frame\">"
451 "</form>"
452 "<iframe name=\"target_frame\"></iframe>", nullptr);
453 test->waitUntilLoadFinished();
454}
455
456void beforeAll()
457{
458 bus = new WebKitTestBus();
459 if (!bus->run())
460 return;
461
462 WebViewTest::add("WebKitWebExtension", "dom-document-title", testWebExtensionGetTitle);
463#if PLATFORM(GTK)
464 WebViewTest::add("WebKitWebExtension", "dom-input-element-is-user-edited", testWebExtensionInputElementIsUserEdited);
465#endif
466 WebViewTest::add("WebKitWebExtension", "document-loaded-signal", testDocumentLoadedSignal);
467 WebViewTest::add("WebKitWebView", "web-process-crashed", testWebKitWebViewProcessCrashed);
468 WebViewTest::add("WebKitWebExtension", "window-object-cleared", testWebExtensionWindowObjectCleared);
469 WebViewTest::add("WebKitWebExtension", "isolated-world", testWebExtensionIsolatedWorld);
470#if PLATFORM(GTK)
471 WebViewTest::add("WebKitWebView", "install-missing-plugins-permission-request", testInstallMissingPluginsPermissionRequest);
472#endif
473 WebViewTest::add("WebKitWebExtension", "form-controls-associated-signal", testWebExtensionFormControlsAssociated);
474 FormSubmissionTest::add("WebKitWebExtension", "form-submission-steps", testWebExtensionFormSubmissionSteps);
475}
476
477void afterAll()
478{
479 delete bus;
480}
481