1 | /* |
2 | * Copyright (C) 2013-2014 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 "WebKitTestServer.h" |
23 | #include "WebViewTest.h" |
24 | #include <cstdarg> |
25 | #include <wtf/glib/GRefPtr.h> |
26 | #include <wtf/glib/GUniquePtr.h> |
27 | |
28 | static WebKitTestServer* kServer; |
29 | |
30 | // These are all here so that they can be changed easily, if necessary. |
31 | static const char* kTestHTML = |
32 | "<html>\n" |
33 | " <head><link rel=\"stylesheet\" type=\"text/css\" href=\"/extra.css\"></head>\n" |
34 | " <body>\n" |
35 | " <div id=\"styledElement\">Sweet stylez!</div>\n" |
36 | " <div id=\"otherElement\">Blocked stylez!</div>\n" |
37 | " </body>\n" |
38 | "</html>" ; |
39 | |
40 | static const char* kTestCSS = |
41 | "div#otherElement {\n" |
42 | " font-weight: bold;\n" |
43 | "}\n" ; |
44 | |
45 | static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }" ; |
46 | static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']" ; |
47 | static const char* kStyleSheetTestScriptResult = "bold" ; |
48 | static const char* kInjectedScript = "document.write('<div id=\"item\">Generated by a script</div>')" ; |
49 | static const char* kScriptTestScript = "document.getElementById('item').innerText" ; |
50 | static const char* kScriptTestScriptResult = "Generated by a script" ; |
51 | static const char* kScriptTestCSSBlocked = "getComputedStyle(document.getElementById('otherElement'))['font-weight']" ; |
52 | static const char* kScriptTestCSSBlockedResult = "normal" ; |
53 | static const char* kJSONFilter = |
54 | "[\n" |
55 | " {\n" |
56 | " \"trigger\": {\n" |
57 | " \"url-filter\": \".*\",\n" |
58 | " \"resource-type\": [\"style-sheet\"]\n" |
59 | " },\n" |
60 | " \"action\": {\n" |
61 | " \"type\": \"block\"\n" |
62 | " }\n" |
63 | " }\n" |
64 | "]\n" ; |
65 | |
66 | static void testWebViewNewWithUserContentManager(Test* test, gconstpointer) |
67 | { |
68 | GRefPtr<WebKitUserContentManager> userContentManager1 = adoptGRef(webkit_user_content_manager_new()); |
69 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(userContentManager1.get())); |
70 | auto webView1 = Test::adoptView(Test::createWebView(userContentManager1.get())); |
71 | g_assert_true(webkit_web_view_get_user_content_manager(webView1.get()) == userContentManager1.get()); |
72 | |
73 | auto webView2 = Test::adoptView(Test::createWebView()); |
74 | g_assert_true(webkit_web_view_get_user_content_manager(webView2.get()) != userContentManager1.get()); |
75 | } |
76 | |
77 | static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path, const char* world = nullptr) |
78 | { |
79 | test->loadURI(kServer->getURIForPath(path).data()); |
80 | test->waitUntilLoadFinished(); |
81 | |
82 | GUniqueOutPtr<GError> error; |
83 | WebKitJavascriptResult* javascriptResult = world ? test->runJavaScriptInWorldAndWaitUntilFinished(kStyleSheetTestScript, world, &error.outPtr()) |
84 | : test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr()); |
85 | g_assert_nonnull(javascriptResult); |
86 | g_assert_no_error(error.get()); |
87 | |
88 | GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult)); |
89 | return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult); |
90 | } |
91 | |
92 | static bool isScriptInjectedForURLAtPath(WebViewTest* test, const char* path, const char* world = nullptr) |
93 | { |
94 | test->loadURI(kServer->getURIForPath(path).data()); |
95 | test->waitUntilLoadFinished(); |
96 | |
97 | GUniqueOutPtr<GError> error; |
98 | WebKitJavascriptResult* javascriptResult = world ? test->runJavaScriptInWorldAndWaitUntilFinished(kScriptTestScript, world, &error.outPtr()) |
99 | : test->runJavaScriptAndWaitUntilFinished(kScriptTestScript, &error.outPtr()); |
100 | if (javascriptResult) { |
101 | g_assert_no_error(error.get()); |
102 | |
103 | GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult)); |
104 | return !g_strcmp0(resultString.get(), kScriptTestScriptResult); |
105 | } |
106 | return false; |
107 | } |
108 | |
109 | static void fillURLListFromPaths(char** list, const char* path, ...) |
110 | { |
111 | va_list argumentList; |
112 | va_start(argumentList, path); |
113 | |
114 | int i = 0; |
115 | while (path) { |
116 | // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed. |
117 | // Until that time patterns with port numbers in them will not properly match URLs with port numbers. |
118 | list[i++] = g_strdup_printf("http://*/%s*" , path); |
119 | path = va_arg(argumentList, const char*); |
120 | } |
121 | } |
122 | |
123 | static void removeOldInjectedContentAndResetLists(WebKitUserContentManager* userContentManager, char** whitelist, char** blacklist) |
124 | { |
125 | webkit_user_content_manager_remove_all_style_sheets(userContentManager); |
126 | webkit_user_content_manager_remove_all_scripts(userContentManager); |
127 | webkit_user_content_manager_remove_all_filters(userContentManager); |
128 | |
129 | while (*whitelist) { |
130 | g_free(*whitelist); |
131 | *whitelist = 0; |
132 | whitelist++; |
133 | } |
134 | |
135 | while (*blacklist) { |
136 | g_free(*blacklist); |
137 | *blacklist = 0; |
138 | blacklist++; |
139 | } |
140 | } |
141 | |
142 | static void testUserContentManagerInjectedStyleSheet(WebViewTest* test, gconstpointer) |
143 | { |
144 | char* whitelist[3] = { 0, 0, 0 }; |
145 | char* blacklist[3] = { 0, 0, 0 }; |
146 | |
147 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
148 | |
149 | // Without a whitelist or a blacklist all URLs should have the injected style sheet. |
150 | static const char* randomPath = "somerandompath" ; |
151 | g_assert_false(isStyleSheetInjectedForURLAtPath(test, randomPath)); |
152 | WebKitUserStyleSheet* styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, nullptr); |
153 | webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); |
154 | webkit_user_style_sheet_unref(styleSheet); |
155 | g_assert_true(isStyleSheetInjectedForURLAtPath(test, randomPath)); |
156 | |
157 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
158 | |
159 | g_assert_false(isStyleSheetInjectedForURLAtPath(test, randomPath, "WebExtensionTestScriptWorld" )); |
160 | styleSheet = webkit_user_style_sheet_new_for_world(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, "WebExtensionTestScriptWorld" , nullptr, nullptr); |
161 | webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); |
162 | webkit_user_style_sheet_unref(styleSheet); |
163 | g_assert_true(isStyleSheetInjectedForURLAtPath(test, randomPath, "WebExtensionTestScriptWorld" )); |
164 | |
165 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
166 | |
167 | fillURLListFromPaths(blacklist, randomPath, 0); |
168 | styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, blacklist); |
169 | webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); |
170 | webkit_user_style_sheet_unref(styleSheet); |
171 | g_assert_false(isStyleSheetInjectedForURLAtPath(test, randomPath)); |
172 | g_assert_true(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath" )); |
173 | |
174 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
175 | |
176 | static const char* inTheWhiteList = "inthewhitelist" ; |
177 | static const char* notInWhitelist = "notinthewhitelist" ; |
178 | static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist" ; |
179 | |
180 | fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0); |
181 | fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0); |
182 | styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, whitelist, blacklist); |
183 | webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet); |
184 | webkit_user_style_sheet_unref(styleSheet); |
185 | g_assert_true(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList)); |
186 | g_assert_false(isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList)); |
187 | g_assert_false(isStyleSheetInjectedForURLAtPath(test, notInWhitelist)); |
188 | |
189 | // It's important to clean up the environment before other tests. |
190 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
191 | } |
192 | |
193 | static void testUserContentManagerInjectedScript(WebViewTest* test, gconstpointer) |
194 | { |
195 | char* whitelist[3] = { 0, 0, 0 }; |
196 | char* blacklist[3] = { 0, 0, 0 }; |
197 | |
198 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
199 | |
200 | // Without a whitelist or a blacklist all URLs should have the injected script. |
201 | static const char* randomPath = "somerandompath" ; |
202 | g_assert_false(isScriptInjectedForURLAtPath(test, randomPath)); |
203 | WebKitUserScript* script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, nullptr); |
204 | webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); |
205 | webkit_user_script_unref(script); |
206 | g_assert_true(isScriptInjectedForURLAtPath(test, randomPath)); |
207 | |
208 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
209 | |
210 | g_assert_false(isScriptInjectedForURLAtPath(test, randomPath, "WebExtensionTestScriptWorld" )); |
211 | script = webkit_user_script_new_for_world(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, "WebExtensionTestScriptWorld" , nullptr, nullptr); |
212 | webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); |
213 | webkit_user_script_unref(script); |
214 | g_assert_true(isScriptInjectedForURLAtPath(test, randomPath, "WebExtensionTestScriptWorld" )); |
215 | |
216 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
217 | |
218 | fillURLListFromPaths(blacklist, randomPath, 0); |
219 | script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, blacklist); |
220 | webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); |
221 | webkit_user_script_unref(script); |
222 | g_assert_false(isScriptInjectedForURLAtPath(test, randomPath)); |
223 | g_assert_true(isScriptInjectedForURLAtPath(test, "someotherrandompath" )); |
224 | |
225 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
226 | |
227 | static const char* inTheWhiteList = "inthewhitelist" ; |
228 | static const char* notInWhitelist = "notinthewhitelist" ; |
229 | static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist" ; |
230 | |
231 | fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0); |
232 | fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0); |
233 | script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, whitelist, blacklist); |
234 | webkit_user_content_manager_add_script(test->m_userContentManager.get(), script); |
235 | webkit_user_script_unref(script); |
236 | g_assert_true(isScriptInjectedForURLAtPath(test, inTheWhiteList)); |
237 | g_assert_false(isScriptInjectedForURLAtPath(test, inTheWhiteListAndBlackList)); |
238 | g_assert_false(isScriptInjectedForURLAtPath(test, notInWhitelist)); |
239 | |
240 | // It's important to clean up the environment before other tests. |
241 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
242 | } |
243 | |
244 | class UserScriptMessageTest : public WebViewTest { |
245 | public: |
246 | MAKE_GLIB_TEST_FIXTURE(UserScriptMessageTest); |
247 | |
248 | UserScriptMessageTest() |
249 | : m_userScriptMessage(nullptr) |
250 | { |
251 | } |
252 | |
253 | ~UserScriptMessageTest() |
254 | { |
255 | if (m_userScriptMessage) |
256 | webkit_javascript_result_unref(m_userScriptMessage); |
257 | } |
258 | |
259 | bool registerHandler(const char* handlerName, const char* worldName = nullptr) |
260 | { |
261 | return worldName ? webkit_user_content_manager_register_script_message_handler_in_world(m_userContentManager.get(), handlerName, worldName) |
262 | : webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), handlerName); |
263 | } |
264 | |
265 | void unregisterHandler(const char* handlerName, const char* worldName = nullptr) |
266 | { |
267 | return worldName ? webkit_user_content_manager_unregister_script_message_handler_in_world(m_userContentManager.get(), handlerName, worldName) |
268 | : webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), handlerName); |
269 | } |
270 | |
271 | static void scriptMessageReceived(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* jsResult, UserScriptMessageTest* test) |
272 | { |
273 | g_signal_handlers_disconnect_by_func(userContentManager, reinterpret_cast<gpointer>(scriptMessageReceived), test); |
274 | if (!test->m_waitForScriptRun) |
275 | g_main_loop_quit(test->m_mainLoop); |
276 | |
277 | g_assert_null(test->m_userScriptMessage); |
278 | test->m_userScriptMessage = webkit_javascript_result_ref(jsResult); |
279 | } |
280 | |
281 | WebKitJavascriptResult* waitUntilMessageReceived(const char* handlerName) |
282 | { |
283 | if (m_userScriptMessage) { |
284 | webkit_javascript_result_unref(m_userScriptMessage); |
285 | m_userScriptMessage = nullptr; |
286 | } |
287 | |
288 | GUniquePtr<char> signalName(g_strdup_printf("script-message-received::%s" , handlerName)); |
289 | g_signal_connect(m_userContentManager.get(), signalName.get(), G_CALLBACK(scriptMessageReceived), this); |
290 | |
291 | g_main_loop_run(m_mainLoop); |
292 | g_assert_false(m_waitForScriptRun); |
293 | g_assert_nonnull(m_userScriptMessage); |
294 | return m_userScriptMessage; |
295 | } |
296 | |
297 | static void runJavaScriptFinished(GObject*, GAsyncResult* result, UserScriptMessageTest* test) |
298 | { |
299 | g_assert_true(test->m_waitForScriptRun); |
300 | test->m_waitForScriptRun = false; |
301 | g_main_loop_quit(test->m_mainLoop); |
302 | } |
303 | |
304 | WebKitJavascriptResult* postMessageAndWaitUntilReceived(const char* handlerName, const char* javascriptValueAsText, const char* worldName = nullptr) |
305 | { |
306 | GUniquePtr<char> javascriptSnippet(g_strdup_printf("window.webkit.messageHandlers.%s.postMessage(%s);" , handlerName, javascriptValueAsText)); |
307 | m_waitForScriptRun = true; |
308 | if (worldName) |
309 | webkit_web_view_run_javascript_in_world(m_webView, javascriptSnippet.get(), worldName, nullptr, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptFinished), this); |
310 | else |
311 | webkit_web_view_run_javascript(m_webView, javascriptSnippet.get(), nullptr, reinterpret_cast<GAsyncReadyCallback>(runJavaScriptFinished), this); |
312 | return waitUntilMessageReceived(handlerName); |
313 | } |
314 | |
315 | private: |
316 | WebKitJavascriptResult* m_userScriptMessage; |
317 | bool m_waitForScriptRun { false }; |
318 | }; |
319 | |
320 | static void testUserContentManagerScriptMessageReceived(UserScriptMessageTest* test, gconstpointer) |
321 | { |
322 | g_assert_true(test->registerHandler("msg" )); |
323 | |
324 | // Trying to register the same handler a second time must fail. |
325 | g_assert_false(test->registerHandler("msg" )); |
326 | |
327 | test->loadHtml("<html></html>" , nullptr); |
328 | test->waitUntilLoadFinished(); |
329 | |
330 | // Check that the "window.webkit.messageHandlers" namespace exists. |
331 | GUniqueOutPtr<GError> error; |
332 | WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';" , &error.outPtr()); |
333 | g_assert_nonnull(javascriptResult); |
334 | g_assert_no_error(error.get()); |
335 | GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); |
336 | g_assert_cmpstr(valueString.get(), ==, "y" ); |
337 | |
338 | // Check that the "document.webkit.messageHandlers.msg" namespace exists. |
339 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';" , &error.outPtr()); |
340 | g_assert_nonnull(javascriptResult); |
341 | g_assert_no_error(error.get()); |
342 | valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
343 | g_assert_cmpstr(valueString.get(), ==, "y" ); |
344 | |
345 | valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg" , "'user message'" ))); |
346 | g_assert_cmpstr(valueString.get(), ==, "user message" ); |
347 | |
348 | // Messages should arrive despite of other handlers being registered. |
349 | g_assert_true(test->registerHandler("anotherHandler" )); |
350 | |
351 | // Check that the "document.webkit.messageHandlers.msg" namespace still exists. |
352 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';" , &error.outPtr()); |
353 | g_assert_nonnull(javascriptResult); |
354 | g_assert_no_error(error.get()); |
355 | valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
356 | g_assert_cmpstr(valueString.get(), ==, "y" ); |
357 | |
358 | // Check that the "document.webkit.messageHandlers.anotherHandler" namespace exists. |
359 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.anotherHandler ? 'y' : 'n';" , &error.outPtr()); |
360 | g_assert_nonnull(javascriptResult); |
361 | g_assert_no_error(error.get()); |
362 | valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult)); |
363 | g_assert_cmpstr(valueString.get(), ==, "y" ); |
364 | |
365 | valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg" , "'handler: msg'" ))); |
366 | g_assert_cmpstr(valueString.get(), ==, "handler: msg" ); |
367 | |
368 | valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("anotherHandler" , "'handler: anotherHandler'" ))); |
369 | g_assert_cmpstr(valueString.get(), ==, "handler: anotherHandler" ); |
370 | |
371 | // Unregistering a handler and re-registering again under the same name should work. |
372 | test->unregisterHandler("msg" ); |
373 | |
374 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg.postMessage('42');" , &error.outPtr()); |
375 | g_assert_null(javascriptResult); |
376 | g_assert_nonnull(error.get()); |
377 | |
378 | // Re-registering a handler that has been unregistered must work |
379 | g_assert_true(test->registerHandler("msg" )); |
380 | valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg" , "'handler: msg'" ))); |
381 | g_assert_cmpstr(valueString.get(), ==, "handler: msg" ); |
382 | |
383 | test->unregisterHandler("anotherHandler" ); |
384 | } |
385 | |
386 | static void testUserContentManagerScriptMessageInWorldReceived(UserScriptMessageTest* test, gconstpointer) |
387 | { |
388 | g_assert_true(test->registerHandler("msg" )); |
389 | |
390 | test->loadHtml("<html></html>" , nullptr); |
391 | test->waitUntilLoadFinished(); |
392 | |
393 | // Check that the "window.webkit.messageHandlers" namespace doesn't exist in isolated worlds. |
394 | GUniqueOutPtr<GError> error; |
395 | WebKitJavascriptResult* javascriptResult = test->runJavaScriptInWorldAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';" , "WebExtensionTestScriptWorld" , &error.outPtr()); |
396 | g_assert_null(javascriptResult); |
397 | g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); |
398 | test->unregisterHandler("msg" ); |
399 | |
400 | g_assert_true(test->registerHandler("msg" , "WebExtensionTestScriptWorld" )); |
401 | |
402 | // Check that the "window.webkit.messageHandlers" namespace exists in the world. |
403 | javascriptResult = test->runJavaScriptInWorldAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';" , "WebExtensionTestScriptWorld" , &error.outPtr()); |
404 | g_assert_nonnull(javascriptResult); |
405 | g_assert_no_error(error.get()); |
406 | GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); |
407 | g_assert_cmpstr(valueString.get(), ==, "y" ); |
408 | |
409 | valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg" , "'user message'" , "WebExtensionTestScriptWorld" ))); |
410 | g_assert_cmpstr(valueString.get(), ==, "user message" ); |
411 | |
412 | // Post message in main world should fail. |
413 | javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg.postMessage('42');" , &error.outPtr()); |
414 | g_assert_null(javascriptResult); |
415 | g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED); |
416 | |
417 | test->unregisterHandler("msg" , "WebExtensionTestScriptWorld" ); |
418 | } |
419 | |
420 | #if PLATFORM(GTK) |
421 | static void testUserContentManagerScriptMessageFromDOMBindings(UserScriptMessageTest* test, gconstpointer) |
422 | { |
423 | g_assert_true(test->registerHandler("dom" )); |
424 | |
425 | test->loadHtml("<html>1</html>" , nullptr); |
426 | WebKitJavascriptResult* javascriptResult = test->waitUntilMessageReceived("dom" ); |
427 | g_assert_nonnull(javascriptResult); |
428 | GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); |
429 | g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded" ); |
430 | |
431 | test->unregisterHandler("dom" ); |
432 | } |
433 | #endif |
434 | |
435 | static bool isCSSBlockedForURLAtPath(WebViewTest* test, const char* path) |
436 | { |
437 | test->loadURI(kServer->getURIForPath(path).data()); |
438 | test->waitUntilLoadFinished(); |
439 | |
440 | GUniqueOutPtr<GError> error; |
441 | WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kScriptTestCSSBlocked, &error.outPtr()); |
442 | g_assert_nonnull(javascriptResult); |
443 | g_assert_no_error(error.get()); |
444 | |
445 | GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); |
446 | return !g_strcmp0(valueString.get(), kScriptTestCSSBlockedResult); |
447 | } |
448 | |
449 | static WebKitUserContentFilter* getUserContentFilter(WebViewTest* test) |
450 | { |
451 | GUniquePtr<char> filtersPath(g_build_filename(test->dataDirectory(), "filters" , nullptr)); |
452 | WebKitUserContentFilterStore* store = webkit_user_content_filter_store_new(filtersPath.get()); |
453 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(store)); |
454 | |
455 | struct Data { |
456 | GMainLoop* mainLoop; |
457 | WebKitUserContentFilter* filter; |
458 | }; |
459 | Data data { test->m_mainLoop, nullptr, }; |
460 | |
461 | GRefPtr<GBytes> source = adoptGRef(g_bytes_new_static(kJSONFilter, strlen(kJSONFilter))); |
462 | webkit_user_content_filter_store_save(store, "TestFilter" , source.get(), nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { |
463 | auto* data = static_cast<Data*>(userData); |
464 | GUniqueOutPtr<GError> error; |
465 | data->filter = webkit_user_content_filter_store_save_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &error.outPtr()); |
466 | g_assert_nonnull(data->filter); |
467 | g_assert_no_error(error.get()); |
468 | g_main_loop_quit(data->mainLoop); |
469 | }, &data); |
470 | g_main_loop_run(data.mainLoop); |
471 | |
472 | g_object_unref(store); |
473 | |
474 | g_assert_nonnull(data.filter); |
475 | return data.filter; |
476 | } |
477 | |
478 | static void testUserContentManagerContentFilter(WebViewTest* test, gconstpointer) |
479 | { |
480 | char* whitelist[] = { nullptr, nullptr, nullptr }; |
481 | char* blacklist[] = { nullptr, nullptr, nullptr }; |
482 | |
483 | removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); |
484 | |
485 | static const char* somePath = "somepath" ; |
486 | g_assert_false(isCSSBlockedForURLAtPath(test, somePath)); |
487 | |
488 | WebKitUserContentFilter* filter = getUserContentFilter(test); |
489 | webkit_user_content_manager_add_filter(test->m_userContentManager.get(), filter); |
490 | g_assert_true(isCSSBlockedForURLAtPath(test, somePath)); |
491 | |
492 | webkit_user_content_manager_remove_filter(test->m_userContentManager.get(), filter); |
493 | g_assert_false(isCSSBlockedForURLAtPath(test, somePath)); |
494 | |
495 | webkit_user_content_filter_unref(filter); |
496 | } |
497 | |
498 | static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) |
499 | { |
500 | soup_message_set_status(message, SOUP_STATUS_OK); |
501 | if (!g_strcmp0(path, "/extra.css" )) |
502 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kTestCSS, strlen(kTestCSS)); |
503 | else |
504 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kTestHTML, strlen(kTestHTML)); |
505 | soup_message_body_complete(message->response_body); |
506 | } |
507 | |
508 | void beforeAll() |
509 | { |
510 | kServer = new WebKitTestServer(); |
511 | kServer->run(serverCallback); |
512 | |
513 | Test::add("WebKitWebView" , "new-with-user-content-manager" , testWebViewNewWithUserContentManager); |
514 | WebViewTest::add("WebKitUserContentManager" , "injected-style-sheet" , testUserContentManagerInjectedStyleSheet); |
515 | WebViewTest::add("WebKitUserContentManager" , "injected-script" , testUserContentManagerInjectedScript); |
516 | UserScriptMessageTest::add("WebKitUserContentManager" , "script-message-received" , testUserContentManagerScriptMessageReceived); |
517 | UserScriptMessageTest::add("WebKitUserContentManager" , "script-message-in-world-received" , testUserContentManagerScriptMessageInWorldReceived); |
518 | #if PLATFORM(GTK) |
519 | UserScriptMessageTest::add("WebKitUserContentManager" , "script-message-from-dom-bindings" , testUserContentManagerScriptMessageFromDOMBindings); |
520 | #endif |
521 | WebViewTest::add("WebKitUserContentManager" , "content-filter" , testUserContentManagerContentFilter); |
522 | } |
523 | |
524 | void afterAll() |
525 | { |
526 | delete kServer; |
527 | } |
528 | |