| 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 | #define FORM_SUBMISSION_TEST_ID "form-submission-test-id" |
| 34 | |
| 35 | static 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) |
| 57 | static 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 | |
| 72 | static 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 | |
| 110 | static 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 | |
| 115 | static 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 | |
| 138 | static 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 | |
| 146 | static 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 | |
| 171 | static 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 | |
| 184 | static 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 | |
| 191 | static 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 | |
| 197 | static 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) |
| 244 | static 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 | |
| 258 | static 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 | |
| 277 | static 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 | |
| 286 | static 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 | |
| 336 | class FormSubmissionTest : public WebViewTest { |
| 337 | public: |
| 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 | |
| 421 | static 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 | |
| 456 | void 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 | |
| 477 | void afterAll() |
| 478 | { |
| 479 | delete bus; |
| 480 | } |
| 481 | |