blob: 877b25e13fec91830e6e69ab4eec6b1cadd7ed5d [file] [log] [blame]
/*
* Copyright (C) 2009, 2010 Gustavo Noronha Silva
* Copyright (C) 2009, 2011 Igalia S.L.
* Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
#include "WebViewTest.h"
#include <libsoup/soup.h>
#include <wtf/Vector.h>
#include <wtf/text/CString.h>
static WebKitTestServer* kServer;
const char* kDNTHeaderNotPresent = "DNT header not present";
static void testLoadingStatus(LoadTrackingTest* test, gconstpointer data)
{
test->setRedirectURI(kServer->getURIForPath("/normal").data());
test->loadURI(kServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents;
g_assert_cmpint(events.size(), ==, 4);
g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[1], ==, LoadTrackingTest::ProvisionalLoadReceivedServerRedirect);
g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished);
}
static void testLoadingError(LoadTrackingTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/error").data());
test->waitUntilLoadFinished();
Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents;
g_assert_cmpint(events.size(), ==, 3);
g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[1], ==, LoadTrackingTest::ProvisionalLoadFailed);
g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished);
}
static void assertNormalLoadHappened(Vector<LoadTrackingTest::LoadEvents>& events)
{
g_assert_cmpint(events.size(), ==, 3);
g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFinished);
}
static void testLoadHtml(LoadTrackingTest* test, gconstpointer)
{
test->loadHtml("<html><body>Hello WebKit-GTK+</body></html>", 0);
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadAlternateHTML(LoadTrackingTest* test, gconstpointer)
{
test->loadAlternateHTML("<html><body>Alternate page</body></html>", "http://error-page.foo/", 0);
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadAlternateHTMLForLocalPage(LoadTrackingTest* test, gconstpointer)
{
test->loadAlternateHTML("<html><body>Alternate page</body></html>", "file:///not/actually/loaded.html", 0);
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
{
test->loadPlainText("Hello WebKit-GTK+");
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadBytes(LoadTrackingTest* test, gconstpointer)
{
GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
char* contents;
gsize contentsLength;
g_file_get_contents(filePath.get(), &contents, &contentsLength, nullptr);
GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_take(contents, contentsLength));
test->loadBytes(bytes.get(), "image/vnd.microsoft.icon", nullptr, nullptr);
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data()));
test->loadRequest(request.get());
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadFromGResource(LoadTrackingTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> request(webkit_uri_request_new("resource:///org/webkit/glib/tests/boring.html"));
test->loadRequest(request.get());
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
class LoadStopTrackingTest : public LoadTrackingTest {
public:
MAKE_GLIB_TEST_FIXTURE(LoadStopTrackingTest);
virtual void loadCommitted()
{
LoadTrackingTest::loadCommitted();
webkit_web_view_stop_loading(m_webView);
}
virtual void loadFailed(const gchar* failingURI, GError* error)
{
g_assert_error(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED);
LoadTrackingTest::loadFailed(failingURI, error);
}
};
static void testLoadCancelled(LoadStopTrackingTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/cancelled").data());
test->waitUntilLoadFinished();
Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents;
g_assert_cmpint(events.size(), ==, 4);
g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFailed);
g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished);
}
static void testWebViewTitle(LoadTrackingTest* test, gconstpointer)
{
g_assert_null(webkit_web_view_get_title(test->m_webView));
test->loadHtml("<html><head><title>Welcome to WebKit-GTK+!</title></head></html>", 0);
test->waitUntilLoadFinished();
g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "Welcome to WebKit-GTK+!");
}
static void testWebViewReload(LoadTrackingTest* test, gconstpointer)
{
// Check that nothing happens when there's nothing to reload.
test->reload();
test->wait(0.25); // Wait for a quarter of a second.
test->loadURI(kServer->getURIForPath("/normal").data());
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
test->reload();
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
static void testLoadProgress(LoadTrackingTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/normal").data());
test->waitUntilLoadFinished();
g_assert_cmpfloat(test->m_estimatedProgress, ==, 1);
}
static void testWebViewHistoryLoad(LoadTrackingTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/normal").data());
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
test->loadURI(kServer->getURIForPath("/normal2").data());
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
// Check that load process is the same for pages loaded from history cache.
test->goBack();
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
test->goForward();
test->waitUntilLoadFinished();
assertNormalLoadHappened(test->m_loadEvents);
}
class LoadTwiceAndReloadTest : public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(LoadTwiceAndReloadTest);
static void reloadOnFinishLoad(WebKitWebView* view, WebKitLoadEvent loadEvent, LoadTwiceAndReloadTest* test)
{
if (++test->m_loadsCount == 3)
test->quitMainLoop();
webkit_web_view_reload(view);
}
LoadTwiceAndReloadTest()
{
g_signal_connect(m_webView, "load-changed", G_CALLBACK(reloadOnFinishLoad), this);
}
~LoadTwiceAndReloadTest()
{
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
}
void waitUntilFinished()
{
m_loadsCount = 0;
g_main_loop_run(m_mainLoop);
}
unsigned m_loadsCount { 0 };
};
static void testWebViewLoadTwiceAndReload(LoadTwiceAndReloadTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/normal").data());
test->loadURI(kServer->getURIForPath("/normal2").data());
test->waitUntilFinished();
}
static void uriChanged(WebKitWebView* webView, GParamSpec*, LoadTrackingTest* test)
{
const char* uri = webkit_web_view_get_uri(webView);
if (g_str_has_suffix(uri, "/normal"))
test->m_activeURI = uri;
}
static void testUnfinishedSubresourceLoad(LoadTrackingTest* test, gconstpointer)
{
// Verify that LoadFinished occurs even if the next load starts before the
// previous load actually finishes.
test->loadURI(kServer->getURIForPath("/unfinished-subresource-load").data());
auto signalID = g_signal_connect(test->m_webView, "notify::uri", G_CALLBACK(uriChanged), test);
test->waitUntilLoadFinished();
test->waitUntilLoadFinished();
g_signal_handler_disconnect(test->m_webView, signalID);
Vector<LoadTrackingTest::LoadEvents>& events = test->m_loadEvents;
g_assert_cmpint(events.size(), ==, 7);
g_assert_cmpint(events[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[1], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(events[2], ==, LoadTrackingTest::LoadFailed);
g_assert_cmpint(events[3], ==, LoadTrackingTest::LoadFinished);
g_assert_cmpint(events[4], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(events[5], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(events[6], ==, LoadTrackingTest::LoadFinished);
}
class ViewURITrackingTest: public LoadTrackingTest {
public:
MAKE_GLIB_TEST_FIXTURE(ViewURITrackingTest);
static void uriChanged(GObject*, GParamSpec*, ViewURITrackingTest* test)
{
g_assert_cmpstr(test->m_currentURI.data(), !=, webkit_web_view_get_uri(test->m_webView));
test->m_currentURI = webkit_web_view_get_uri(test->m_webView);
}
ViewURITrackingTest()
: m_currentURI(webkit_web_view_get_uri(m_webView))
{
g_assert_true(m_currentURI.isNull());
m_currentURIList.grow(m_currentURIList.capacity());
g_signal_connect(m_webView, "notify::uri", G_CALLBACK(uriChanged), this);
}
enum State { Provisional, ProvisionalAfterRedirect, Commited, Finished };
void loadURI(const char* uri)
{
reset();
LoadTrackingTest::loadURI(uri);
}
void loadURIAndRedirectOnCommitted(const char* uri, const char* redirectURI)
{
reset();
m_uriToLoadOnCommitted = redirectURI;
LoadTrackingTest::loadURI(uri);
}
void provisionalLoadStarted()
{
m_currentURIList[Provisional] = m_currentURI;
}
void provisionalLoadReceivedServerRedirect()
{
m_currentURIList[ProvisionalAfterRedirect] = m_currentURI;
}
void loadCommitted()
{
m_currentURIList[Commited] = m_currentURI;
if (!m_uriToLoadOnCommitted.isNull()) {
m_estimatedProgress = 0;
m_activeURI = m_uriToLoadOnCommitted;
webkit_web_view_load_uri(m_webView, m_uriToLoadOnCommitted.data());
}
}
void loadFinished()
{
m_currentURIList[Finished] = m_currentURI;
LoadTrackingTest::loadFinished();
if (!m_uriToLoadOnCommitted.isNull())
m_uriToLoadOnCommitted = { };
}
void checkURIAtState(State state, const char* path)
{
if (path)
ASSERT_CMP_CSTRING(m_currentURIList[state], ==, kServer->getURIForPath(path));
else
g_assert_true(m_currentURIList[state].isNull());
}
private:
void reset()
{
m_currentURI = { };
m_uriToLoadOnCommitted = { };
m_currentURIList.clear();
m_currentURIList.grow(m_currentURIList.capacity());
}
CString m_currentURI;
CString m_uriToLoadOnCommitted;
Vector<CString, 4> m_currentURIList;
};
static void testWebViewActiveURI(ViewURITrackingTest* test, gconstpointer)
{
// Normal load, the URL doesn't change.
test->loadURI(kServer->getURIForPath("/normal1").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal1");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal1");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal1");
// Redirect, the URL changes after the redirect.
test->loadURI(kServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal");
// Normal load, URL changed by WebKitPage::send-request.
test->loadURI(kServer->getURIForPath("/normal-change-request").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed");
// Redirect, URL changed by WebKitPage::send-request.
test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-to-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect");
// Non-API request loads.
test->loadURI(kServer->getURIForPath("/redirect-js/normal").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/normal");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/normal");
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal");
test->loadURI(kServer->getURIForPath("/redirect-js/redirect").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/redirect");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/redirect");
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal");
test->loadURI(kServer->getURIForPath("/redirect-js/normal-change-request").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/normal-change-request");
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed");
test->loadURI(kServer->getURIForPath("/redirect-js/redirect-to-change-request").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect-to-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/redirect-js/redirect-to-change-request");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/redirect-js/redirect-to-change-request");
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-js/redirect-to-change-request");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request");
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect");
test->loadURIAndRedirectOnCommitted(kServer->getURIForPath("/normal").data(), kServer->getURIForPath("/headers").data());
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal");
// Pending API request is always updated immedately.
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/headers");
test->waitUntilLoadFinished();
test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/headers");
test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
test->checkURIAtState(ViewURITrackingTest::State::Commited, "/headers");
test->checkURIAtState(ViewURITrackingTest::State::Finished, "/headers");
}
class ViewIsLoadingTest: public LoadTrackingTest {
public:
MAKE_GLIB_TEST_FIXTURE(ViewIsLoadingTest);
static void isLoadingChanged(GObject*, GParamSpec*, ViewIsLoadingTest* test)
{
if (webkit_web_view_is_loading(test->m_webView))
test->beginLoad();
else
test->endLoad();
}
ViewIsLoadingTest()
{
g_signal_connect(m_webView, "notify::is-loading", G_CALLBACK(isLoadingChanged), this);
}
void beginLoad()
{
// New load, load-started hasn't been emitted yet.
g_assert_true(m_loadEvents.isEmpty());
g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void endLoad()
{
// Load finish, load-finished and load-failed haven't been emitted yet.
g_assert_false(m_loadEvents.isEmpty());
g_assert_false(m_loadEvents.contains(LoadTrackingTest::LoadFinished));
g_assert_false(m_loadEvents.contains(LoadTrackingTest::LoadFailed));
}
};
static void testWebViewIsLoading(ViewIsLoadingTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/normal").data());
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->reload();
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->loadURI(kServer->getURIForPath("/error").data());
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->loadURI(kServer->getURIForPath("/normal").data());
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->loadURI(kServer->getURIForPath("/normal2").data());
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->goBack();
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->goForward();
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
test->loadAlternateHTML("<html><head><title>Title</title></head></html>", "file:///foo", nullptr);
test->waitUntilLoadFinished();
g_assert_false(webkit_web_view_is_loading(test->m_webView));
}
class WebPageURITest: public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(WebPageURITest);
static void webPageURIChangedCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebPageURITest* test)
{
const char* uri;
g_variant_get(result, "(&s)", &uri);
test->m_webPageURIs.append(uri);
}
static void webViewURIChanged(GObject*, GParamSpec*, WebPageURITest* test)
{
test->m_webViewURIs.append(webkit_web_view_get_uri(test->m_webView));
}
WebPageURITest()
{
m_proxy = extensionProxy();
m_uriChangedSignalID = g_dbus_connection_signal_subscribe(
g_dbus_proxy_get_connection(m_proxy.get()),
0,
"org.webkit.gtk.WebExtensionTest",
"URIChanged",
"/org/webkit/gtk/WebExtensionTest",
0,
G_DBUS_SIGNAL_FLAGS_NONE,
reinterpret_cast<GDBusSignalCallback>(webPageURIChangedCallback),
this,
0);
g_assert_cmpuint(m_uriChangedSignalID, !=, 0);
g_signal_connect(m_webView, "notify::uri", G_CALLBACK(webViewURIChanged), this);
}
~WebPageURITest()
{
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(m_proxy.get()), m_uriChangedSignalID);
}
void loadURI(const char* uri)
{
m_webPageURIs.clear();
m_webViewURIs.clear();
WebViewTest::loadURI(uri);
}
void checkViewAndPageURIsMatch() const
{
g_assert_cmpint(m_webPageURIs.size(), ==, m_webViewURIs.size());
for (size_t i = 0; i < m_webPageURIs.size(); ++i)
ASSERT_CMP_CSTRING(m_webPageURIs[i], ==, m_webViewURIs[i]);
}
GRefPtr<GDBusProxy> m_proxy;
unsigned m_uriChangedSignalID;
Vector<CString> m_webPageURIs;
Vector<CString> m_webViewURIs;
};
static void testWebPageURI(WebPageURITest* test, gconstpointer)
{
// Normal load.
test->loadURI(kServer->getURIForPath("/normal1").data());
test->waitUntilLoadFinished();
test->checkViewAndPageURIsMatch();
g_assert_cmpint(test->m_webPageURIs.size(), ==, 1);
ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal1"));
// Redirect
test->loadURI(kServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
test->checkViewAndPageURIsMatch();
g_assert_cmpint(test->m_webPageURIs.size(), ==, 2);
ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect"));
ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal"));
// Normal load, URL changed by WebKitPage::send-request.
test->loadURI(kServer->getURIForPath("/normal-change-request").data());
test->waitUntilLoadFinished();
test->checkViewAndPageURIsMatch();
g_assert_cmpint(test->m_webPageURIs.size(), ==, 2);
ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal-change-request"));
ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/request-changed"));
// Redirect, URL changed by WebKitPage::send-request.
test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data());
test->waitUntilLoadFinished();
test->checkViewAndPageURIsMatch();
g_assert_cmpint(test->m_webPageURIs.size(), ==, 3);
ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect-to-change-request"));
ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal-change-request"));
ASSERT_CMP_CSTRING(test->m_webPageURIs[2], ==, kServer->getURIForPath("/request-changed-on-redirect"));
}
static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar"));
g_assert_nonnull(uriRequest.get());
g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar");
g_assert_null(webkit_uri_request_get_http_headers(uriRequest.get()));
// Load a request with no Do Not Track header.
webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/do-not-track-header").data());
test->loadRequest(uriRequest.get());
test->waitUntilLoadFinished();
size_t mainResourceDataSize = 0;
const char* mainResourceData = test->mainResourceData(mainResourceDataSize);
g_assert_cmpint(mainResourceDataSize, ==, strlen(kDNTHeaderNotPresent));
g_assert_cmpint(strncmp(mainResourceData, kDNTHeaderNotPresent, mainResourceDataSize), ==, 0);
// Add the Do Not Track header and load the request again.
SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(uriRequest.get());
g_assert_nonnull(headers);
soup_message_headers_append(headers, "DNT", "1");
test->loadRequest(uriRequest.get());
test->waitUntilLoadFinished();
mainResourceData = test->mainResourceData(mainResourceDataSize);
g_assert_cmpint(mainResourceDataSize, ==, 1);
g_assert_cmpint(strncmp(mainResourceData, "1", mainResourceDataSize), ==, 0);
// Load a URI for which the web extension will add the Do Not Track header.
test->loadURI(kServer->getURIForPath("/add-do-not-track-header").data());
test->waitUntilLoadFinished();
mainResourceData = test->mainResourceData(mainResourceDataSize);
g_assert_cmpint(mainResourceDataSize, ==, 1);
g_assert_cmpint(strncmp(mainResourceData, "1", mainResourceDataSize), ==, 0);
}
static void testURIRequestHTTPMethod(WebViewTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar"));
g_assert_nonnull(uriRequest.get());
g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar");
g_assert_null(webkit_uri_request_get_http_method(uriRequest.get()));
webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/http-get-method").data());
test->loadRequest(uriRequest.get());
test->waitUntilLoadFinished();
test->runJavaScriptAndWaitUntilFinished("xhr = new XMLHttpRequest; xhr.open('POST', '/http-post-method', false); xhr.send();", nullptr);
}
static void testURIResponseHTTPHeaders(WebViewTest* test, gconstpointer)
{
test->loadHtml("<html><body>No HTTP headers</body></html>", "file:///");
test->waitUntilLoadFinished();
WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
g_assert_true(WEBKIT_IS_WEB_RESOURCE(resource));
WebKitURIResponse* response = webkit_web_resource_get_response(resource);
g_assert_true(WEBKIT_IS_URI_RESPONSE(response));
g_assert_null(webkit_uri_response_get_http_headers(response));
test->loadURI(kServer->getURIForPath("/headers").data());
test->waitUntilLoadFinished();
resource = webkit_web_view_get_main_resource(test->m_webView);
g_assert_true(WEBKIT_IS_WEB_RESOURCE(resource));
response = webkit_web_resource_get_response(resource);
g_assert_true(WEBKIT_IS_URI_RESPONSE(response));
SoupMessageHeaders* headers = webkit_uri_response_get_http_headers(response);
g_assert_nonnull(headers);
g_assert_cmpstr(soup_message_headers_get_one(headers, "Foo"), ==, "bar");
}
static void testRedirectToDataURI(WebViewTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/redirect-to-data").data());
test->waitUntilLoadFinished();
static const char* expectedData = "data-uri";
size_t mainResourceDataSize = 0;
const char* mainResourceData = test->mainResourceData(mainResourceDataSize);
g_assert_cmpint(mainResourceDataSize, ==, strlen(expectedData));
g_assert_cmpint(strncmp(mainResourceData, expectedData, mainResourceDataSize), ==, 0);
}
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
static const char* responseString = "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
"Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>";
if (message->method != SOUP_METHOD_GET) {
soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
return;
}
soup_message_set_status(message, SOUP_STATUS_OK);
if (g_str_has_prefix(path, "/normal") || g_str_has_prefix(path, "/http-get-method"))
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
else if (g_str_equal(path, "/error"))
soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
else if (g_str_equal(path, "/redirect")) {
soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
soup_message_headers_append(message->response_headers, "Location", "/normal");
} else if (g_str_equal(path, "/redirect-to-change-request")) {
soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
soup_message_headers_append(message->response_headers, "Location", "/normal-change-request");
} else if (g_str_has_prefix(path, "/redirect-js/")) {
static const char* redirectJSFormat = "<html><body><script>location = '%s';</script></body></html>";
char* redirectJS = g_strdup_printf(redirectJSFormat, g_strrstr(path, "/"));
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, redirectJS, strlen(redirectJS));
} else if (g_str_equal(path, "/cancelled")) {
soup_message_headers_set_encoding(message->response_headers, SOUP_ENCODING_CHUNKED);
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
soup_server_unpause_message(server, message);
return;
} else if (g_str_equal(path, "/do-not-track-header") || g_str_equal(path, "/add-do-not-track-header")) {
const char* doNotTrack = soup_message_headers_get_one(message->request_headers, "DNT");
if (doNotTrack)
soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, doNotTrack, strlen(doNotTrack));
else
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kDNTHeaderNotPresent, strlen(kDNTHeaderNotPresent));
soup_message_set_status(message, SOUP_STATUS_OK);
} else if (g_str_equal(path, "/headers")) {
soup_message_headers_append(message->response_headers, "Foo", "bar");
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
} else if (g_str_equal(path, "/redirect-to-data")) {
soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
soup_message_headers_append(message->response_headers, "Location", "data:text/plain;charset=utf-8,data-uri");
} else if (g_str_equal(path, "/unfinished-subresource-load")) {
static const char* unfinishedSubresourceLoadResponseString = "<html><body>"
"<img src=\"/stall\"/>"
"<script>"
" function run() {"
" location = '/normal';"
" }"
" setInterval(run(), 50);"
"</script>"
"</body></html>";
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, unfinishedSubresourceLoadResponseString, strlen(unfinishedSubresourceLoadResponseString));
} else if (g_str_equal(path, "/stall")) {
// This request is never unpaused and stalls forever.
soup_server_pause_message(server, message);
return;
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
soup_message_body_complete(message->response_body);
}
void beforeAll()
{
kServer = new WebKitTestServer();
kServer->run(serverCallback);
LoadTrackingTest::add("WebKitWebView", "loading-status", testLoadingStatus);
LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError);
LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml);
LoadTrackingTest::add("WebKitWebView", "load-alternate-html", testLoadAlternateHTML);
LoadTrackingTest::add("WebKitWebView", "load-alternate-html-for-local-page", testLoadAlternateHTMLForLocalPage);
LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText);
LoadTrackingTest::add("WebKitWebView", "load-bytes", testLoadBytes);
LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest);
LoadTrackingTest::add("WebKitWebView", "load-gresource", testLoadFromGResource);
LoadStopTrackingTest::add("WebKitWebView", "stop-loading", testLoadCancelled);
LoadTrackingTest::add("WebKitWebView", "title", testWebViewTitle);
LoadTrackingTest::add("WebKitWebView", "progress", testLoadProgress);
LoadTrackingTest::add("WebKitWebView", "reload", testWebViewReload);
LoadTrackingTest::add("WebKitWebView", "history-load", testWebViewHistoryLoad);
LoadTwiceAndReloadTest::add("WebKitWebView", "load-twice-and-reload", testWebViewLoadTwiceAndReload);
LoadTrackingTest::add("WebKitWebView", "unfinished-subresource-load", testUnfinishedSubresourceLoad);
// This test checks that web view notify::uri signal is correctly emitted
// and the uri is already updated when loader client signals are emitted.
ViewURITrackingTest::add("WebKitWebView", "active-uri", testWebViewActiveURI);
ViewIsLoadingTest::add("WebKitWebView", "is-loading", testWebViewIsLoading);
WebPageURITest::add("WebKitWebPage", "get-uri", testWebPageURI);
WebViewTest::add("WebKitURIRequest", "http-headers", testURIRequestHTTPHeaders);
WebViewTest::add("WebKitURIRequest", "http-method", testURIRequestHTTPMethod);
WebViewTest::add("WebKitURIResponse", "http-headers", testURIResponseHTTPHeaders);
WebViewTest::add("WebKitWebPage", "redirect-to-data-uri", testRedirectToDataURI);
}
void afterAll()
{
delete kServer;
}