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
32static WebKitTestBus* bus;
33static WebKitTestServer* kServer;
34
35const char* kDNTHeaderNotPresent = "DNT header not present";
36
37static 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
51static 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
63static 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
71static 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
78static 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
85static 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
92static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
93{
94 test->loadPlainText("Hello WebKit-GTK+");
95 test->waitUntilLoadFinished();
96 assertNormalLoadHappened(test->m_loadEvents);
97}
98
99static 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
111static 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
119static 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
127class LoadStopTrackingTest : public LoadTrackingTest {
128public:
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
143static 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
156static 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
164static 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
179static 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
186static 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
206class LoadTwiceAndReloadTest : public WebViewTest {
207public:
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
236static 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
243static 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
250static 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
271class ViewURITrackingTest: public LoadTrackingTest {
272public:
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
326private:
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
338static 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
422class ViewIsLoadingTest: public LoadTrackingTest {
423public:
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
455static 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
478class WebPageURITest: public WebViewTest {
479public:
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
540static 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
575static void testURIRequestHTTPHeaders(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* headers = 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
612static 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
626static void testURIResponseHTTPHeaders(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* headers = 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
647static 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
659static 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
730void 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
768void afterAll()
769{
770 delete bus;
771 delete kServer;
772}
773