blob: 28b634a751957a66c29c8136371007b22e55c5de [file] [log] [blame]
/*
* 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()
{
}