Changeset 225054 in webkit


Ignore:
Timestamp:
Nov 20, 2017 2:02:46 PM (6 years ago)
Author:
mario@webkit.org
Message:

[GTK] New API to add, retrieve and delete cookies via WebKitCookieManager
https://bugs.webkit.org/show_bug.cgi?id=177932

Reviewed by Carlos Garcia Campos.

Source/WebCore:

Implemented setCookie(), getCookies() and deleteCookie() in the Soup
backend, and refactored some utility functions and conversions out of
NetworkStorageSessionSoup into a new CookieSoup.cpp file, so
that we now can convert between SoupCookie* and WebCore::Cookie
easily from anywhere (this is now needed from the UI Process).

  • platform/Cookie.h: Add declarations for the new conversions.
  • platform/SourcesSoup.txt: Add CookieSoup.cpp.
  • platform/network/soup/CookieSoup.cpp: Added.

(WebCore::Cookie::Cookie): New constructor, creates a WebCore::Cookie out of a SoupCookie*.
(WebCore::msToSoupDate): Moved from NetworkStorageSessionSoup.cpp.
(WebCore::Cookie::toSoupCookie): New, based on toSoupCookie() from NetworkStorageSessionSoup.cpp.

  • platform/network/soup/NetworkStorageSessionSoup.cpp:

(WebCore::NetworkStorageSession::setCookies): Used the new implicit conversion.
(WebCore::NetworkStorageSession::setCookie): Newly implemented.
(WebCore::NetworkStorageSession::deleteCookie): Newly implemented.
(WebCore::NetworkStorageSession::getCookies): Newly implemented.

Source/WebKit:

Added new API to WebKitCookieManager to add, retrieve and delete complete
cookies into/out-of a running session, and updated documentation sections.

  • UIProcess/API/glib/WebKitCookieManager.cpp:

(webkit_cookie_manager_add_cookie): New function.
(webkit_cookie_manager_add_cookie_finish): Ditto.
(webkit_cookie_manager_get_cookies): Ditto.
(webkit_cookie_manager_get_cookies_finish): Ditto.
(webkit_cookie_manager_delete_cookie): Ditto.
(webkit_cookie_manager_delete_cookie_finish): Ditto.

  • UIProcess/API/gtk/WebKitCookieManager.h: Added new functions.
  • UIProcess/API/wpe/WebKitCookieManager.h: Ditto.
  • UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: Ditto.

Tools:

Added new test cases to cover the newly added API for WebKitCookieManager:
webkit_cookie_manager_add_cookie, webkit_cookie_manager_get_cookies and
webkit_cookie_manager_delete_cookie.

  • TestWebKitAPI/Tests/WebKitGLib/TestCookieManager.cpp:

(testCookieManagerAddCookie): Added.
(testCookieManagerGetCookies): Added.
(testCookieManagerDeleteCookie): Added.
(serverCallback): Small update to avoid hardcoding strings we reuse.
(beforeAll): Added the new test cases to the test suite.

Location:
trunk
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r225052 r225054  
     12017-11-20  Mario Sanchez Prada  <mario@endlessm.com>
     2
     3        [GTK] New API to add, retrieve and delete cookies via WebKitCookieManager
     4        https://bugs.webkit.org/show_bug.cgi?id=177932
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Implemented setCookie(), getCookies() and deleteCookie() in the Soup
     9        backend, and refactored some utility functions and conversions out of
     10        NetworkStorageSessionSoup into a new CookieSoup.cpp file, so
     11        that we now can convert between SoupCookie* and WebCore::Cookie
     12        easily from anywhere (this is now needed from the UI Process).
     13
     14        * platform/Cookie.h: Add declarations for the new conversions.
     15        * platform/SourcesSoup.txt: Add CookieSoup.cpp.
     16        * platform/network/soup/CookieSoup.cpp: Added.
     17        (WebCore::Cookie::Cookie): New constructor, creates a WebCore::Cookie out of a SoupCookie*.
     18        (WebCore::msToSoupDate): Moved from NetworkStorageSessionSoup.cpp.
     19        (WebCore::Cookie::toSoupCookie): New, based on toSoupCookie() from NetworkStorageSessionSoup.cpp.
     20        * platform/network/soup/NetworkStorageSessionSoup.cpp:
     21        (WebCore::NetworkStorageSession::setCookies): Used the new implicit conversion.
     22        (WebCore::NetworkStorageSession::setCookie): Newly implemented.
     23        (WebCore::NetworkStorageSession::deleteCookie): Newly implemented.
     24        (WebCore::NetworkStorageSession::getCookies): Newly implemented.
     25
    1262017-11-20  Zalan Bujtas  <zalan@apple.com>
    227
  • trunk/Source/WebCore/platform/Cookie.h

    r222233 r225054  
    6868    WEBCORE_EXPORT Cookie(NSHTTPCookie *);
    6969    WEBCORE_EXPORT operator NSHTTPCookie *() const;
     70#elif USE(SOUP)
     71    explicit Cookie(SoupCookie*);
     72    SoupCookie* toSoupCookie() const;
    7073#endif
    7174
  • trunk/Source/WebCore/platform/SourcesSoup.txt

    r224189 r225054  
    2525platform/network/soup/CertificateInfo.cpp
    2626platform/network/soup/CookieJarSoup.cpp
     27platform/network/soup/CookieSoup.cpp
    2728platform/network/soup/CookieStorageSoup.cpp
    2829platform/network/soup/CredentialStorageSoup.cpp
  • trunk/Source/WebCore/platform/network/soup/NetworkStorageSessionSoup.cpp

    r224791 r225054  
    33 * Copyright (C) 2013 University of Szeged. All rights reserved.
    44 * Copyright (C) 2016 Igalia S.L.
     5 * Copyright (C) 2017 Endless Mobile, Inc.
    56 *
    67 * Redistribution and use in source and binary forms, with or without
     
    3435#include "ResourceHandle.h"
    3536#include "SoupNetworkSession.h"
     37#include <WebCore/GUniquePtrSoup.h>
    3638#include <libsoup/soup.h>
    3739#include <wtf/DateMath.h>
     
    284286}
    285287
    286 static SoupDate* msToSoupDate(double ms)
    287 {
    288     int year = msToYear(ms);
    289     int dayOfYear = dayInYear(ms, year);
    290     bool leapYear = isLeapYear(year);
    291 
    292     // monthFromDayInYear() returns a value in the [0,11] range, while soup_date_new() expects
    293     // a value in the [1,12] range, meaning we have to manually adjust the month value.
    294     return soup_date_new(year, monthFromDayInYear(dayOfYear, leapYear) + 1, dayInMonthFromDayInYear(dayOfYear, leapYear), msToHours(ms), msToMinutes(ms), static_cast<int>(ms / 1000) % 60);
    295 }
    296 
    297 static SoupCookie* toSoupCookie(const Cookie& cookie)
    298 {
    299     SoupCookie* soupCookie = soup_cookie_new(cookie.name.utf8().data(), cookie.value.utf8().data(),
    300         cookie.domain.utf8().data(), cookie.path.utf8().data(), -1);
    301     soup_cookie_set_http_only(soupCookie, cookie.httpOnly);
    302     soup_cookie_set_secure(soupCookie, cookie.secure);
    303     if (!cookie.session) {
    304         SoupDate* date = msToSoupDate(cookie.expires);
    305         soup_cookie_set_expires(soupCookie, date);
    306         soup_date_free(date);
    307     }
    308     return soupCookie;
    309 }
    310 
    311288void NetworkStorageSession::setCookies(const Vector<Cookie>& cookies, const URL&, const URL&)
    312289{
    313290    for (auto cookie : cookies)
    314         soup_cookie_jar_add_cookie(cookieStorage(), toSoupCookie(cookie));
    315 }
    316 
    317 void NetworkStorageSession::setCookie(const Cookie&)
    318 {
    319     // FIXME: Implement for WK2 to use.
    320 }
    321 
    322 void NetworkStorageSession::deleteCookie(const Cookie&)
    323 {
    324     // FIXME: Implement for WK2 to use.
     291        soup_cookie_jar_add_cookie(cookieStorage(), cookie.toSoupCookie());
     292}
     293
     294void NetworkStorageSession::setCookie(const Cookie& cookie)
     295{
     296    soup_cookie_jar_add_cookie(cookieStorage(), cookie.toSoupCookie());
     297}
     298
     299void NetworkStorageSession::deleteCookie(const Cookie& cookie)
     300{
     301    GUniquePtr<SoupCookie> targetCookie(cookie.toSoupCookie());
     302    soup_cookie_jar_delete_cookie(cookieStorage(), targetCookie.get());
    325303}
    326304
     
    331309}
    332310
    333 Vector<Cookie> NetworkStorageSession::getCookies(const URL&)
     311Vector<Cookie> NetworkStorageSession::getCookies(const URL& url)
     312{
     313    Vector<Cookie> cookies;
     314    GUniquePtr<SoupURI> uri = url.createSoupURI();
     315    GUniquePtr<GSList> cookiesList(soup_cookie_jar_get_cookie_list(cookieStorage(), uri.get(), TRUE));
     316    for (GSList* item = cookiesList.get(); item; item = g_slist_next(item)) {
     317        GUniquePtr<SoupCookie> soupCookie(static_cast<SoupCookie*>(item->data));
     318        cookies.append(WebCore::Cookie(soupCookie.get()));
     319    }
     320
     321    return cookies;
     322}
     323
     324void NetworkStorageSession::flushCookieStore()
    334325{
    335326    // FIXME: Implement for WK2 to use.
    336     return { };
    337 }
    338 
    339 void NetworkStorageSession::flushCookieStore()
    340 {
    341     // FIXME: Implement for WK2 to use.
    342327}
    343328
  • trunk/Source/WebKit/ChangeLog

    r225044 r225054  
     12017-11-20  Mario Sanchez Prada  <mario@endlessm.com>
     2
     3        [GTK] New API to add, retrieve and delete cookies via WebKitCookieManager
     4        https://bugs.webkit.org/show_bug.cgi?id=177932
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Added new API to WebKitCookieManager to add, retrieve and delete complete
     9        cookies into/out-of a running session, and updated documentation sections.
     10
     11        * UIProcess/API/glib/WebKitCookieManager.cpp:
     12        (webkit_cookie_manager_add_cookie): New function.
     13        (webkit_cookie_manager_add_cookie_finish): Ditto.
     14        (webkit_cookie_manager_get_cookies): Ditto.
     15        (webkit_cookie_manager_get_cookies_finish): Ditto.
     16        (webkit_cookie_manager_delete_cookie): Ditto.
     17        (webkit_cookie_manager_delete_cookie_finish): Ditto.
     18        * UIProcess/API/gtk/WebKitCookieManager.h: Added new functions.
     19        * UIProcess/API/wpe/WebKitCookieManager.h: Ditto.
     20        * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: Ditto.
     21
    1222017-11-20  Carlos Garcia Campos  <cgarcia@igalia.com>
    223
  • trunk/Source/WebKit/UIProcess/API/glib/WebKitCookieManager.cpp

    r220887 r225054  
    11/*
    22 * Copyright (C) 2012 Igalia S.L.
     3 * Copyright (C) 2017 Endless Mobile, Inc.
    34 *
    45 * This library is free software; you can redistribute it and/or
     
    2829#include "WebKitWebsiteDataPrivate.h"
    2930#include "WebsiteDataRecord.h"
     31#include <glib/gi18n-lib.h>
    3032#include <pal/SessionID.h>
    3133#include <wtf/glib/GRefPtr.h>
     
    234236
    235237/**
     238 * webkit_cookie_manager_add_cookie:
     239 * @cookie_manager: a #WebKitCookieManager
     240 * @cookie: the #SoupCookie to be added
     241 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
     242 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
     243 * @user_data: (closure): the data to pass to callback function
     244 *
     245 * Asynchronously add a #SoupCookie to the underlying storage.
     246 *
     247 * When the operation is finished, @callback will be called. You can then call
     248 * webkit_cookie_manager_add_cookie_finish() to get the result of the operation.
     249 *
     250 * Since: 2.20
     251 */
     252void webkit_cookie_manager_add_cookie(WebKitCookieManager* manager, SoupCookie* cookie, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
     253{
     254    g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
     255    g_return_if_fail(cookie);
     256
     257    GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
     258
     259    auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
     260    const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
     261
     262    // Cookies are read/written from/to the same SQLite database on disk regardless
     263    // of the process we access them from, so just use the first process pool.
     264    processPools[0]->supplement<WebCookieManagerProxy>()->setCookie(sessionID, WebCore::Cookie(cookie), [task = WTFMove(task)](CallbackBase::Error error) {
     265        if (error != CallbackBase::Error::None) {
     266            // This can only happen in cases where the web process is not available,
     267            // consider the operation "cancelled" from the point of view of the client.
     268            g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled"));
     269            return;
     270        }
     271
     272        g_task_return_boolean(task.get(), TRUE);
     273    });
     274}
     275
     276/**
     277 * webkit_cookie_manager_add_cookie_finish:
     278 * @cookie_manager: a #WebKitCookieManager
     279 * @result: a #GAsyncResult
     280 * @error: return location for error or %NULL to ignore
     281 *
     282 * Finish an asynchronous operation started with webkit_cookie_manager_add_cookie().
     283 *
     284 * Returns: %TRUE if the cookie was added or %FALSE in case of error.
     285 *
     286 * Since: 2.20
     287 */
     288gboolean webkit_cookie_manager_add_cookie_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
     289{
     290    g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), FALSE);
     291    g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
     292
     293    return g_task_propagate_boolean(G_TASK(result), error);
     294}
     295
     296/**
     297 * webkit_cookie_manager_get_cookies:
     298 * @cookie_manager: a #WebKitCookieManager
     299 * @uri: the URI associated to the cookies to be retrieved
     300 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
     301 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
     302 * @user_data: (closure): the data to pass to callback function
     303 *
     304 * Asynchronously get a list of #SoupCookie from @cookie_manager associated with @uri, which
     305 * must be either an HTTP or an HTTPS URL.
     306 *
     307 * When the operation is finished, @callback will be called. You can then call
     308 * webkit_cookie_manager_get_cookies_finish() to get the result of the operation.
     309 *
     310 * Since: 2.20
     311 */
     312void webkit_cookie_manager_get_cookies(WebKitCookieManager* manager, const gchar* uri, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
     313{
     314    g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
     315    g_return_if_fail(uri);
     316
     317    GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
     318
     319    auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
     320    const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
     321
     322    // Cookies are read/written from/to the same SQLite database on disk regardless
     323    // of the process we access them from, so just use the first process pool.
     324    processPools[0]->supplement<WebCookieManagerProxy>()->getCookies(sessionID, WebCore::URL(WebCore::URL(), String::fromUTF8(uri)), [task = WTFMove(task)](const Vector<WebCore::Cookie>& cookies, CallbackBase::Error error) {
     325        if (error != CallbackBase::Error::None) {
     326            // This can only happen in cases where the web process is not available,
     327            // consider the operation "cancelled" from the point of view of the client.
     328            g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled"));
     329            return;
     330        }
     331
     332        GList* cookiesList = nullptr;
     333        for (auto& cookie : cookies)
     334            cookiesList = g_list_prepend(cookiesList, cookie.toSoupCookie());
     335
     336        g_task_return_pointer(task.get(), g_list_reverse(cookiesList), [](gpointer data) {
     337            g_list_free_full(static_cast<GList*>(data), reinterpret_cast<GDestroyNotify>(soup_cookie_free));
     338        });
     339    });
     340}
     341
     342/**
     343 * webkit_cookie_manager_get_cookies_finish:
     344 * @cookie_manager: a #WebKitCookieManager
     345 * @result: a #GAsyncResult
     346 * @error: return location for error or %NULL to ignore
     347 *
     348 * Finish an asynchronous operation started with webkit_cookie_manager_get_cookies().
     349 * The return value is a #GSList of #SoupCookie instances which should be released
     350 * with g_list_free_full() and soup_cookie_free().
     351 *
     352 * Returns: (element-type SoupCookie) (transfer full): A #GList of #SoupCookie instances.
     353 *
     354 * Since: 2.20
     355 */
     356GList* webkit_cookie_manager_get_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
     357{
     358    g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), nullptr);
     359    g_return_val_if_fail(g_task_is_valid(result, manager), nullptr);
     360
     361    return reinterpret_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
     362}
     363
     364/**
     365 * webkit_cookie_manager_delete_cookie:
     366 * @cookie_manager: a #WebKitCookieManager
     367 * @cookie: the #SoupCookie to be deleted
     368 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
     369 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
     370 * @user_data: (closure): the data to pass to callback function
     371 *
     372 * Asynchronously delete a #SoupCookie from the current session.
     373 *
     374 * When the operation is finished, @callback will be called. You can then call
     375 * webkit_cookie_manager_delete_cookie_finish() to get the result of the operation.
     376 *
     377 * Since: 2.20
     378 */
     379void webkit_cookie_manager_delete_cookie(WebKitCookieManager* manager, SoupCookie* cookie, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
     380{
     381    g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
     382    g_return_if_fail(cookie);
     383
     384    GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
     385
     386    auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
     387    const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
     388
     389    // Cookies are read/written from/to the same SQLite database on disk regardless
     390    // of the process we access them from, so just use the first process pool.
     391    processPools[0]->supplement<WebCookieManagerProxy>()->deleteCookie(sessionID, WebCore::Cookie(cookie), [task = WTFMove(task)](CallbackBase::Error error) {
     392        if (error != CallbackBase::Error::None) {
     393            // This can only happen in cases where the web process is not available,
     394            // consider the operation "cancelled" from the point of view of the client.
     395            g_task_return_new_error(task.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled"));
     396            return;
     397        }
     398
     399        g_task_return_boolean(task.get(), TRUE);
     400    });
     401}
     402
     403/**
     404 * webkit_cookie_manager_delete_cookie_finish:
     405 * @cookie_manager: a #WebKitCookieManager
     406 * @result: a #GAsyncResult
     407 * @error: return location for error or %NULL to ignore
     408 *
     409 * Finish an asynchronous operation started with webkit_cookie_manager_delete_cookie().
     410 *
     411 * Returns: %TRUE if the cookie was deleted or %FALSE in case of error.
     412 *
     413 * Since: 2.20
     414 */
     415gboolean webkit_cookie_manager_delete_cookie_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
     416{
     417    g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), FALSE);
     418    g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
     419
     420    return g_task_propagate_boolean(G_TASK(result), error);
     421}
     422
     423/**
    236424 * webkit_cookie_manager_get_domains_with_cookies:
    237425 * @cookie_manager: a #WebKitCookieManager
  • trunk/Source/WebKit/UIProcess/API/gtk/WebKitCookieManager.h

    r212345 r225054  
    11/*
    22 * Copyright (C) 2012 Igalia S.L.
     3 * Copyright (C) 2017 Endless Mobile, Inc.
    34 *
    45 * This library is free software; you can redistribute it and/or
     
    2728#include <gio/gio.h>
    2829#include <glib-object.h>
     30#include <libsoup/soup.h>
    2931#include <webkit2/WebKitDefines.h>
    3032
     
    108110                                                       GError                      **error);
    109111
     112WEBKIT_API void
     113webkit_cookie_manager_add_cookie                      (WebKitCookieManager          *cookie_manager,
     114                                                       SoupCookie                   *cookie,
     115                                                       GCancellable                 *cancellable,
     116                                                       GAsyncReadyCallback           callback,
     117                                                       gpointer                      user_data);
     118
     119WEBKIT_API gboolean
     120webkit_cookie_manager_add_cookie_finish               (WebKitCookieManager          *cookie_manager,
     121                                                       GAsyncResult                 *result,
     122                                                       GError                      **error);
     123
     124WEBKIT_API void
     125webkit_cookie_manager_get_cookies                     (WebKitCookieManager          *cookie_manager,
     126                                                       const gchar                  *uri,
     127                                                       GCancellable                 *cancellable,
     128                                                       GAsyncReadyCallback           callback,
     129                                                       gpointer                      user_data);
     130
     131WEBKIT_API GList *
     132webkit_cookie_manager_get_cookies_finish              (WebKitCookieManager          *cookie_manager,
     133                                                       GAsyncResult                 *result,
     134                                                       GError                      **error);
     135
     136WEBKIT_API void
     137webkit_cookie_manager_delete_cookie                   (WebKitCookieManager          *cookie_manager,
     138                                                       SoupCookie                   *cookie,
     139                                                       GCancellable                 *cancellable,
     140                                                       GAsyncReadyCallback           callback,
     141                                                       gpointer                      user_data);
     142
     143WEBKIT_API gboolean
     144webkit_cookie_manager_delete_cookie_finish            (WebKitCookieManager          *cookie_manager,
     145                                                       GAsyncResult                 *result,
     146                                                       GError                      **error);
     147
    110148WEBKIT_DEPRECATED_FOR(webkit_website_data_manager_fetch) void
    111149webkit_cookie_manager_get_domains_with_cookies        (WebKitCookieManager          *cookie_manager,
  • trunk/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt

    r224737 r225054  
    10071007webkit_cookie_manager_get_domains_with_cookies
    10081008webkit_cookie_manager_get_domains_with_cookies_finish
     1009webkit_cookie_manager_add_cookie
     1010webkit_cookie_manager_add_cookie_finish
     1011webkit_cookie_manager_get_cookies
     1012webkit_cookie_manager_get_cookies_finish
     1013webkit_cookie_manager_delete_cookie
     1014webkit_cookie_manager_delete_cookie_finish
    10091015webkit_cookie_manager_delete_cookies_for_domain
    10101016webkit_cookie_manager_delete_all_cookies
  • trunk/Source/WebKit/UIProcess/API/wpe/WebKitCookieManager.h

    r218553 r225054  
    11/*
    22 * Copyright (C) 2012 Igalia S.L.
     3 * Copyright (C) 2017 Endless Mobile, Inc.
    34 *
    45 * This library is free software; you can redistribute it and/or
     
    2728#include <gio/gio.h>
    2829#include <glib-object.h>
     30#include <libsoup/soup.h>
    2931#include <wpe/WebKitDefines.h>
    3032
     
    108110                                                       GError                      **error);
    109111
     112WEBKIT_API void
     113webkit_cookie_manager_add_cookie                      (WebKitCookieManager          *cookie_manager,
     114                                                       SoupCookie                   *cookie,
     115                                                       GCancellable                 *cancellable,
     116                                                       GAsyncReadyCallback           callback,
     117                                                       gpointer                      user_data);
     118
     119WEBKIT_API gboolean
     120webkit_cookie_manager_add_cookie_finish               (WebKitCookieManager          *cookie_manager,
     121                                                       GAsyncResult                 *result,
     122                                                       GError                      **error);
     123
     124WEBKIT_API void
     125webkit_cookie_manager_get_cookies                     (WebKitCookieManager          *cookie_manager,
     126                                                       const gchar                  *uri,
     127                                                       GCancellable                 *cancellable,
     128                                                       GAsyncReadyCallback           callback,
     129                                                       gpointer                      user_data);
     130
     131WEBKIT_API GList *
     132webkit_cookie_manager_get_cookies_finish              (WebKitCookieManager          *cookie_manager,
     133                                                       GAsyncResult                 *result,
     134                                                       GError                      **error);
     135
     136WEBKIT_API void
     137webkit_cookie_manager_delete_cookie                   (WebKitCookieManager          *cookie_manager,
     138                                                       SoupCookie                   *cookie,
     139                                                       GCancellable                 *cancellable,
     140                                                       GAsyncReadyCallback           callback,
     141                                                       gpointer                      user_data);
     142
     143WEBKIT_API gboolean
     144webkit_cookie_manager_delete_cookie_finish            (WebKitCookieManager          *cookie_manager,
     145                                                       GAsyncResult                 *result,
     146                                                       GError                      **error);
     147
    110148WEBKIT_DEPRECATED_FOR(webkit_website_data_manager_fetch) void
    111149webkit_cookie_manager_get_domains_with_cookies        (WebKitCookieManager          *cookie_manager,
  • trunk/Tools/ChangeLog

    r225053 r225054  
     12017-11-20  Mario Sanchez Prada  <mario@endlessm.com>
     2
     3        [GTK] New API to add, retrieve and delete cookies via WebKitCookieManager
     4        https://bugs.webkit.org/show_bug.cgi?id=177932
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        Added new test cases to cover the newly added API for WebKitCookieManager:
     9        webkit_cookie_manager_add_cookie, webkit_cookie_manager_get_cookies and
     10        webkit_cookie_manager_delete_cookie.
     11
     12        * TestWebKitAPI/Tests/WebKitGLib/TestCookieManager.cpp:
     13        (testCookieManagerAddCookie): Added.
     14        (testCookieManagerGetCookies): Added.
     15        (testCookieManagerDeleteCookie): Added.
     16        (serverCallback): Small update to avoid hardcoding strings we reuse.
     17        (beforeAll): Added the new test cases to the test suite.
     18
    1192017-11-20  Stephan Szabo  <stephan.szabo@sony.com>
    220
  • trunk/Tools/TestWebKitAPI/Tests/WebKitGLib/TestCookieManager.cpp

    r225045 r225054  
    11/*
    22 * Copyright (C) 2012 Igalia S.L.
     3 * Copyright (C) 2017 Endless Mobile, Inc.
    34 *
    45 * This library is free software; you can redistribute it and/or
     
    2223#include "WebKitTestServer.h"
    2324#include "WebViewTest.h"
     25#include <WebCore/GUniquePtrSoup.h>
    2426#include <glib/gstdio.h>
    2527
     
    2830static const char* kFirstPartyDomain = "127.0.0.1";
    2931static const char* kThirdPartyDomain = "localhost";
     32
     33static const char* kCookieName = "foo";
     34static const char* kCookieValue = "bar";
     35static const char* kCookiePath = "/";
     36
     37static const char* kCookiePathNew = "/new";
     38static const char* kCookieValueNew = "new-value";
     39
    3040static const char* kIndexHtmlFormat =
    3141    "<html><body>"
     
    5666    {
    5767        g_strfreev(m_domains);
     68        g_list_free_full(m_cookies, reinterpret_cast<GDestroyNotify>(soup_cookie_free));
     69
    5870        g_signal_handlers_disconnect_matched(m_cookieManager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
    5971        if (m_cookiesTextFile)
     
    103115    }
    104116
     117    static void addCookieReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
     118    {
     119        GUniqueOutPtr<GError> error;
     120        bool added = webkit_cookie_manager_add_cookie_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
     121        g_assert(!error.get());
     122        g_assert(added);
     123
     124        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
     125        g_main_loop_quit(test->m_mainLoop);
     126    }
     127
     128    void addCookie(SoupCookie* cookie)
     129    {
     130        webkit_cookie_manager_add_cookie(m_cookieManager, cookie, 0, addCookieReadyCallback, this);
     131        g_main_loop_run(m_mainLoop);
     132    }
     133
     134    static void getCookiesReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
     135    {
     136        GUniqueOutPtr<GError> error;
     137        GList* cookies = webkit_cookie_manager_get_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
     138        g_assert(!error.get());
     139
     140        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
     141        test->m_cookies = cookies;
     142        g_main_loop_quit(test->m_mainLoop);
     143    }
     144
     145    GList* getCookies(const char* uri)
     146    {
     147        g_list_free_full(m_cookies, reinterpret_cast<GDestroyNotify>(soup_cookie_free));
     148        m_cookies = nullptr;
     149        webkit_cookie_manager_get_cookies(m_cookieManager, uri, 0, getCookiesReadyCallback, this);
     150        g_main_loop_run(m_mainLoop);
     151
     152        return m_cookies;
     153    }
     154
     155    static void deleteCookieReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
     156    {
     157        GUniqueOutPtr<GError> error;
     158        bool deleted = webkit_cookie_manager_delete_cookie_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
     159        g_assert(!error.get());
     160        g_assert(deleted);
     161
     162        CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
     163        g_main_loop_quit(test->m_mainLoop);
     164    }
     165
     166    void deleteCookie(SoupCookie* cookie)
     167    {
     168        webkit_cookie_manager_delete_cookie(m_cookieManager, cookie, 0, deleteCookieReadyCallback, this);
     169        g_main_loop_run(m_mainLoop);
     170    }
     171
    105172    void setAcceptPolicy(WebKitCookieAcceptPolicy policy)
    106173    {
     
    171238    WebKitCookieAcceptPolicy m_acceptPolicy { WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY };
    172239    char** m_domains { nullptr };
     240    GList* m_cookies { nullptr };
    173241    bool m_cookiesChanged { false };
    174242    int m_cookiesExpectedToChangeCount { 0 };
     
    208276    g_assert(domains);
    209277    g_assert_cmpint(g_strv_length(domains), ==, 0);
     278}
     279
     280static void testCookieManagerAddCookie(CookieManagerTest* test, gconstpointer)
     281{
     282    // Load the html content, with the default NO_THIRD_PARTY accept policy,
     283    // which will automatically add one cookie.
     284    test->loadURI(kServer->getURIForPath("/index.html").data());
     285    test->waitUntilLoadFinished();
     286    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     287
     288    // Check the cookies that have been added for the domain.
     289    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
     290    GList* foundCookies = test->getCookies(uri.get());
     291    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     292
     293    SoupCookie* foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     294    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     295    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
     296    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
     297    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);
     298
     299    // Try to add now a cookie with same (name, domain, path) than the ones already added.
     300    GUniquePtr<SoupCookie> firstCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePath, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
     301    test->addCookie(firstCookie.get());
     302
     303    // Still one cookie, since (name, domain, path) are the same than the already existing
     304    // one, but the new value is now stored as replaced by the recently added cookie.
     305    foundCookies = test->getCookies(uri.get());
     306    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     307
     308    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     309    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     310    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
     311    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
     312    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValueNew);
     313
     314    // Now create another cookie with a different path and add it.
     315    GUniquePtr<SoupCookie> secondCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
     316    test->addCookie(secondCookie.get());
     317    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     318
     319    // Retrieve the list of cookies for the same domain and path again now and check.
     320    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain, kCookiePathNew));
     321    foundCookies = test->getCookies(uri.get());
     322
     323    // We have now two cookies that would apply to the passed URL, one is the cookie initially
     324    // loaded with the web content and the other cookie the one we manually added.
     325    g_assert_cmpint(g_list_length(foundCookies), ==, 2);
     326
     327    // Add a third new cookie for a different domain than the previous ones.
     328    GUniquePtr<SoupCookie> thirdCookie(soup_cookie_new(kCookieName, kCookieValueNew, kThirdPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
     329    test->addCookie(thirdCookie.get());
     330
     331    // Only one cookie now, since the domain is different.
     332    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kThirdPartyDomain, kCookiePathNew));
     333    foundCookies = test->getCookies(uri.get());
     334    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     335    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);
     336
     337    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     338    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     339    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kThirdPartyDomain);
     340    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePathNew);
     341    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValueNew);
     342
     343    // Finally, delete all cookies and check they are all gone.
     344    test->deleteAllCookies();
     345    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
     346}
     347
     348static void testCookieManagerGetCookies(CookieManagerTest* test, gconstpointer)
     349{
     350    // Load the html content and retrieve the two cookies automatically added with ALWAYS policy.
     351    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
     352    test->loadURI(kServer->getURIForPath("/index.html").data());
     353    test->waitUntilLoadFinished();
     354    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);
     355
     356    // Retrieve the first cookie using a HTTP scheme.
     357    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
     358    GList* foundCookies = test->getCookies(uri.get());
     359    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     360
     361    SoupCookie* foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     362    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     363    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
     364    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
     365    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);
     366
     367    // Retrieve the second cookie using a HTTPS scheme.
     368    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTPS, kThirdPartyDomain));
     369    foundCookies = test->getCookies(uri.get());
     370    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     371
     372    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     373    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     374    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kThirdPartyDomain);
     375    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
     376    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);
     377
     378    // Create a new cookie and add it to the first domain.
     379    GUniquePtr<SoupCookie> newCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
     380    test->addCookie(newCookie.get());
     381
     382    // We should get two cookies that would apply to the same URL passed, since
     383    // http://127.0.0.1/new is a subset of the http://127.0.0.1/ URL.
     384    uri.reset(g_strdup_printf("%s://%s%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain, kCookiePathNew));
     385    foundCookies = test->getCookies(uri.get());
     386    g_assert_cmpint(g_list_length(foundCookies), ==, 2);
     387
     388    // We have now two cookies that would apply to the passed URL, one is the cookie initially
     389    // loaded with the web content and the other cookie the one we manually added.
     390    g_assert_cmpint(g_list_length(foundCookies), ==, 2);
     391
     392    bool newPathChecked = false;
     393    const char* pathFound = nullptr;
     394    const char* valueFound = nullptr;
     395    for (uint i = 0; i < 2; i++) {
     396        foundCookie = static_cast<SoupCookie*>(g_list_nth_data(foundCookies, i));
     397        g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     398        g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
     399
     400        // Cookies will have different values for 'value' and 'path', so make sure that
     401        // we check for both possibilities, but different ones for each cookie found.
     402        pathFound = soup_cookie_get_path(foundCookie);
     403        valueFound = soup_cookie_get_value(foundCookie);
     404        if (i > 0) {
     405            if (newPathChecked) {
     406                g_assert_cmpstr(pathFound, ==, kCookiePath);
     407                g_assert_cmpstr(valueFound, ==, kCookieValue);
     408            } else {
     409                g_assert_cmpstr(pathFound, ==, kCookiePathNew);
     410                g_assert_cmpstr(valueFound, ==, kCookieValueNew);
     411            }
     412        } else {
     413            if (g_strcmp0(pathFound, kCookiePath)) {
     414                g_assert_cmpstr(pathFound, ==, kCookiePathNew);
     415                g_assert_cmpstr(valueFound, ==, kCookieValueNew);
     416                newPathChecked = true;
     417            }
     418
     419            if (g_strcmp0(pathFound, kCookiePathNew)) {
     420                g_assert_cmpstr(pathFound, ==, kCookiePath);
     421                g_assert_cmpstr(valueFound, ==, kCookieValue);
     422                newPathChecked = false;
     423            }
     424        }
     425    }
     426
     427    // We should get 1 cookie only if we specify http://127.0.0.1/, though.
     428    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
     429    foundCookies = test->getCookies(uri.get());
     430    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     431
     432    foundCookie = static_cast<SoupCookie*>(foundCookies->data);
     433    g_assert_cmpstr(soup_cookie_get_name(foundCookie), ==, kCookieName);
     434    g_assert_cmpstr(soup_cookie_get_domain(foundCookie), ==, kFirstPartyDomain);
     435    g_assert_cmpstr(soup_cookie_get_path(foundCookie), ==, kCookiePath);
     436    g_assert_cmpstr(soup_cookie_get_value(foundCookie), ==, kCookieValue);
     437
     438    // Finally, delete all cookies and try to retrieve them again, one by one.
     439    test->deleteAllCookies();
     440    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
     441
     442    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
     443    foundCookies = test->getCookies(uri.get());
     444    g_assert_null(foundCookies);
     445}
     446
     447static void testCookieManagerDeleteCookie(CookieManagerTest* test, gconstpointer)
     448{
     449    test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
     450    test->loadURI(kServer->getURIForPath("/index.html").data());
     451    test->waitUntilLoadFinished();
     452
     453    // Initially, there should be two cookies available.
     454    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);
     455
     456    // Delete the cookie for the first party domain.
     457    GUniquePtr<char> uri(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kFirstPartyDomain));
     458    GList* foundCookies = test->getCookies(uri.get());
     459    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     460
     461    GUniquePtr<SoupCookie> firstPartyCookie(soup_cookie_copy(static_cast<SoupCookie*>(foundCookies->data)));
     462    test->deleteCookie(firstPartyCookie.get());
     463    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     464
     465    // Try deleting a non-existent cookie (wrong name).
     466    GUniquePtr<SoupCookie> wrongCookie(soup_cookie_new("wrong-name", kCookieValue, kThirdPartyDomain, kCookiePath, -1));
     467    test->deleteCookie(wrongCookie.get());
     468    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     469
     470    // Try deleting a non-existent cookie (wrong domain).
     471    wrongCookie.reset(soup_cookie_new(kCookieName, kCookieValue, "wrong-domain", kCookiePath, -1));
     472    test->deleteCookie(wrongCookie.get());
     473    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     474
     475    // Try deleting a non-existent cookie (wrong path).
     476    wrongCookie.reset(soup_cookie_new(kCookieName, kCookieValue, kThirdPartyDomain, "wrong-path", -1));
     477    test->deleteCookie(wrongCookie.get());
     478    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     479
     480    // Delete the cookie for the third party domain.
     481    uri.reset(g_strdup_printf("%s://%s", SOUP_URI_SCHEME_HTTP, kThirdPartyDomain));
     482    foundCookies = test->getCookies(uri.get());
     483    g_assert_cmpint(g_list_length(foundCookies), ==, 1);
     484
     485    GUniquePtr<SoupCookie> thirdPartyCookie(soup_cookie_copy(static_cast<SoupCookie*>(foundCookies->data)));
     486    test->deleteCookie(thirdPartyCookie.get());
     487    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
     488
     489    // Finally, add a new cookie now we don't have any and delete it afterwards.
     490    GUniquePtr<SoupCookie> newCookie(soup_cookie_new(kCookieName, kCookieValueNew, kFirstPartyDomain, kCookiePathNew, SOUP_COOKIE_MAX_AGE_ONE_HOUR));
     491    test->addCookie(newCookie.get());
     492    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
     493    test->deleteCookie(newCookie.get());
     494    g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
    210495}
    211496
     
    387672
    388673    soup_message_set_status(message, SOUP_STATUS_OK);
     674    gchar* header_str = g_strdup_printf("%s=%s; Max-Age=60", kCookieName, kCookieValue);
     675
    389676    if (g_str_equal(path, "/index.html")) {
    390677        char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server));
    391         soup_message_headers_replace(message->response_headers, "Set-Cookie", "foo=bar; Max-Age=60");
     678        soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
    392679        soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml));
    393680    } else if (g_str_equal(path, "/image.png"))
    394         soup_message_headers_replace(message->response_headers, "Set-Cookie", "baz=qux; Max-Age=60");
     681        soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
    395682    else if (g_str_equal(path, "/no-cookies.html")) {
    396683        static const char* indexHtml = "<html><body><p>No cookies</p></body></html>";
     
    407694
    408695    CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy);
     696    CookieManagerTest::add("WebKitCookieManager", "add-cookie", testCookieManagerAddCookie);
     697    CookieManagerTest::add("WebKitCookieManager", "get-cookies", testCookieManagerGetCookies);
     698    CookieManagerTest::add("WebKitCookieManager", "delete-cookie", testCookieManagerDeleteCookie);
    409699    CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies);
    410700    CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged);
Note: See TracChangeset for help on using the changeset viewer.