1 | /* |
2 | * Copyright (C) 2009, 2010 Gustavo Noronha Silva |
3 | * Copyright (C) 2009, 2011 Igalia S.L. |
4 | * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved. |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public License |
17 | * along with this library; see the file COPYING.LIB. If not, write to |
18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | * Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #include "config.h" |
23 | |
24 | #include "LoadTrackingTest.h" |
25 | #include "WebKitTestBus.h" |
26 | #include "WebKitTestServer.h" |
27 | #include "WebViewTest.h" |
28 | #include <libsoup/soup.h> |
29 | #include <wtf/Vector.h> |
30 | #include <wtf/text/CString.h> |
31 | |
32 | static WebKitTestBus* bus; |
33 | static WebKitTestServer* kServer; |
34 | |
35 | const char* = "DNT header not present" ; |
36 | |
37 | static void testLoadingStatus(LoadTrackingTest* test, gconstpointer data) |
38 | { |
39 | test->setRedirectURI(kServer->getURIForPath("/normal" ).data()); |
40 | test->loadURI(kServer->getURIForPath("/redirect" ).data()); |
41 | test->waitUntilLoadFinished(); |
42 | |
43 | Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents; |
44 | g_assert_cmpint(events.size(), ==, 4); |
45 | g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); |
46 | g_assert_cmpint(events[1], ==, LoadTrackingTest::ProvisionalLoadReceivedServerRedirect); |
47 | g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadCommitted); |
48 | g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished); |
49 | } |
50 | |
51 | static void testLoadingError(LoadTrackingTest* test, gconstpointer) |
52 | { |
53 | test->loadURI(kServer->getURIForPath("/error" ).data()); |
54 | test->waitUntilLoadFinished(); |
55 | |
56 | Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents; |
57 | g_assert_cmpint(events.size(), ==, 3); |
58 | g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); |
59 | g_assert_cmpint(events[1], ==, LoadTrackingTest::ProvisionalLoadFailed); |
60 | g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); |
61 | } |
62 | |
63 | static void assertNormalLoadHappened(Vector<LoadTrackingTest::LoadEvents>& events) |
64 | { |
65 | g_assert_cmpint(events.size(), ==, 3); |
66 | g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); |
67 | g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted); |
68 | g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished); |
69 | } |
70 | |
71 | static void testLoadHtml(LoadTrackingTest* test, gconstpointer) |
72 | { |
73 | test->loadHtml("<html><body>Hello WebKit-GTK+</body></html>" , 0); |
74 | test->waitUntilLoadFinished(); |
75 | assertNormalLoadHappened(test->m_loadEvents); |
76 | } |
77 | |
78 | static void testLoadAlternateHTML(LoadTrackingTest* test, gconstpointer) |
79 | { |
80 | test->loadAlternateHTML("<html><body>Alternate page</body></html>" , "http://error-page.foo/" , 0); |
81 | test->waitUntilLoadFinished(); |
82 | assertNormalLoadHappened(test->m_loadEvents); |
83 | } |
84 | |
85 | static void testLoadAlternateHTMLForLocalPage(LoadTrackingTest* test, gconstpointer) |
86 | { |
87 | test->loadAlternateHTML("<html><body>Alternate page</body></html>" , "file:///not/actually/loaded.html" , 0); |
88 | test->waitUntilLoadFinished(); |
89 | assertNormalLoadHappened(test->m_loadEvents); |
90 | } |
91 | |
92 | static void testLoadPlainText(LoadTrackingTest* test, gconstpointer) |
93 | { |
94 | test->loadPlainText("Hello WebKit-GTK+" ); |
95 | test->waitUntilLoadFinished(); |
96 | assertNormalLoadHappened(test->m_loadEvents); |
97 | } |
98 | |
99 | static void testLoadBytes(LoadTrackingTest* test, gconstpointer) |
100 | { |
101 | GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico" , nullptr)); |
102 | char* contents; |
103 | gsize contentsLength; |
104 | g_file_get_contents(filePath.get(), &contents, &contentsLength, nullptr); |
105 | GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_take(contents, contentsLength)); |
106 | test->loadBytes(bytes.get(), "image/vnd.microsoft.icon" , nullptr, nullptr); |
107 | test->waitUntilLoadFinished(); |
108 | assertNormalLoadHappened(test->m_loadEvents); |
109 | } |
110 | |
111 | static void testLoadRequest(LoadTrackingTest* test, gconstpointer) |
112 | { |
113 | GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal" ).data())); |
114 | test->loadRequest(request.get()); |
115 | test->waitUntilLoadFinished(); |
116 | assertNormalLoadHappened(test->m_loadEvents); |
117 | } |
118 | |
119 | static void testLoadFromGResource(LoadTrackingTest* test, gconstpointer) |
120 | { |
121 | GRefPtr<WebKitURIRequest> request(webkit_uri_request_new("resource:///org/webkit/glib/tests/boring.html" )); |
122 | test->loadRequest(request.get()); |
123 | test->waitUntilLoadFinished(); |
124 | assertNormalLoadHappened(test->m_loadEvents); |
125 | } |
126 | |
127 | class LoadStopTrackingTest : public LoadTrackingTest { |
128 | public: |
129 | MAKE_GLIB_TEST_FIXTURE(LoadStopTrackingTest); |
130 | |
131 | virtual void loadCommitted() |
132 | { |
133 | LoadTrackingTest::loadCommitted(); |
134 | webkit_web_view_stop_loading(m_webView); |
135 | } |
136 | virtual void loadFailed(const gchar* failingURI, GError* error) |
137 | { |
138 | g_assert_error(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED); |
139 | LoadTrackingTest::loadFailed(failingURI, error); |
140 | } |
141 | }; |
142 | |
143 | static void testLoadCancelled(LoadStopTrackingTest* test, gconstpointer) |
144 | { |
145 | test->loadURI(kServer->getURIForPath("/cancelled" ).data()); |
146 | test->waitUntilLoadFinished(); |
147 | |
148 | Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents; |
149 | g_assert_cmpint(events.size(), ==, 4); |
150 | g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); |
151 | g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted); |
152 | g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFailed); |
153 | g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished); |
154 | } |
155 | |
156 | static void testWebViewTitle(LoadTrackingTest* test, gconstpointer) |
157 | { |
158 | g_assert_null(webkit_web_view_get_title(test->m_webView)); |
159 | test->loadHtml("<html><head><title>Welcome to WebKit-GTK+!</title></head></html>" , 0); |
160 | test->waitUntilLoadFinished(); |
161 | g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "Welcome to WebKit-GTK+!" ); |
162 | } |
163 | |
164 | static void testWebViewReload(LoadTrackingTest* test, gconstpointer) |
165 | { |
166 | // Check that nothing happens when there's nothing to reload. |
167 | test->reload(); |
168 | test->wait(0.25); // Wait for a quarter of a second. |
169 | |
170 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
171 | test->waitUntilLoadFinished(); |
172 | assertNormalLoadHappened(test->m_loadEvents); |
173 | |
174 | test->reload(); |
175 | test->waitUntilLoadFinished(); |
176 | assertNormalLoadHappened(test->m_loadEvents); |
177 | } |
178 | |
179 | static void testLoadProgress(LoadTrackingTest* test, gconstpointer) |
180 | { |
181 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
182 | test->waitUntilLoadFinished(); |
183 | g_assert_cmpfloat(test->m_estimatedProgress, ==, 1); |
184 | } |
185 | |
186 | static void testWebViewHistoryLoad(LoadTrackingTest* test, gconstpointer) |
187 | { |
188 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
189 | test->waitUntilLoadFinished(); |
190 | assertNormalLoadHappened(test->m_loadEvents); |
191 | |
192 | test->loadURI(kServer->getURIForPath("/normal2" ).data()); |
193 | test->waitUntilLoadFinished(); |
194 | assertNormalLoadHappened(test->m_loadEvents); |
195 | |
196 | // Check that load process is the same for pages loaded from history cache. |
197 | test->goBack(); |
198 | test->waitUntilLoadFinished(); |
199 | assertNormalLoadHappened(test->m_loadEvents); |
200 | |
201 | test->goForward(); |
202 | test->waitUntilLoadFinished(); |
203 | assertNormalLoadHappened(test->m_loadEvents); |
204 | } |
205 | |
206 | class LoadTwiceAndReloadTest : public WebViewTest { |
207 | public: |
208 | MAKE_GLIB_TEST_FIXTURE(LoadTwiceAndReloadTest); |
209 | |
210 | static void reloadOnFinishLoad(WebKitWebView* view, WebKitLoadEvent loadEvent, LoadTwiceAndReloadTest* test) |
211 | { |
212 | if (++test->m_loadsCount == 3) |
213 | test->quitMainLoop(); |
214 | webkit_web_view_reload(view); |
215 | } |
216 | |
217 | LoadTwiceAndReloadTest() |
218 | { |
219 | g_signal_connect(m_webView, "load-changed" , G_CALLBACK(reloadOnFinishLoad), this); |
220 | } |
221 | |
222 | ~LoadTwiceAndReloadTest() |
223 | { |
224 | g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this); |
225 | } |
226 | |
227 | void waitUntilFinished() |
228 | { |
229 | m_loadsCount = 0; |
230 | g_main_loop_run(m_mainLoop); |
231 | } |
232 | |
233 | unsigned m_loadsCount { 0 }; |
234 | }; |
235 | |
236 | static void testWebViewLoadTwiceAndReload(LoadTwiceAndReloadTest* test, gconstpointer) |
237 | { |
238 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
239 | test->loadURI(kServer->getURIForPath("/normal2" ).data()); |
240 | test->waitUntilFinished(); |
241 | } |
242 | |
243 | static void uriChanged(WebKitWebView* webView, GParamSpec*, LoadTrackingTest* test) |
244 | { |
245 | const char* uri = webkit_web_view_get_uri(webView); |
246 | if (g_str_has_suffix(uri, "/normal" )) |
247 | test->m_activeURI = uri; |
248 | } |
249 | |
250 | static void testUnfinishedSubresourceLoad(LoadTrackingTest* test, gconstpointer) |
251 | { |
252 | // Verify that LoadFinished occurs even if the next load starts before the |
253 | // previous load actually finishes. |
254 | test->loadURI(kServer->getURIForPath("/unfinished-subresource-load" ).data()); |
255 | auto signalID = g_signal_connect(test->m_webView, "notify::uri" , G_CALLBACK(uriChanged), test); |
256 | test->waitUntilLoadFinished(); |
257 | test->waitUntilLoadFinished(); |
258 | g_signal_handler_disconnect(test->m_webView, signalID); |
259 | |
260 | Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents; |
261 | g_assert_cmpint(events.size(), ==, 7); |
262 | g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted); |
263 | g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted); |
264 | g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFailed); |
265 | g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished); |
266 | g_assert_cmpint(events[4], ==, LoadTrackingTest::ProvisionalLoadStarted); |
267 | g_assert_cmpint(events[5], ==, LoadTrackingTest::LoadCommitted); |
268 | g_assert_cmpint(events[6], ==, LoadTrackingTest::LoadFinished); |
269 | } |
270 | |
271 | class ViewURITrackingTest: public LoadTrackingTest { |
272 | public: |
273 | MAKE_GLIB_TEST_FIXTURE(ViewURITrackingTest); |
274 | |
275 | static void uriChanged(GObject*, GParamSpec*, ViewURITrackingTest* test) |
276 | { |
277 | g_assert_cmpstr(test->m_currentURI.data(), !=, webkit_web_view_get_uri(test->m_webView)); |
278 | test->m_currentURI = webkit_web_view_get_uri(test->m_webView); |
279 | } |
280 | |
281 | ViewURITrackingTest() |
282 | : m_currentURI(webkit_web_view_get_uri(m_webView)) |
283 | { |
284 | g_assert_true(m_currentURI.isNull()); |
285 | m_currentURIList.grow(m_currentURIList.capacity()); |
286 | g_signal_connect(m_webView, "notify::uri" , G_CALLBACK(uriChanged), this); |
287 | } |
288 | |
289 | enum State { Provisional, ProvisionalAfterRedirect, Commited, Finished }; |
290 | |
291 | void loadURI(const char* uri) |
292 | { |
293 | reset(); |
294 | LoadTrackingTest::loadURI(uri); |
295 | } |
296 | |
297 | void provisionalLoadStarted() |
298 | { |
299 | m_currentURIList[Provisional] = m_currentURI; |
300 | } |
301 | |
302 | void provisionalLoadReceivedServerRedirect() |
303 | { |
304 | m_currentURIList[ProvisionalAfterRedirect] = m_currentURI; |
305 | } |
306 | |
307 | void loadCommitted() |
308 | { |
309 | m_currentURIList[Commited] = m_currentURI; |
310 | } |
311 | |
312 | void loadFinished() |
313 | { |
314 | m_currentURIList[Finished] = m_currentURI; |
315 | LoadTrackingTest::loadFinished(); |
316 | } |
317 | |
318 | void checkURIAtState(State state, const char* path) |
319 | { |
320 | if (path) |
321 | ASSERT_CMP_CSTRING(m_currentURIList[state], ==, kServer->getURIForPath(path)); |
322 | else |
323 | g_assert_true(m_currentURIList[state].isNull()); |
324 | } |
325 | |
326 | private: |
327 | void reset() |
328 | { |
329 | m_currentURI = CString(); |
330 | m_currentURIList.clear(); |
331 | m_currentURIList.grow(m_currentURIList.capacity()); |
332 | } |
333 | |
334 | CString m_currentURI; |
335 | Vector<CString, 4> m_currentURIList; |
336 | }; |
337 | |
338 | static void testWebViewActiveURI(ViewURITrackingTest* test, gconstpointer) |
339 | { |
340 | // Normal load, the URL doesn't change. |
341 | test->loadURI(kServer->getURIForPath("/normal1" ).data()); |
342 | test->waitUntilLoadFinished(); |
343 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal1" ); |
344 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
345 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal1" ); |
346 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal1" ); |
347 | |
348 | // Redirect, the URL changes after the redirect. |
349 | test->loadURI(kServer->getURIForPath("/redirect" ).data()); |
350 | test->waitUntilLoadFinished(); |
351 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect" ); |
352 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal" ); |
353 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal" ); |
354 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal" ); |
355 | |
356 | // Normal load, URL changed by WebKitPage::send-request. |
357 | test->loadURI(kServer->getURIForPath("/normal-change-request" ).data()); |
358 | test->waitUntilLoadFinished(); |
359 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal-change-request" ); |
360 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
361 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed" ); |
362 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed" ); |
363 | |
364 | // Redirect, URL changed by WebKitPage::send-request. |
365 | test->loadURI(kServer->getURIForPath("/redirect-to-change-request" ).data()); |
366 | test->waitUntilLoadFinished(); |
367 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-to-change-request" ); |
368 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request" ); |
369 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect" ); |
370 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect" ); |
371 | |
372 | // Non-API request loads. |
373 | test->loadURI(kServer->getURIForPath("/redirect-js/normal" ).data()); |
374 | test->waitUntilLoadFinished(); |
375 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal" ); |
376 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
377 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/normal" ); |
378 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/normal" ); |
379 | test->waitUntilLoadFinished(); |
380 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal" ); |
381 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
382 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal" ); |
383 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal" ); |
384 | |
385 | test->loadURI(kServer->getURIForPath("/redirect-js/redirect" ).data()); |
386 | test->waitUntilLoadFinished(); |
387 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect" ); |
388 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
389 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/redirect" ); |
390 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/redirect" ); |
391 | test->waitUntilLoadFinished(); |
392 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect" ); |
393 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal" ); |
394 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal" ); |
395 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal" ); |
396 | |
397 | test->loadURI(kServer->getURIForPath("/redirect-js/normal-change-request" ).data()); |
398 | test->waitUntilLoadFinished(); |
399 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal-change-request" ); |
400 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
401 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/normal-change-request" ); |
402 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/normal-change-request" ); |
403 | test->waitUntilLoadFinished(); |
404 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal-change-request" ); |
405 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
406 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed" ); |
407 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed" ); |
408 | |
409 | test->loadURI(kServer->getURIForPath("/redirect-js/redirect-to-change-request" ).data()); |
410 | test->waitUntilLoadFinished(); |
411 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect-to-change-request" ); |
412 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr); |
413 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/redirect-to-change-request" ); |
414 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/redirect-to-change-request" ); |
415 | test->waitUntilLoadFinished(); |
416 | test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect-to-change-request" ); |
417 | test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request" ); |
418 | test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect" ); |
419 | test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect" ); |
420 | } |
421 | |
422 | class ViewIsLoadingTest: public LoadTrackingTest { |
423 | public: |
424 | MAKE_GLIB_TEST_FIXTURE(ViewIsLoadingTest); |
425 | |
426 | static void isLoadingChanged(GObject*, GParamSpec*, ViewIsLoadingTest* test) |
427 | { |
428 | if (webkit_web_view_is_loading(test->m_webView)) |
429 | test->beginLoad(); |
430 | else |
431 | test->endLoad(); |
432 | } |
433 | |
434 | ViewIsLoadingTest() |
435 | { |
436 | g_signal_connect(m_webView, "notify::is-loading" , G_CALLBACK(isLoadingChanged), this); |
437 | } |
438 | |
439 | void beginLoad() |
440 | { |
441 | // New load, load-started hasn't been emitted yet. |
442 | g_assert_true(m_loadEvents.isEmpty()); |
443 | g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data()); |
444 | } |
445 | |
446 | void endLoad() |
447 | { |
448 | // Load finish, load-finished and load-failed haven't been emitted yet. |
449 | g_assert_false(m_loadEvents.isEmpty()); |
450 | g_assert_false(m_loadEvents.contains(LoadTrackingTest::LoadFinished)); |
451 | g_assert_false(m_loadEvents.contains(LoadTrackingTest::LoadFailed)); |
452 | } |
453 | }; |
454 | |
455 | static void testWebViewIsLoading(ViewIsLoadingTest* test, gconstpointer) |
456 | { |
457 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
458 | test->waitUntilLoadFinished(); |
459 | |
460 | test->reload(); |
461 | test->waitUntilLoadFinished(); |
462 | |
463 | test->loadURI(kServer->getURIForPath("/error" ).data()); |
464 | test->waitUntilLoadFinished(); |
465 | |
466 | test->loadURI(kServer->getURIForPath("/normal" ).data()); |
467 | test->waitUntilLoadFinished(); |
468 | test->loadURI(kServer->getURIForPath("/normal2" ).data()); |
469 | test->waitUntilLoadFinished(); |
470 | |
471 | test->goBack(); |
472 | test->waitUntilLoadFinished(); |
473 | |
474 | test->goForward(); |
475 | test->waitUntilLoadFinished(); |
476 | } |
477 | |
478 | class WebPageURITest: public WebViewTest { |
479 | public: |
480 | MAKE_GLIB_TEST_FIXTURE(WebPageURITest); |
481 | |
482 | static void webPageURIChangedCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebPageURITest* test) |
483 | { |
484 | const char* uri; |
485 | g_variant_get(result, "(&s)" , &uri); |
486 | test->m_webPageURIs.append(uri); |
487 | } |
488 | |
489 | static void webViewURIChanged(GObject*, GParamSpec*, WebPageURITest* test) |
490 | { |
491 | test->m_webViewURIs.append(webkit_web_view_get_uri(test->m_webView)); |
492 | } |
493 | |
494 | WebPageURITest() |
495 | { |
496 | GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u" , Test::s_webExtensionID)); |
497 | GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(), |
498 | "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest" , m_mainLoop)); |
499 | m_uriChangedSignalID = g_dbus_connection_signal_subscribe( |
500 | g_dbus_proxy_get_connection(proxy.get()), |
501 | 0, |
502 | "org.webkit.gtk.WebExtensionTest" , |
503 | "URIChanged" , |
504 | "/org/webkit/gtk/WebExtensionTest" , |
505 | 0, |
506 | G_DBUS_SIGNAL_FLAGS_NONE, |
507 | reinterpret_cast<GDBusSignalCallback>(webPageURIChangedCallback), |
508 | this, |
509 | 0); |
510 | g_assert_cmpuint(m_uriChangedSignalID, !=, 0); |
511 | |
512 | g_signal_connect(m_webView, "notify::uri" , G_CALLBACK(webViewURIChanged), this); |
513 | } |
514 | |
515 | ~WebPageURITest() |
516 | { |
517 | g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
518 | g_dbus_connection_signal_unsubscribe(bus->connection(), m_uriChangedSignalID); |
519 | } |
520 | |
521 | void loadURI(const char* uri) |
522 | { |
523 | m_webPageURIs.clear(); |
524 | m_webViewURIs.clear(); |
525 | WebViewTest::loadURI(uri); |
526 | } |
527 | |
528 | void checkViewAndPageURIsMatch() const |
529 | { |
530 | g_assert_cmpint(m_webPageURIs.size(), ==, m_webViewURIs.size()); |
531 | for (size_t i = 0; i < m_webPageURIs.size(); ++i) |
532 | ASSERT_CMP_CSTRING(m_webPageURIs[i], ==, m_webViewURIs[i]); |
533 | } |
534 | |
535 | unsigned m_uriChangedSignalID; |
536 | Vector<CString> m_webPageURIs; |
537 | Vector<CString> m_webViewURIs; |
538 | }; |
539 | |
540 | static void testWebPageURI(WebPageURITest* test, gconstpointer) |
541 | { |
542 | // Normal load. |
543 | test->loadURI(kServer->getURIForPath("/normal1" ).data()); |
544 | test->waitUntilLoadFinished(); |
545 | test->checkViewAndPageURIsMatch(); |
546 | g_assert_cmpint(test->m_webPageURIs.size(), ==, 1); |
547 | ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal1" )); |
548 | |
549 | // Redirect |
550 | test->loadURI(kServer->getURIForPath("/redirect" ).data()); |
551 | test->waitUntilLoadFinished(); |
552 | test->checkViewAndPageURIsMatch(); |
553 | g_assert_cmpint(test->m_webPageURIs.size(), ==, 2); |
554 | ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect" )); |
555 | ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal" )); |
556 | |
557 | // Normal load, URL changed by WebKitPage::send-request. |
558 | test->loadURI(kServer->getURIForPath("/normal-change-request" ).data()); |
559 | test->waitUntilLoadFinished(); |
560 | test->checkViewAndPageURIsMatch(); |
561 | g_assert_cmpint(test->m_webPageURIs.size(), ==, 2); |
562 | ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal-change-request" )); |
563 | ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/request-changed" )); |
564 | |
565 | // Redirect, URL changed by WebKitPage::send-request. |
566 | test->loadURI(kServer->getURIForPath("/redirect-to-change-request" ).data()); |
567 | test->waitUntilLoadFinished(); |
568 | test->checkViewAndPageURIsMatch(); |
569 | g_assert_cmpint(test->m_webPageURIs.size(), ==, 3); |
570 | ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect-to-change-request" )); |
571 | ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal-change-request" )); |
572 | ASSERT_CMP_CSTRING(test->m_webPageURIs[2], ==, kServer->getURIForPath("/request-changed-on-redirect" )); |
573 | } |
574 | |
575 | static void (WebViewTest* test, gconstpointer) |
576 | { |
577 | GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar" )); |
578 | g_assert_nonnull(uriRequest.get()); |
579 | g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar" ); |
580 | g_assert_null(webkit_uri_request_get_http_headers(uriRequest.get())); |
581 | |
582 | // Load a request with no Do Not Track header. |
583 | webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/do-not-track-header" ).data()); |
584 | test->loadRequest(uriRequest.get()); |
585 | test->waitUntilLoadFinished(); |
586 | |
587 | size_t mainResourceDataSize = 0; |
588 | const char* mainResourceData = test->mainResourceData(mainResourceDataSize); |
589 | g_assert_cmpint(mainResourceDataSize, ==, strlen(kDNTHeaderNotPresent)); |
590 | g_assert_cmpint(strncmp(mainResourceData, kDNTHeaderNotPresent, mainResourceDataSize), ==, 0); |
591 | |
592 | // Add the Do Not Track header and load the request again. |
593 | SoupMessageHeaders* = webkit_uri_request_get_http_headers(uriRequest.get()); |
594 | g_assert_nonnull(headers); |
595 | soup_message_headers_append(headers, "DNT" , "1" ); |
596 | test->loadRequest(uriRequest.get()); |
597 | test->waitUntilLoadFinished(); |
598 | |
599 | mainResourceData = test->mainResourceData(mainResourceDataSize); |
600 | g_assert_cmpint(mainResourceDataSize, ==, 1); |
601 | g_assert_cmpint(strncmp(mainResourceData, "1" , mainResourceDataSize), ==, 0); |
602 | |
603 | // Load a URI for which the web extension will add the Do Not Track header. |
604 | test->loadURI(kServer->getURIForPath("/add-do-not-track-header" ).data()); |
605 | test->waitUntilLoadFinished(); |
606 | |
607 | mainResourceData = test->mainResourceData(mainResourceDataSize); |
608 | g_assert_cmpint(mainResourceDataSize, ==, 1); |
609 | g_assert_cmpint(strncmp(mainResourceData, "1" , mainResourceDataSize), ==, 0); |
610 | } |
611 | |
612 | static void testURIRequestHTTPMethod(WebViewTest* test, gconstpointer) |
613 | { |
614 | GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar" )); |
615 | g_assert_nonnull(uriRequest.get()); |
616 | g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar" ); |
617 | g_assert_null(webkit_uri_request_get_http_method(uriRequest.get())); |
618 | |
619 | webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/http-get-method" ).data()); |
620 | test->loadRequest(uriRequest.get()); |
621 | test->waitUntilLoadFinished(); |
622 | |
623 | test->runJavaScriptAndWaitUntilFinished("xhr = new XMLHttpRequest; xhr.open('POST', '/http-post-method', false); xhr.send();" , nullptr); |
624 | } |
625 | |
626 | static void (WebViewTest* test, gconstpointer) |
627 | { |
628 | test->loadHtml("<html><body>No HTTP headers</body></html>" , "file:///" ); |
629 | test->waitUntilLoadFinished(); |
630 | WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView); |
631 | g_assert_true(WEBKIT_IS_WEB_RESOURCE(resource)); |
632 | WebKitURIResponse* response = webkit_web_resource_get_response(resource); |
633 | g_assert_true(WEBKIT_IS_URI_RESPONSE(response)); |
634 | g_assert_null(webkit_uri_response_get_http_headers(response)); |
635 | |
636 | test->loadURI(kServer->getURIForPath("/headers" ).data()); |
637 | test->waitUntilLoadFinished(); |
638 | resource = webkit_web_view_get_main_resource(test->m_webView); |
639 | g_assert_true(WEBKIT_IS_WEB_RESOURCE(resource)); |
640 | response = webkit_web_resource_get_response(resource); |
641 | g_assert_true(WEBKIT_IS_URI_RESPONSE(response)); |
642 | SoupMessageHeaders* = webkit_uri_response_get_http_headers(response); |
643 | g_assert_nonnull(headers); |
644 | g_assert_cmpstr(soup_message_headers_get_one(headers, "Foo" ), ==, "bar" ); |
645 | } |
646 | |
647 | static void testRedirectToDataURI(WebViewTest* test, gconstpointer) |
648 | { |
649 | test->loadURI(kServer->getURIForPath("/redirect-to-data" ).data()); |
650 | test->waitUntilLoadFinished(); |
651 | |
652 | static const char* expectedData = "data-uri" ; |
653 | size_t mainResourceDataSize = 0; |
654 | const char* mainResourceData = test->mainResourceData(mainResourceDataSize); |
655 | g_assert_cmpint(mainResourceDataSize, ==, strlen(expectedData)); |
656 | g_assert_cmpint(strncmp(mainResourceData, expectedData, mainResourceDataSize), ==, 0); |
657 | } |
658 | |
659 | static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) |
660 | { |
661 | static const char* responseString = "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
662 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
663 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
664 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
665 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
666 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
667 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!" |
668 | "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>" ; |
669 | |
670 | if (message->method != SOUP_METHOD_GET) { |
671 | soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); |
672 | return; |
673 | } |
674 | |
675 | soup_message_set_status(message, SOUP_STATUS_OK); |
676 | |
677 | if (g_str_has_prefix(path, "/normal" ) || g_str_has_prefix(path, "/http-get-method" )) |
678 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); |
679 | else if (g_str_equal(path, "/error" )) |
680 | soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT); |
681 | else if (g_str_equal(path, "/redirect" )) { |
682 | soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); |
683 | soup_message_headers_append(message->response_headers, "Location" , "/normal" ); |
684 | } else if (g_str_equal(path, "/redirect-to-change-request" )) { |
685 | soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); |
686 | soup_message_headers_append(message->response_headers, "Location" , "/normal-change-request" ); |
687 | } else if (g_str_has_prefix(path, "/redirect-js/" )) { |
688 | static const char* redirectJSFormat = "<html><body><script>location = '%s';</script></body></html>" ; |
689 | char* redirectJS = g_strdup_printf(redirectJSFormat, g_strrstr(path, "/" )); |
690 | soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, redirectJS, strlen(redirectJS)); |
691 | } else if (g_str_equal(path, "/cancelled" )) { |
692 | soup_message_headers_set_encoding(message->response_headers, SOUP_ENCODING_CHUNKED); |
693 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); |
694 | soup_server_unpause_message(server, message); |
695 | return; |
696 | } else if (g_str_equal(path, "/do-not-track-header" ) || g_str_equal(path, "/add-do-not-track-header" )) { |
697 | const char* doNotTrack = soup_message_headers_get_one(message->request_headers, "DNT" ); |
698 | if (doNotTrack) |
699 | soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, doNotTrack, strlen(doNotTrack)); |
700 | else |
701 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kDNTHeaderNotPresent, strlen(kDNTHeaderNotPresent)); |
702 | soup_message_set_status(message, SOUP_STATUS_OK); |
703 | } else if (g_str_equal(path, "/headers" )) { |
704 | soup_message_headers_append(message->response_headers, "Foo" , "bar" ); |
705 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString)); |
706 | } else if (g_str_equal(path, "/redirect-to-data" )) { |
707 | soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY); |
708 | soup_message_headers_append(message->response_headers, "Location" , "data:text/plain;charset=utf-8,data-uri" ); |
709 | } else if (g_str_equal(path, "/unfinished-subresource-load" )) { |
710 | static const char* unfinishedSubresourceLoadResponseString = "<html><body>" |
711 | "<img src=\"/stall\"/>" |
712 | "<script>" |
713 | " function run() {" |
714 | " location = '/normal';" |
715 | " }" |
716 | " setInterval(run(), 50);" |
717 | "</script>" |
718 | "</body></html>" ; |
719 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, unfinishedSubresourceLoadResponseString, strlen(unfinishedSubresourceLoadResponseString)); |
720 | } else if (g_str_equal(path, "/stall" )) { |
721 | // This request is never unpaused and stalls forever. |
722 | soup_server_pause_message(server, message); |
723 | return; |
724 | } else |
725 | soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); |
726 | |
727 | soup_message_body_complete(message->response_body); |
728 | } |
729 | |
730 | void beforeAll() |
731 | { |
732 | bus = new WebKitTestBus(); |
733 | if (!bus->run()) |
734 | return; |
735 | |
736 | kServer = new WebKitTestServer(); |
737 | kServer->run(serverCallback); |
738 | |
739 | LoadTrackingTest::add("WebKitWebView" , "loading-status" , testLoadingStatus); |
740 | LoadTrackingTest::add("WebKitWebView" , "loading-error" , testLoadingError); |
741 | LoadTrackingTest::add("WebKitWebView" , "load-html" , testLoadHtml); |
742 | LoadTrackingTest::add("WebKitWebView" , "load-alternate-html" , testLoadAlternateHTML); |
743 | LoadTrackingTest::add("WebKitWebView" , "load-alternate-html-for-local-page" , testLoadAlternateHTMLForLocalPage); |
744 | LoadTrackingTest::add("WebKitWebView" , "load-plain-text" , testLoadPlainText); |
745 | LoadTrackingTest::add("WebKitWebView" , "load-bytes" , testLoadBytes); |
746 | LoadTrackingTest::add("WebKitWebView" , "load-request" , testLoadRequest); |
747 | LoadTrackingTest::add("WebKitWebView" , "load-gresource" , testLoadFromGResource); |
748 | LoadStopTrackingTest::add("WebKitWebView" , "stop-loading" , testLoadCancelled); |
749 | LoadTrackingTest::add("WebKitWebView" , "title" , testWebViewTitle); |
750 | LoadTrackingTest::add("WebKitWebView" , "progress" , testLoadProgress); |
751 | LoadTrackingTest::add("WebKitWebView" , "reload" , testWebViewReload); |
752 | LoadTrackingTest::add("WebKitWebView" , "history-load" , testWebViewHistoryLoad); |
753 | LoadTwiceAndReloadTest::add("WebKitWebView" , "load-twice-and-reload" , testWebViewLoadTwiceAndReload); |
754 | LoadTrackingTest::add("WebKitWebView" , "unfinished-subresource-load" , testUnfinishedSubresourceLoad); |
755 | |
756 | // This test checks that web view notify::uri signal is correctly emitted |
757 | // and the uri is already updated when loader client signals are emitted. |
758 | ViewURITrackingTest::add("WebKitWebView" , "active-uri" , testWebViewActiveURI); |
759 | |
760 | ViewIsLoadingTest::add("WebKitWebView" , "is-loading" , testWebViewIsLoading); |
761 | WebPageURITest::add("WebKitWebPage" , "get-uri" , testWebPageURI); |
762 | WebViewTest::add("WebKitURIRequest" , "http-headers" , testURIRequestHTTPHeaders); |
763 | WebViewTest::add("WebKitURIRequest" , "http-method" , testURIRequestHTTPMethod); |
764 | WebViewTest::add("WebKitURIResponse" , "http-headers" , testURIResponseHTTPHeaders); |
765 | WebViewTest::add("WebKitWebPage" , "redirect-to-data-uri" , testRedirectToDataURI); |
766 | } |
767 | |
768 | void afterAll() |
769 | { |
770 | delete bus; |
771 | delete kServer; |
772 | } |
773 | |