/*
 * Copyright (C) 2012 Igalia S.L.
 * Copyright (C) 2017 Endless Mobile, Inc.
 *
 * 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 "WebKitTestServer.h"
#include "WebViewTest.h"
#include <WebCore/GUniquePtrSoup.h>
#include <glib/gstdio.h>

static WebKitTestServer* kServer;

static const char* kFirstPartyDomain = "127.0.0.1";
static const char* kThirdPartyDomain = "localhost";

static const char* kCookieName = "foo";
static const char* kCookieValue = "bar";
static const char* kCookiePath = "/";

static const char* kCookiePathNew = "/new";
static const char* kCookieValueNew = "new-value";

static const char* kIndexHtmlFormat =
    "<html><body>"
    " <p>WebKitGTK+ Cookie Manager test</p>"
    " <img src='http://localhost:%u/image.png' width=5 height=5></img>"
    "</body></html>";

class CookieManagerTest: public WebViewTest {
public:
    MAKE_GLIB_TEST_FIXTURE(CookieManagerTest);

    static void cookiesChangedCallback(WebKitCookieManager*, CookieManagerTest* test)
    {
        test->m_cookiesChanged = true;
        if (test->m_finishLoopWhenCookiesChange && !(--test->m_cookiesExpectedToChangeCount))
            g_main_loop_quit(test->m_mainLoop);
    }

    CookieManagerTest()
        : WebViewTest()
        , m_cookieManager(webkit_web_context_get_cookie_manager(m_webContext.get()))
    {
        g_assert_true(webkit_website_data_manager_get_cookie_manager(webkit_web_context_get_website_data_manager(m_webContext.get())) == m_cookieManager);
        g_signal_connect(m_cookieManager, "changed", G_CALLBACK(cookiesChangedCallback), this);
    }

    ~CookieManagerTest()
    {
        g_strfreev(m_domains);
        g_list_free_full(m_cookies, reinterpret_cast<GDestroyNotify>(soup_cookie_free));

        g_signal_handlers_disconnect_matched(m_cookieManager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
        if (m_cookiesTextFile)
            g_unlink(m_cookiesTextFile.get());
        if (m_cookiesSQLiteFile)
            g_unlink(m_cookiesSQLiteFile.get());
    }

    void setPersistentStorage(WebKitCookiePersistentStorage storage)
    {
        const char* filename = 0;
        switch (storage) {
        case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
            if (!m_cookiesTextFile)
                m_cookiesTextFile.reset(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
            filename = m_cookiesTextFile.get();
            break;
        case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
            if (!m_cookiesSQLiteFile)
                m_cookiesSQLiteFile.reset(g_build_filename(Test::dataDirectory(), "cookies.db", nullptr));
            filename = m_cookiesSQLiteFile.get();
            break;
        default:
            g_assert_not_reached();
        }
        webkit_cookie_manager_set_persistent_storage(m_cookieManager, filename, storage);
    }

    static void getAcceptPolicyReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
    {
        GUniqueOutPtr<GError> error;
        WebKitCookieAcceptPolicy policy = webkit_cookie_manager_get_accept_policy_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
        g_assert_no_error(error.get());

        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
        test->m_acceptPolicy = policy;
        g_main_loop_quit(test->m_mainLoop);
    }

    WebKitCookieAcceptPolicy getAcceptPolicy()
    {
        m_acceptPolicy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY;
        webkit_cookie_manager_get_accept_policy(m_cookieManager, 0, getAcceptPolicyReadyCallback, this);
        g_main_loop_run(m_mainLoop);

        return m_acceptPolicy;
    }

    static void addCookieReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
    {
        GUniqueOutPtr<GError> error;
        bool added = webkit_cookie_manager_add_cookie_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
        g_assert_no_error(error.get());
        g_assert_true(added);

        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
        g_main_loop_quit(test->m_mainLoop);
    }

    void addCookie(SoupCookie* cookie)
    {
        webkit_cookie_manager_add_cookie(m_cookieManager, cookie, 0, addCookieReadyCallback, this);
        g_main_loop_run(m_mainLoop);
    }

    static void getCookiesReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
    {
        GUniqueOutPtr<GError> error;
        GList* cookies = webkit_cookie_manager_get_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
        g_assert_no_error(error.get());

        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
        test->m_cookies = cookies;
        g_main_loop_quit(test->m_mainLoop);
    }

    GList* getCookies(const char* uri)
    {
        g_list_free_full(m_cookies, reinterpret_cast<GDestroyNotify>(soup_cookie_free));
        m_cookies = nullptr;
        webkit_cookie_manager_get_cookies(m_cookieManager, uri, 0, getCookiesReadyCallback, this);
        g_main_loop_run(m_mainLoop);

        return m_cookies;
    }

    static void deleteCookieReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
    {
        GUniqueOutPtr<GError> error;
        bool deleted = webkit_cookie_manager_delete_cookie_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
        g_assert_no_error(error.get());
        g_assert_true(deleted);

        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
        g_main_loop_quit(test->m_mainLoop);
    }

    void deleteCookie(SoupCookie* cookie)
    {
        webkit_cookie_manager_delete_cookie(m_cookieManager, cookie, 0, deleteCookieReadyCallback, this);
        g_main_loop_run(m_mainLoop);
    }

    void setAcceptPolicy(WebKitCookieAcceptPolicy policy)
    {
        webkit_cookie_manager_set_accept_policy(m_cookieManager, policy);
    }

    static void getDomainsReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
    {
        GUniqueOutPtr<GError> error;
        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        char** domains = webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
        G_GNUC_END_IGNORE_DEPRECATIONS;
        g_assert_no_error(error.get());

        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
        test->m_domains = domains;
        g_main_loop_quit(test->m_mainLoop);
    }

    char** getDomains()
    {
        g_strfreev(m_domains);
        m_domains = 0;
        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, 0, getDomainsReadyCallback, this);
        G_GNUC_END_IGNORE_DEPRECATIONS;
        g_main_loop_run(m_mainLoop);

        return m_domains;
    }

    bool hasDomain(const char* domain)
    {
        if (!m_domains)
            return false;

        for (size_t i = 0; m_domains[i]; ++i) {
            if (g_str_equal(m_domains[i], domain))
                return true;
        }
        return false;
    }

    void deleteCookiesForDomain(const char* domain)
    {
        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        webkit_cookie_manager_delete_cookies_for_domain(m_cookieManager, domain);
        G_GNUC_END_IGNORE_DEPRECATIONS;
    }

    void deleteAllCookies()
    {
        G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
        webkit_cookie_manager_delete_all_cookies(m_cookieManager);
        G_GNUC_END_IGNORE_DEPRECATIONS;
    }

    void waitUntilCookiesChanged(int cookiesExpectedToChangeCount = 1)
    {
        m_cookiesChanged = false;
        m_cookiesExpectedToChangeCount = cookiesExpectedToChangeCount;
        m_finishLoopWhenCookiesChange = true;
        g_main_loop_run(m_mainLoop);
        m_finishLoopWhenCookiesChange = false;
    }

    WebKitCookieManager* m_cookieManager { nullptr };
    WebKitCookieAcceptPolicy m_acceptPolicy { WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY };
    char** m_domains { nullptr };
    GList* m_cookies { nullptr };
    bool m_cookiesChanged { false };
    int m_cookiesExpectedToChangeCount { 0 };
    bool m_finishLoopWhenCookiesChange { false };
    GUniquePtr<char> m_cookiesTextFile;
    GUniquePtr<char> m_cookiesSQLiteFile;
};

static void testCookieManagerAcceptPolicy(CookieManagerTest* test, gconstpointer)
{
    // Default policy is NO_THIRD_PARTY.
    g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    char** domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 1);
    g_assert_cmpstr(domains[0], ==, kFirstPartyDomain);
    test->deleteAllCookies();

    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 2);
    g_assert_true(test->hasDomain(kFirstPartyDomain));
    g_assert_true(test->hasDomain(kThirdPartyDomain));
    test->deleteAllCookies();

    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER);
    g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NEVER);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);
}

static void testCookieManagerAddCookie(CookieManagerTest* test, gconstpointer)
{
    // Load the html content, with the default NO_THIRD_PARTY accept policy,
    // which will automatically add one cookie.
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Check the cookies that have been added for the domain.
    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
    GList* foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    SoupCookie* foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);

    // Try to add now a cookie with same (name, domain, path) than the ones already added.
    GUniquePtr<SoupCookie> firstCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePath, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
    test->addCookie(firstCookie.get());

    // Still one cookie, since (name, domain, path) are the same than the already existing
    // one, but the new value is now stored as replaced by the recently added cookie.
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValueNew);

    // Now create another cookie with a different path and add it.
    GUniquePtr<SoupCookie> secondCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
    test->addCookie(secondCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Retrieve the list of cookies for the same domain and path again now and check.
    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain, kCookiePathNew));
    foundCookies = test->getCookies(uri.get());

    // We have now two cookies that would apply to the passed URL, one is the cookie initially
    // loaded with the web content and the other cookie the one we manually added.
    g_assert_cmpint(g_list_length(foundCookies), ==, 2);

    // Add a third new cookie for a different domain than the previous ones.
    GUniquePtr<SoupCookie> thirdCookie(soup_cookie_new(kCookieName, kCookieValueNew, kThirdPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
    test->addCookie(thirdCookie.get());

    // Only one cookie now, since the domain is different.
    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kThirdPartyDomain, kCookiePathNew));
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);

    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kThirdPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePathNew);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValueNew);

    // Finally, delete all cookies and check they are all gone.
    test->deleteAllCookies();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
}

static void testCookieManagerGetCookies(CookieManagerTest* test, gconstpointer)
{
    // Load the html content and retrieve the two cookies automatically added with ALWAYS policy.
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);

    // Retrieve the first cookie using a HTTP scheme.
    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
    GList* foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    SoupCookie* foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);

    // Retrieve the second cookie using a HTTPS scheme.
    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTPS, kThirdPartyDomain));
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kThirdPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);

    // Create a new cookie and add it to the first domain.
    GUniquePtr<SoupCookie> newCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
    test->addCookie(newCookie.get());

    // We should get two cookies that would apply to the same URL passed, since
    // http://127.0.0.1/new is a subset of the http://127.0.0.1/ URL.
    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain, kCookiePathNew));
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 2);

    // We have now two cookies that would apply to the passed URL, one is the cookie initially
    // loaded with the web content and the other cookie the one we manually added.
    g_assert_cmpint(g_list_length(foundCookies), ==, 2);

    bool newPathChecked = false;
    const char* pathFound = nullptr;
    const char* valueFound = nullptr;
    for (uint i = 0; i < 2; i++) {
        foundCookie = static_cast<SoupCookie*>(g_list_nth_data(foundCookies, i));
        g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
        g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);

        // Cookies will have different values for 'value' and 'path', so make sure that
        // we check for both possibilities, but different ones for each cookie found.
        pathFound = soup_cookie_get_path(foundCookie);
        valueFound = soup_cookie_get_value(foundCookie);
        if (i > 0) {
            if (newPathChecked) {
                g_assert_cmpstr(pathFound, ==, kCookiePath);
                g_assert_cmpstr(valueFound, ==, kCookieValue);
            } else {
                g_assert_cmpstr(pathFound, ==, kCookiePathNew);
                g_assert_cmpstr(valueFound, ==, kCookieValueNew);
            }
        } else {
            if (g_strcmp0(pathFound, kCookiePath)) {
                g_assert_cmpstr(pathFound, ==, kCookiePathNew);
                g_assert_cmpstr(valueFound, ==, kCookieValueNew);
                newPathChecked = true;
            }

            if (g_strcmp0(pathFound, kCookiePathNew)) {
                g_assert_cmpstr(pathFound, ==, kCookiePath);
                g_assert_cmpstr(valueFound, ==, kCookieValue);
                newPathChecked = false;
            }
        }
    }

    // We should get 1 cookie only if we specify http://127.0.0.1/, though.
    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);

    // Finally, delete all cookies and try to retrieve them again, one by one.
    test->deleteAllCookies();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);

    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
    foundCookies = test->getCookies(uri.get());
    g_assert_null(foundCookies);
}

static void testCookieManagerDeleteCookie(CookieManagerTest* test, gconstpointer)
{
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();

    // Initially, there should be two cookies available.
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);

    // Delete the cookie for the first party domain.
    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
    GList* foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    GUniquePtr<SoupCookie> firstPartyCookie(soup_cookie_copy(static_cast<SoupCookie*>(foundCookies->data)));
    test->deleteCookie(firstPartyCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Try deleting a non-existent cookie (wrong name).
    GUniquePtr<SoupCookie> wrongCookie(soup_cookie_new("wrong-name", kCookieValue, kThirdPartyDomain, kCookiePath, -1));
    test->deleteCookie(wrongCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Try deleting a non-existent cookie (wrong domain).
    wrongCookie.reset(soup_cookie_new(kCookieName, kCookieValue, "wrong-domain", kCookiePath, -1));
    test->deleteCookie(wrongCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Try deleting a non-existent cookie (wrong path).
    wrongCookie.reset(soup_cookie_new(kCookieName, kCookieValue, kThirdPartyDomain, "wrong-path", -1));
    test->deleteCookie(wrongCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Delete the cookie for the third party domain.
    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kThirdPartyDomain));
    foundCookies = test->getCookies(uri.get());
    g_assert_cmpint(g_list_length(foundCookies), ==, 1);

    GUniquePtr<SoupCookie> thirdPartyCookie(soup_cookie_copy(static_cast<SoupCookie*>(foundCookies->data)));
    test->deleteCookie(thirdPartyCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);

    // Finally, add a new cookie now we don't have any and delete it afterwards.
    GUniquePtr<SoupCookie> newCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
    test->addCookie(newCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
    test->deleteCookie(newCookie.get());
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
}

static void testCookieManagerDeleteCookies(CookieManagerTest* test, gconstpointer)
{
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);

    // Delete first party cookies.
    test->deleteCookiesForDomain(kFirstPartyDomain);
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);

    // Delete third party cookies.
    test->deleteCookiesForDomain(kThirdPartyDomain);
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);

    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);

    // Delete all cookies.
    test->deleteAllCookies();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
}

static void testCookieManagerCookiesChanged(CookieManagerTest* test, gconstpointer)
{
    g_assert_false(test->m_cookiesChanged);
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_true(test->m_cookiesChanged);

    test->deleteCookiesForDomain(kFirstPartyDomain);
    test->waitUntilCookiesChanged();
    g_assert_true(test->m_cookiesChanged);

    test->deleteAllCookies();
    test->waitUntilCookiesChanged();
    g_assert_true(test->m_cookiesChanged);
}

class CookiePersistentStorageTest : public CookieManagerTest {
public:
    MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(CookiePersistentStorageTest, setup, teardown);

    static void setup()
    {
        WebViewTest::shouldInitializeWebViewInConstructor = false;
    }

    static void teardown()
    {
        WebViewTest::shouldInitializeWebViewInConstructor = true;
    }
};

static void testCookieManagerPersistentStorage(CookiePersistentStorageTest* test, gconstpointer)
{
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);

    g_unlink(test->m_cookiesTextFile.get());
    g_unlink(test->m_cookiesSQLiteFile.get());

    // Text storage using a new file.
    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
    char** domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);

    // Initialization of web view is deferred to ensure it's not required for
    // setting persistent storage to work.
    test->initializeWebView();
    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_true(test->m_cookiesChanged);
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 2);
    g_assert_true(g_file_test(test->m_cookiesTextFile.get(), G_FILE_TEST_EXISTS));

    // SQLite storage using a new file.
    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);

    test->loadURI(kServer->getURIForPath("/index.html").data());
    test->waitUntilLoadFinished();
    g_assert_true(test->m_cookiesChanged);
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 2);
    g_assert_true(g_file_test(test->m_cookiesSQLiteFile.get(), G_FILE_TEST_EXISTS));

    // Text storage using an existing file.
    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 2);
    test->deleteAllCookies();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);

    // SQLite storage with an existing file.
    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 2);
    test->deleteAllCookies();
    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
}

static void testCookieManagerPersistentStorageDeleteAll(CookieManagerTest* test, gconstpointer)
{
    // This checks that we can remove all the cookies of an existing file before a web process is created.
    // See bug https://bugs.webkit.org/show_bug.cgi?id=175265.
    static const char cookiesFileFormat[] = "127.0.0.1\tFALSE\t/\tFALSE\t%ld\tfoo\tbar\nlocalhost\tFALSE\t/\tFALSE\t%ld\tbaz\tqux\n";
    time_t expires = time(nullptr) + 60;
    GUniquePtr<char> cookiesFileContents(g_strdup_printf(cookiesFileFormat, expires, expires));
    GUniquePtr<char> cookiesFile(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
    g_assert_true(g_file_set_contents(cookiesFile.get(), cookiesFileContents.get(), -1, nullptr));

    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
    test->deleteAllCookies();
    // Changed signal is emitted for every deleted cookie, twice in this case.
    test->waitUntilCookiesChanged(2);

    // Ensure the web process is created and load something without cookies.
    test->m_cookiesChanged = false;
    test->loadURI(kServer->getURIForPath("/no-cookies.html").data());
    test->waitUntilLoadFinished();
    g_assert_false(test->m_cookiesChanged);
    char** domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);
}

static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
{
    if (loadEvent != WEBKIT_LOAD_FINISHED)
        return;
    g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
    test->quitMainLoop();
}

static void testCookieManagerEphemeral(CookieManagerTest* test, gconstpointer)
{
    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
    test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
    char** domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);

    auto webView = Test::adoptView(g_object_new(WEBKIT_TYPE_WEB_VIEW,
#if PLATFORM(WPE)
        "backend", Test::createWebViewBackend(),
#endif
        "web-context", webkit_web_view_get_context(test->m_webView),
        "is-ephemeral", TRUE,
        nullptr));
    g_assert_true(webkit_web_view_is_ephemeral(webView.get()));
    g_assert_false(webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get())));

    g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
    webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/index.html").data());
    g_main_loop_run(test->m_mainLoop);

    domains = test->getDomains();
    g_assert_nonnull(domains);
    g_assert_cmpint(g_strv_length(domains), ==, 0);

    auto* viewDataManager = webkit_web_view_get_website_data_manager(webView.get());
    g_assert_true(WEBKIT_IS_WEBSITE_DATA_MANAGER(viewDataManager));
    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewDataManager));
    g_assert_true(viewDataManager != webkit_web_context_get_website_data_manager(webkit_web_view_get_context(test->m_webView)));
    auto* cookieManager = webkit_website_data_manager_get_cookie_manager(viewDataManager);
    g_assert_true(WEBKIT_IS_COOKIE_MANAGER(cookieManager));
    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(cookieManager));
    g_assert_true(cookieManager != test->m_cookieManager);
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
    webkit_cookie_manager_get_domains_with_cookies(cookieManager, nullptr, [](GObject* object, GAsyncResult* result, gpointer userData) {
        auto* test = static_cast<CookieManagerTest*>(userData);
        GUniquePtr<char*> domains(webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, nullptr));
        g_assert_nonnull(domains);
        g_assert_cmpint(g_strv_length(domains.get()), ==, 1);
        g_assert_cmpstr(domains.get()[0], ==, kFirstPartyDomain);
        test->quitMainLoop();
    }, test);
    G_GNUC_END_IGNORE_DEPRECATIONS;
    g_main_loop_run(test->m_mainLoop);
}

static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
    if (message->method != SOUP_METHOD_GET) {
        soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
        return;
    }

    soup_message_set_status(message, SOUP_STATUS_OK);
    gchar* header_str = g_strdup_printf("%s=%s; Max-Age=60", kCookieName, kCookieValue);

    if (g_str_equal(path, "/index.html")) {
        char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server));
        soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
        soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml));
    } else if (g_str_equal(path, "/image.png"))
        soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
    else if (g_str_equal(path, "/no-cookies.html")) {
        static const char* indexHtml = "<html><body><p>No cookies</p></body></html>";
        soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHtml, strlen(indexHtml));
    } 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);

    CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy);
    CookieManagerTest::add("WebKitCookieManager", "add-cookie", testCookieManagerAddCookie);
    CookieManagerTest::add("WebKitCookieManager", "get-cookies", testCookieManagerGetCookies);
    CookieManagerTest::add("WebKitCookieManager", "delete-cookie", testCookieManagerDeleteCookie);
    CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies);
    CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged);
    CookiePersistentStorageTest::add("WebKitCookieManager", "persistent-storage", testCookieManagerPersistentStorage);
    CookieManagerTest::add("WebKitCookieManager", "persistent-storage-delete-all", testCookieManagerPersistentStorageDeleteAll);
    CookieManagerTest::add("WebKitCookieManager", "ephemeral", testCookieManagerEphemeral);
}

void afterAll()
{
    delete kServer;
}
