[GTK] Add webkit_uri_response_get_http_headers to WebKit2 GTK+ API
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKit2Gtk / TestLoaderClient.cpp
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 <gtk/gtk.h>
29 #include <libsoup/soup.h>
30 #include <wtf/text/CString.h>
31
32 static WebKitTestBus* bus;
33 static WebKitTestServer* kServer;
34
35 const char* kDNTHeaderNotPresent = "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 testLoadPlainText(LoadTrackingTest* test, gconstpointer)
86 {
87     test->loadPlainText("Hello WebKit-GTK+");
88     test->waitUntilLoadFinished();
89     assertNormalLoadHappened(test->m_loadEvents);
90 }
91
92 static void testLoadBytes(LoadTrackingTest* test, gconstpointer)
93 {
94     GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
95     char* contents;
96     gsize contentsLength;
97     g_file_get_contents(filePath.get(), &contents, &contentsLength, nullptr);
98     GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_take(contents, contentsLength));
99     test->loadBytes(bytes.get(), "image/vnd.microsoft.icon", nullptr, nullptr);
100     test->waitUntilLoadFinished();
101     assertNormalLoadHappened(test->m_loadEvents);
102 }
103
104 static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
105 {
106     GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data()));
107     test->loadRequest(request.get());
108     test->waitUntilLoadFinished();
109     assertNormalLoadHappened(test->m_loadEvents);
110 }
111
112 class LoadStopTrackingTest : public LoadTrackingTest {
113 public:
114     MAKE_GLIB_TEST_FIXTURE(LoadStopTrackingTest);
115
116     virtual void loadCommitted()
117     {
118         LoadTrackingTest::loadCommitted();
119         webkit_web_view_stop_loading(m_webView);
120     }
121     virtual void loadFailed(const gchar* failingURI, GError* error)
122     {
123         g_assert(g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED));
124         LoadTrackingTest::loadFailed(failingURI, error);
125     }
126 };
127
128 static void testLoadCancelled(LoadStopTrackingTest* test, gconstpointer)
129 {
130     test->loadURI(kServer->getURIForPath("/cancelled").data());
131     test->waitUntilLoadFinished();
132
133     Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents;
134     g_assert_cmpint(events.size(), ==, 4);
135     g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
136     g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted);
137     g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFailed);
138     g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished);
139 }
140
141 static void testWebViewTitle(LoadTrackingTest* test, gconstpointer)
142 {
143     g_assert(!webkit_web_view_get_title(test->m_webView));
144     test->loadHtml("<html><head><title>Welcome to WebKit-GTK+!</title></head></html>", 0);
145     test->waitUntilLoadFinished();
146     g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "Welcome to WebKit-GTK+!");
147 }
148
149 static void testWebViewReload(LoadTrackingTest* test, gconstpointer)
150 {
151     // Check that nothing happens when there's nothing to reload.
152     test->reload();
153     test->wait(0.25); // Wait for a quarter of a second.
154
155     test->loadURI(kServer->getURIForPath("/normal").data());
156     test->waitUntilLoadFinished();
157     assertNormalLoadHappened(test->m_loadEvents);
158
159     test->reload();
160     test->waitUntilLoadFinished();
161     assertNormalLoadHappened(test->m_loadEvents);
162 }
163
164 static void testLoadProgress(LoadTrackingTest* test, gconstpointer)
165 {
166     test->loadURI(kServer->getURIForPath("/normal").data());
167     test->waitUntilLoadFinished();
168     g_assert_cmpfloat(test->m_estimatedProgress, ==, 1);
169 }
170
171 static void testWebViewHistoryLoad(LoadTrackingTest* test, gconstpointer)
172 {
173     test->loadURI(kServer->getURIForPath("/normal").data());
174     test->waitUntilLoadFinished();
175     assertNormalLoadHappened(test->m_loadEvents);
176
177     test->loadURI(kServer->getURIForPath("/normal2").data());
178     test->waitUntilLoadFinished();
179     assertNormalLoadHappened(test->m_loadEvents);
180
181     // Check that load process is the same for pages loaded from history cache.
182     test->goBack();
183     test->waitUntilLoadFinished();
184     assertNormalLoadHappened(test->m_loadEvents);
185
186     test->goForward();
187     test->waitUntilLoadFinished();
188     assertNormalLoadHappened(test->m_loadEvents);
189 }
190
191 class ViewURITrackingTest: public LoadTrackingTest {
192 public:
193     MAKE_GLIB_TEST_FIXTURE(ViewURITrackingTest);
194
195     static void uriChanged(GObject*, GParamSpec*, ViewURITrackingTest* test)
196     {
197         g_assert_cmpstr(test->m_activeURI.data(), !=, webkit_web_view_get_uri(test->m_webView));
198         test->m_activeURI = webkit_web_view_get_uri(test->m_webView);
199     }
200
201     ViewURITrackingTest()
202         : m_activeURI(webkit_web_view_get_uri(m_webView))
203     {
204         g_assert(m_activeURI.isNull());
205         g_signal_connect(m_webView, "notify::uri", G_CALLBACK(uriChanged), this);
206     }
207
208     void provisionalLoadStarted()
209     {
210         checkActiveURI("/redirect");
211     }
212
213     void provisionalLoadReceivedServerRedirect()
214     {
215         checkActiveURI("/normal");
216     }
217
218     void loadCommitted()
219     {
220         checkActiveURI("/normal");
221     }
222
223     void loadFinished()
224     {
225         checkActiveURI("/normal");
226         LoadTrackingTest::loadFinished();
227     }
228
229     CString m_activeURI;
230
231 private:
232     void checkActiveURI(const char* uri)
233     {
234         ASSERT_CMP_CSTRING(m_activeURI, ==, kServer->getURIForPath(uri));
235     }
236 };
237
238 static void testWebViewActiveURI(ViewURITrackingTest* test, gconstpointer)
239 {
240     test->loadURI(kServer->getURIForPath("/redirect").data());
241     test->waitUntilLoadFinished();
242 }
243
244 class ViewIsLoadingTest: public LoadTrackingTest {
245 public:
246     MAKE_GLIB_TEST_FIXTURE(ViewIsLoadingTest);
247
248     static void isLoadingChanged(GObject*, GParamSpec*, ViewIsLoadingTest* test)
249     {
250         if (webkit_web_view_is_loading(test->m_webView))
251             test->beginLoad();
252         else
253             test->endLoad();
254     }
255
256     ViewIsLoadingTest()
257     {
258         g_signal_connect(m_webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), this);
259     }
260
261     void beginLoad()
262     {
263         // New load, load-started hasn't been emitted yet.
264         g_assert(m_loadEvents.isEmpty());
265         g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
266     }
267
268     void endLoad()
269     {
270         // Load finish, load-finished and load-failed haven't been emitted yet.
271         g_assert(!m_loadEvents.isEmpty());
272         g_assert(!m_loadEvents.contains(LoadTrackingTest::LoadFinished));
273         g_assert(!m_loadEvents.contains(LoadTrackingTest::LoadFailed));
274     }
275 };
276
277 static void testWebViewIsLoading(ViewIsLoadingTest* test, gconstpointer)
278 {
279     test->loadURI(kServer->getURIForPath("/normal").data());
280     test->waitUntilLoadFinished();
281
282     test->reload();
283     test->waitUntilLoadFinished();
284
285     test->loadURI(kServer->getURIForPath("/error").data());
286     test->waitUntilLoadFinished();
287
288     test->loadURI(kServer->getURIForPath("/normal").data());
289     test->waitUntilLoadFinished();
290     test->loadURI(kServer->getURIForPath("/normal2").data());
291     test->waitUntilLoadFinished();
292
293     test->goBack();
294     test->waitUntilLoadFinished();
295
296     test->goForward();
297     test->waitUntilLoadFinished();
298 }
299
300 class WebPageURITest: public WebViewTest {
301 public:
302     MAKE_GLIB_TEST_FIXTURE(WebPageURITest);
303
304     static void webPageURIChangedCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebPageURITest* test)
305     {
306         const char* uri;
307         g_variant_get(result, "(&s)", &uri);
308         test->m_webPageURIs.append(uri);
309     }
310
311     static void webViewURIChanged(GObject*, GParamSpec*, WebPageURITest* test)
312     {
313         test->m_webViewURIs.append(webkit_web_view_get_uri(test->m_webView));
314     }
315
316     WebPageURITest()
317     {
318         GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
319             "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", m_mainLoop));
320         m_uriChangedSignalID = g_dbus_connection_signal_subscribe(
321             g_dbus_proxy_get_connection(proxy.get()),
322             0,
323             "org.webkit.gtk.WebExtensionTest",
324             "URIChanged",
325             "/org/webkit/gtk/WebExtensionTest",
326             0,
327             G_DBUS_SIGNAL_FLAGS_NONE,
328             reinterpret_cast<GDBusSignalCallback>(webPageURIChangedCallback),
329             this,
330             0);
331         g_assert(m_uriChangedSignalID);
332
333         g_signal_connect(m_webView, "notify::uri", G_CALLBACK(webViewURIChanged), this);
334     }
335
336     ~WebPageURITest()
337     {
338         g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
339         g_dbus_connection_signal_unsubscribe(bus->connection(), m_uriChangedSignalID);
340     }
341
342     unsigned m_uriChangedSignalID;
343     Vector<CString> m_webPageURIs;
344     Vector<CString> m_webViewURIs;
345 };
346
347 static void testWebPageURI(WebPageURITest* test, gconstpointer)
348 {
349     test->loadURI(kServer->getURIForPath("/redirect").data());
350     test->waitUntilLoadFinished();
351
352     g_assert_cmpint(test->m_webPageURIs.size(), ==, test->m_webViewURIs.size());
353     for (size_t i = 0; i < test->m_webPageURIs.size(); ++i)
354         ASSERT_CMP_CSTRING(test->m_webPageURIs[i], ==, test->m_webViewURIs[i]);
355
356     g_assert_cmpint(test->m_webPageURIs.size(), ==, 2);
357     ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect"));
358     ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal"));
359
360 }
361
362 static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer)
363 {
364     GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar"));
365     g_assert(uriRequest.get());
366     g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar");
367     g_assert(!webkit_uri_request_get_http_headers(uriRequest.get()));
368
369     // Load a request with no Do Not Track header.
370     webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/do-not-track-header").data());
371     test->loadRequest(uriRequest.get());
372     test->waitUntilLoadFinished();
373
374     size_t mainResourceDataSize = 0;
375     const char* mainResourceData = test->mainResourceData(mainResourceDataSize);
376     g_assert_cmpint(mainResourceDataSize, ==, strlen(kDNTHeaderNotPresent));
377     g_assert(!strncmp(mainResourceData, kDNTHeaderNotPresent, mainResourceDataSize));
378
379     // Add the Do Not Track header and load the request again.
380     SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(uriRequest.get());
381     g_assert(headers);
382     soup_message_headers_append(headers, "DNT", "1");
383     test->loadRequest(uriRequest.get());
384     test->waitUntilLoadFinished();
385
386     mainResourceData = test->mainResourceData(mainResourceDataSize);
387     g_assert_cmpint(mainResourceDataSize, ==, 1);
388     g_assert(!strncmp(mainResourceData, "1", mainResourceDataSize));
389
390     // Load a URI for which the web extension will add the Do Not Track header.
391     test->loadURI(kServer->getURIForPath("/add-do-not-track-header").data());
392     test->waitUntilLoadFinished();
393
394     mainResourceData = test->mainResourceData(mainResourceDataSize);
395     g_assert_cmpint(mainResourceDataSize, ==, 1);
396     g_assert(!strncmp(mainResourceData, "1", mainResourceDataSize));
397 }
398
399 static void testURIResponseHTTPHeaders(WebViewTest* test, gconstpointer)
400 {
401     test->loadHtml("<html><body>No HTTP headers</body></html>", "file:///");
402     test->waitUntilLoadFinished();
403     WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
404     g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
405     WebKitURIResponse* response = webkit_web_resource_get_response(resource);
406     g_assert(WEBKIT_IS_URI_RESPONSE(response));
407     g_assert(!webkit_uri_response_get_http_headers(response));
408
409     test->loadURI(kServer->getURIForPath("/headers").data());
410     test->waitUntilLoadFinished();
411     resource = webkit_web_view_get_main_resource(test->m_webView);
412     g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
413     response = webkit_web_resource_get_response(resource);
414     g_assert(WEBKIT_IS_URI_RESPONSE(response));
415     SoupMessageHeaders* headers = webkit_uri_response_get_http_headers(response);
416     g_assert(headers);
417     g_assert_cmpstr(soup_message_headers_get_one(headers, "Foo"), ==, "bar");
418 }
419
420 static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
421 {
422     static const char* responseString = "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
423         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
424         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
425         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
426         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
427         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
428         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
429         "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>";
430
431     if (message->method != SOUP_METHOD_GET) {
432         soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
433         return;
434     }
435
436     soup_message_set_status(message, SOUP_STATUS_OK);
437
438     if (g_str_has_prefix(path, "/normal"))
439         soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
440     else if (g_str_equal(path, "/error"))
441         soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
442     else if (g_str_equal(path, "/redirect")) {
443         soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
444         soup_message_headers_append(message->response_headers, "Location", "/normal");
445     } else if (g_str_equal(path, "/cancelled")) {
446         soup_message_headers_set_encoding(message->response_headers, SOUP_ENCODING_CHUNKED);
447         soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
448         soup_server_unpause_message(server, message);
449         return;
450     } else if (g_str_equal(path, "/do-not-track-header") || g_str_equal(path, "/add-do-not-track-header")) {
451         const char* doNotTrack = soup_message_headers_get_one(message->request_headers, "DNT");
452         if (doNotTrack)
453             soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, doNotTrack, strlen(doNotTrack));
454         else
455             soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kDNTHeaderNotPresent, strlen(kDNTHeaderNotPresent));
456         soup_message_set_status(message, SOUP_STATUS_OK);
457     } else if (g_str_equal(path, "/headers")) {
458         soup_message_headers_append(message->response_headers, "Foo", "bar");
459         soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
460     } else
461         soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
462
463     soup_message_body_complete(message->response_body);
464 }
465
466 void beforeAll()
467 {
468     webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
469     bus = new WebKitTestBus();
470     if (!bus->run())
471         return;
472
473     kServer = new WebKitTestServer();
474     kServer->run(serverCallback);
475
476     LoadTrackingTest::add("WebKitWebView", "loading-status", testLoadingStatus);
477     LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError);
478     LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml);
479     LoadTrackingTest::add("WebKitWebView", "load-alternate-html", testLoadAlternateHTML);
480     LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText);
481     LoadTrackingTest::add("WebKitWebView", "load-bytes", testLoadBytes);
482     LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest);
483     LoadStopTrackingTest::add("WebKitWebView", "stop-loading", testLoadCancelled);
484     LoadTrackingTest::add("WebKitWebView", "title", testWebViewTitle);
485     LoadTrackingTest::add("WebKitWebView", "progress", testLoadProgress);
486     LoadTrackingTest::add("WebKitWebView", "reload", testWebViewReload);
487     LoadTrackingTest::add("WebKitWebView", "history-load", testWebViewHistoryLoad);
488
489     // This test checks that web view notify::uri signal is correctly emitted
490     // and the uri is already updated when loader client signals are emitted.
491     ViewURITrackingTest::add("WebKitWebView", "active-uri", testWebViewActiveURI);
492
493     ViewIsLoadingTest::add("WebKitWebView", "is-loading", testWebViewIsLoading);
494     WebPageURITest::add("WebKitWebPage", "get-uri", testWebPageURI);
495     WebViewTest::add("WebKitURIRequest", "http-headers", testURIRequestHTTPHeaders);
496     WebViewTest::add("WebKitURIResponse", "http-headers", testURIResponseHTTPHeaders);
497 }
498
499 void afterAll()
500 {
501     delete bus;
502     delete kServer;
503 }