1 | /* |
2 | * Copyright (C) 2017 Igalia S.L. |
3 | * Copyright (C) 2012 Samsung Electronics Ltd. All Rights Reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * |
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR |
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | |
28 | #include "WebViewTest.h" |
29 | #include <wtf/glib/GRefPtr.h> |
30 | #include <wtf/text/WTFString.h> |
31 | |
32 | static GPid gChildProcessPid; |
33 | static bool gServerIsReady; |
34 | |
35 | static void stopTestServer() |
36 | { |
37 | // Do nothing if there's no server running. |
38 | if (!gChildProcessPid) |
39 | return; |
40 | |
41 | g_spawn_close_pid(gChildProcessPid); |
42 | kill(gChildProcessPid, SIGTERM); |
43 | gChildProcessPid = 0; |
44 | } |
45 | |
46 | static void sigAbortHandler(int sigNum) |
47 | { |
48 | // Just stop the test server if SIGABRT was received. |
49 | stopTestServer(); |
50 | } |
51 | |
52 | static void connectToInspectorServer(GMainLoop* mainLoop) |
53 | { |
54 | g_dbus_connection_new_for_address("tcp:host=127.0.0.1,port=2999" , G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, nullptr, nullptr, |
55 | [](GObject* , GAsyncResult* result, gpointer userData) { |
56 | auto* mainLoop = static_cast<GMainLoop*>(userData); |
57 | GUniqueOutPtr<GError> error; |
58 | GRefPtr<GDBusConnection> connection = adoptGRef(g_dbus_connection_new_for_address_finish(result, &error.outPtr())); |
59 | if (!connection) { |
60 | if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { |
61 | g_timeout_add(100, [](gpointer userData) { |
62 | connectToInspectorServer(static_cast<GMainLoop*>(userData)); |
63 | return G_SOURCE_REMOVE; |
64 | }, userData); |
65 | return; |
66 | } |
67 | |
68 | g_printerr("Failed to connect to inspector server" ); |
69 | g_assert_not_reached(); |
70 | } |
71 | gServerIsReady = true; |
72 | g_main_loop_quit(mainLoop); |
73 | }, mainLoop); |
74 | } |
75 | |
76 | static void waitUntilInspectorServerIsReady() |
77 | { |
78 | GRefPtr<GMainLoop> mainLoop = adoptGRef(g_main_loop_new(nullptr, FALSE)); |
79 | unsigned timeoutID = g_timeout_add(25000, [](gpointer userData) { |
80 | g_main_loop_quit(static_cast<GMainLoop*>(userData)); |
81 | return G_SOURCE_REMOVE; |
82 | }, mainLoop.get()); |
83 | connectToInspectorServer(mainLoop.get()); |
84 | g_main_loop_run(mainLoop.get()); |
85 | if (gServerIsReady) |
86 | g_source_remove(timeoutID); |
87 | } |
88 | |
89 | static void startTestServer() |
90 | { |
91 | // Prepare argv[] for spawning the server process. |
92 | GUniquePtr<char> testServerPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI" , "WebKit2Gtk" , "InspectorTestServer" , nullptr)); |
93 | |
94 | // We install a handler to ensure that we kill the child process |
95 | // if the parent dies because of whatever the reason is. |
96 | signal(SIGABRT, sigAbortHandler); |
97 | |
98 | char* testServerArgv[2]; |
99 | testServerArgv[0] = testServerPath.get(); |
100 | testServerArgv[1] = nullptr; |
101 | |
102 | g_assert_true(g_spawn_async(nullptr, testServerArgv, nullptr, G_SPAWN_DEFAULT, nullptr, nullptr, &gChildProcessPid, nullptr)); |
103 | |
104 | waitUntilInspectorServerIsReady(); |
105 | if (!gServerIsReady) |
106 | stopTestServer(); |
107 | } |
108 | |
109 | class InspectorServerTest: public WebViewTest { |
110 | public: |
111 | MAKE_GLIB_TEST_FIXTURE(InspectorServerTest); |
112 | |
113 | bool getPageList() |
114 | { |
115 | loadURI("inspector://127.0.0.1:2999" ); |
116 | waitUntilLoadFinished(); |
117 | for (unsigned i = 0; i < 5; ++i) { |
118 | size_t mainResourceDataSize = 0; |
119 | const char* mainResourceData = this->mainResourceData(mainResourceDataSize); |
120 | g_assert_nonnull(mainResourceData); |
121 | if (g_strrstr_len(mainResourceData, mainResourceDataSize, "No targets found" )) |
122 | wait(0.1); |
123 | else if (g_strrstr_len(mainResourceData, mainResourceDataSize, "Inspectable targets" )) |
124 | return true; |
125 | } |
126 | |
127 | return false; |
128 | } |
129 | }; |
130 | |
131 | // Test to get inspector server page list from the test server. |
132 | // Should contain only one entry pointing to http://127.0.0.1:2999. |
133 | static void testInspectorServerPageList(InspectorServerTest* test, gconstpointer) |
134 | { |
135 | GUniqueOutPtr<GError> error; |
136 | |
137 | test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL); |
138 | g_assert_true(test->getPageList()); |
139 | |
140 | WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targetname').length;" , &error.outPtr()); |
141 | g_assert_nonnull(javascriptResult); |
142 | g_assert_no_error(error.get()); |
143 | g_assert_cmpint(WebViewTest::javascriptResultToNumber(javascriptResult), ==, 1); |
144 | |
145 | GUniquePtr<char> valueString; |
146 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByClassName('targeturl')[0].innerText;" , &error.outPtr()); |
147 | g_assert_nonnull(javascriptResult); |
148 | g_assert_no_error(error.get()); |
149 | valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
150 | g_assert_cmpstr(valueString.get(), ==, "http://127.0.0.1:2999/" ); |
151 | } |
152 | |
153 | void beforeAll() |
154 | { |
155 | startTestServer(); |
156 | InspectorServerTest::add("WebKitWebInspectorServer" , "test-page-list" , testInspectorServerPageList); |
157 | } |
158 | |
159 | void afterAll() |
160 | { |
161 | stopTestServer(); |
162 | } |
163 | |