| /* |
| * Copyright (C) 2017 Igalia S.L. |
| * Copyright (C) 2012 Samsung Electronics Ltd. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| |
| #include "WebViewTest.h" |
| #include <signal.h> |
| #include <sys/eventfd.h> |
| #include <wtf/glib/GRefPtr.h> |
| #include <wtf/glib/GUniquePtr.h> |
| #include <wtf/text/WTFString.h> |
| |
| static GPid gActiveServerPid; |
| static const unsigned gMaxConnectionTries = 10; |
| |
| class InspectorServerTest: public WebViewTest { |
| public: |
| MAKE_GLIB_TEST_FIXTURE(InspectorServerTest); |
| |
| InspectorServerTest() |
| { |
| startTestServer(); |
| g_assert_cmpuint(m_connectionTryCount, <, gMaxConnectionTries); |
| } |
| |
| ~InspectorServerTest() |
| { |
| stopTestServer(); |
| } |
| |
| void connectToInspectorServer() |
| { |
| if (++m_connectionTryCount == gMaxConnectionTries) { |
| g_main_loop_quit(m_mainLoop); |
| return; |
| } |
| |
| GRefPtr<GSocketClient> socketClient = adoptGRef(g_socket_client_new()); |
| g_socket_client_connect_to_host_async(socketClient.get(), "127.0.0.1:2999", 0, nullptr, [](GObject* client, GAsyncResult* result, gpointer userData) { |
| auto* test = static_cast<InspectorServerTest*>(userData); |
| GUniqueOutPtr<GError> error; |
| GRefPtr<GSocketConnection> connection = adoptGRef(g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(client), result, &error.outPtr())); |
| if (!connection) { |
| if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { |
| g_timeout_add(100, [](gpointer userData) { |
| static_cast<InspectorServerTest*>(userData)->connectToInspectorServer(); |
| return G_SOURCE_REMOVE; |
| }, userData); |
| return; |
| } |
| |
| g_printerr("Failed to connect to inspector server\n"); |
| g_assert_not_reached(); |
| } |
| g_main_loop_quit(test->m_mainLoop); |
| }, this); |
| } |
| |
| void startTestServer() |
| { |
| // Prepare argv[] for spawning the server process. |
| GUniquePtr<char> testServerPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "InspectorTestServer", nullptr)); |
| |
| int eventFD = eventfd(0, 0); |
| g_assert_cmpint(eventFD, !=, -1); |
| GUniquePtr<gchar> eventFDString(g_strdup_printf("%d", eventFD)); |
| |
| char* testServerArgv[3]; |
| testServerArgv[0] = testServerPath.get(); |
| testServerArgv[1] = eventFDString.get(); |
| testServerArgv[2] = nullptr; |
| |
| GUniquePtr<char*> testServerEnvp(g_environ_setenv(g_get_environ(), shouldStartHTTPServer ? "WEBKIT_INSPECTOR_HTTP_SERVER" : "WEBKIT_INSPECTOR_SERVER", "127.0.0.1:2999", TRUE)); |
| |
| g_assert_true(g_spawn_async(nullptr, testServerArgv, testServerEnvp.get(), G_SPAWN_LEAVE_DESCRIPTORS_OPEN, nullptr, nullptr, &m_serverPid, nullptr)); |
| |
| gActiveServerPid = m_serverPid; |
| |
| // Wait for the page to load. |
| uint64_t event; |
| auto result = read(eventFD, &event, sizeof(uint64_t)); |
| g_assert_cmpint(result, ==, sizeof(uint64_t)); |
| close(eventFD); |
| |
| // Wait until server is ready. |
| connectToInspectorServer(); |
| g_main_loop_run(m_mainLoop); |
| if (m_connectionTryCount == gMaxConnectionTries) |
| stopTestServer(); |
| } |
| |
| void stopTestServer() |
| { |
| // Do nothing if there's no server running. |
| if (!m_serverPid) |
| return; |
| |
| g_spawn_close_pid(m_serverPid); |
| kill(m_serverPid, SIGTERM); |
| m_serverPid = 0; |
| gActiveServerPid = 0; |
| } |
| |
| bool loadTargetListPageAndWaitUntilFinished() |
| { |
| loadURI(shouldStartHTTPServer ? "http://127.0.0.1:2999/" : "inspector://127.0.0.1:2999"); |
| waitUntilLoadFinished(); |
| |
| for (unsigned i = 0; i < 5; ++i) { |
| size_t mainResourceDataSize = 0; |
| const char* mainResourceData = this->mainResourceData(mainResourceDataSize); |
| g_assert_nonnull(mainResourceData); |
| if (g_strrstr_len(mainResourceData, mainResourceDataSize, "No targets found")) { |
| webkit_web_view_reload(m_webView); |
| waitUntilLoadFinished(); |
| continue; |
| } |
| |
| if (g_strrstr_len(mainResourceData, mainResourceDataSize, "Inspectable targets")) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| GPid m_serverPid { 0 }; |
| unsigned m_connectionTryCount { 0 }; |
| static bool shouldStartHTTPServer; |
| }; |
| |
| bool InspectorServerTest::shouldStartHTTPServer = false; |
| |
| class InspectorHTTPServerTest : public InspectorServerTest { |
| public: |
| MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(InspectorHTTPServerTest, setup, teardown); |
| |
| static void setup() |
| { |
| InspectorServerTest::shouldStartHTTPServer = true; |
| } |
| |
| static void teardown() |
| { |
| InspectorServerTest::shouldStartHTTPServer = false; |
| } |
| }; |
| |
| // Test to get inspector server page list from the test server. |
| // Should contain only one entry pointing to http://127.0.0.1:2999. |
| static void testInspectorServerPageList(InspectorServerTest* test, gconstpointer) |
| { |
| test->showInWindow(); |
| g_assert_true(test->loadTargetListPageAndWaitUntilFinished()); |
| |
| GUniqueOutPtr<GError> error; |
| WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targetname').length;", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 1); |
| |
| GUniquePtr<char> valueString; |
| javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targeturl')[0].innerText;", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
| g_assert_cmpstr(valueString.get(), ==, "http://127.0.0.1:2999/"); |
| |
| javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('input')[0].onclick.toString();", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
| g_assert_nonnull(g_strrstr(valueString.get(), "window.webkit.messageHandlers.inspector.postMessage('1:1:WebPage');")); |
| } |
| |
| // Test to get inspector server page list from the HTTP test server. |
| // Should contain only one entry pointing to http://127.0.0.1:2999. |
| static void testInspectorHTTPServerPageList(InspectorHTTPServerTest* test, gconstpointer) |
| { |
| test->showInWindow(); |
| g_assert_true(test->loadTargetListPageAndWaitUntilFinished()); |
| |
| GUniqueOutPtr<GError> error; |
| WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targetname').length;", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 1); |
| |
| GUniquePtr<char> valueString; |
| javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targeturl')[0].innerText;", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
| g_assert_cmpstr(valueString.get(), ==, "http://127.0.0.1:2999/"); |
| |
| javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('input')[0].onclick.toString();", &error.outPtr()); |
| g_assert_nonnull(javascriptResult); |
| g_assert_no_error(error.get()); |
| valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
| g_assert_nonnull(g_strrstr(valueString.get(), "window.open('Main.html?ws=' + window.location.host + '/socket/1/1/WebPage', '_blank', 'location=no,menubar=no,status=no,toolbar=no');")); |
| } |
| |
| void beforeAll() |
| { |
| // Terminate the server process if any test fails. |
| signal(SIGABRT, +[](int) { |
| kill(gActiveServerPid, SIGTERM); |
| }); |
| |
| InspectorServerTest::add("WebKitWebInspectorServer", "test-page-list", testInspectorServerPageList); |
| InspectorHTTPServerTest::add("WebKitWebInspectorServer", "http-test-page-list", testInspectorHTTPServerPageList); |
| } |
| |
| void afterAll() |
| { |
| } |