Use sendWithAsyncReply for cookie getting/clearing functions
[WebKit.git] / Source / WebKit / UIProcess / API / glib / WebKitCookieManager.cpp
1 /*
2  * Copyright (C) 2012 Igalia S.L.
3  * Copyright (C) 2017 Endless Mobile, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2,1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "WebKitCookieManager.h"
23
24 #include "SoupCookiePersistentStorageType.h"
25 #include "WebCookieManagerProxy.h"
26 #include "WebKitCookieManagerPrivate.h"
27 #include "WebKitEnumTypes.h"
28 #include "WebKitWebsiteDataManagerPrivate.h"
29 #include "WebKitWebsiteDataPrivate.h"
30 #include "WebsiteDataRecord.h"
31 #include <glib/gi18n-lib.h>
32 #include <pal/SessionID.h>
33 #include <wtf/glib/GRefPtr.h>
34 #include <wtf/glib/WTFGType.h>
35 #include <wtf/text/CString.h>
36
37 using namespace WebKit;
38
39 /**
40  * SECTION: WebKitCookieManager
41  * @Short_description: Defines how to handle cookies in a #WebKitWebContext
42  * @Title: WebKitCookieManager
43  *
44  * The WebKitCookieManager defines how to set up and handle cookies.
45  * You can get it from a #WebKitWebsiteDataManager with
46  * webkit_website_data_manager_get_cookie_manager(), and use it to set where to
47  * store cookies with webkit_cookie_manager_set_persistent_storage(),
48  * or to set the acceptance policy, with webkit_cookie_manager_get_accept_policy().
49  */
50
51 enum {
52     CHANGED,
53
54     LAST_SIGNAL
55 };
56
57 struct _WebKitCookieManagerPrivate {
58     PAL::SessionID sessionID() const
59     {
60         ASSERT(dataManager);
61         return webkitWebsiteDataManagerGetDataStore(dataManager).sessionID();
62     }
63
64     ~_WebKitCookieManagerPrivate()
65     {
66         for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(dataManager))
67             processPool->supplement<WebCookieManagerProxy>()->setCookieObserverCallback(sessionID(), nullptr);
68     }
69
70     WebKitWebsiteDataManager* dataManager;
71 };
72
73 static guint signals[LAST_SIGNAL] = { 0, };
74
75 WEBKIT_DEFINE_TYPE(WebKitCookieManager, webkit_cookie_manager, G_TYPE_OBJECT)
76
77 static inline SoupCookiePersistentStorageType toSoupCookiePersistentStorageType(WebKitCookiePersistentStorage kitStorage)
78 {
79     switch (kitStorage) {
80     case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
81         return SoupCookiePersistentStorageType::Text;
82     case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
83         return SoupCookiePersistentStorageType::SQLite;
84     default:
85         ASSERT_NOT_REACHED();
86         return SoupCookiePersistentStorageType::Text;
87     }
88 }
89
90 static inline WebKitCookieAcceptPolicy toWebKitCookieAcceptPolicy(HTTPCookieAcceptPolicy httpPolicy)
91 {
92     switch (httpPolicy) {
93     case HTTPCookieAcceptPolicy::AlwaysAccept:
94         return WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
95     case HTTPCookieAcceptPolicy::Never:
96         return WEBKIT_COOKIE_POLICY_ACCEPT_NEVER;
97     case HTTPCookieAcceptPolicy::OnlyFromMainDocumentDomain:
98         return WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY;
99     default:
100         ASSERT_NOT_REACHED();
101         return WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
102     }
103 }
104
105 static inline HTTPCookieAcceptPolicy toHTTPCookieAcceptPolicy(WebKitCookieAcceptPolicy kitPolicy)
106 {
107     switch (kitPolicy) {
108     case WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS:
109         return HTTPCookieAcceptPolicy::AlwaysAccept;
110     case WEBKIT_COOKIE_POLICY_ACCEPT_NEVER:
111         return HTTPCookieAcceptPolicy::Never;
112     case WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY:
113         return HTTPCookieAcceptPolicy::OnlyFromMainDocumentDomain;
114     default:
115         ASSERT_NOT_REACHED();
116         return HTTPCookieAcceptPolicy::AlwaysAccept;
117     }
118 }
119
120 static void webkit_cookie_manager_class_init(WebKitCookieManagerClass* findClass)
121 {
122     GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
123
124     /**
125      * WebKitCookieManager::changed:
126      * @cookie_manager: the #WebKitCookieManager
127      *
128      * This signal is emitted when cookies are added, removed or modified.
129      */
130     signals[CHANGED] =
131         g_signal_new("changed",
132                      G_TYPE_FROM_CLASS(gObjectClass),
133                      G_SIGNAL_RUN_LAST,
134                      0, 0, 0,
135                      g_cclosure_marshal_VOID__VOID,
136                      G_TYPE_NONE, 0);
137 }
138
139 WebKitCookieManager* webkitCookieManagerCreate(WebKitWebsiteDataManager* dataManager)
140 {
141     WebKitCookieManager* manager = WEBKIT_COOKIE_MANAGER(g_object_new(WEBKIT_TYPE_COOKIE_MANAGER, nullptr));
142     manager->priv->dataManager = dataManager;
143     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager)) {
144         processPool->supplement<WebCookieManagerProxy>()->setCookieObserverCallback(manager->priv->sessionID(), [manager] {
145             g_signal_emit(manager, signals[CHANGED], 0);
146         });
147     }
148     return manager;
149 }
150
151 /**
152  * webkit_cookie_manager_set_persistent_storage:
153  * @cookie_manager: a #WebKitCookieManager
154  * @filename: the filename to read to/write from
155  * @storage: a #WebKitCookiePersistentStorage
156  *
157  * Set the @filename where non-session cookies are stored persistently using
158  * @storage as the format to read/write the cookies.
159  * Cookies are initially read from @filename to create an initial set of cookies.
160  * Then, non-session cookies will be written to @filename when the WebKitCookieManager::changed
161  * signal is emitted.
162  * By default, @cookie_manager doesn't store the cookies persistently, so you need to call this
163  * method to keep cookies saved across sessions.
164  *
165  * This method should never be called on a #WebKitCookieManager associated to an ephemeral #WebKitWebsiteDataManager.
166  */
167 void webkit_cookie_manager_set_persistent_storage(WebKitCookieManager* manager, const char* filename, WebKitCookiePersistentStorage storage)
168 {
169     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
170     g_return_if_fail(filename);
171     g_return_if_fail(!webkit_website_data_manager_is_ephemeral(manager->priv->dataManager));
172
173     auto sessionID = manager->priv->sessionID();
174     if (sessionID.isEphemeral())
175         return;
176
177     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
178         processPool->supplement<WebCookieManagerProxy>()->setCookiePersistentStorage(sessionID, String::fromUTF8(filename), toSoupCookiePersistentStorageType(storage));
179 }
180
181 /**
182  * webkit_cookie_manager_set_accept_policy:
183  * @cookie_manager: a #WebKitCookieManager
184  * @policy: a #WebKitCookieAcceptPolicy
185  *
186  * Set the cookie acceptance policy of @cookie_manager as @policy.
187  */
188 void webkit_cookie_manager_set_accept_policy(WebKitCookieManager* manager, WebKitCookieAcceptPolicy policy)
189 {
190     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
191
192     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
193         processPool->supplement<WebCookieManagerProxy>()->setHTTPCookieAcceptPolicy(manager->priv->sessionID(), toHTTPCookieAcceptPolicy(policy), []() { });
194 }
195
196 /**
197  * webkit_cookie_manager_get_accept_policy:
198  * @cookie_manager: a #WebKitCookieManager
199  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
200  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
201  * @user_data: (closure): the data to pass to callback function
202  *
203  * Asynchronously get the cookie acceptance policy of @cookie_manager.
204  *
205  * When the operation is finished, @callback will be called. You can then call
206  * webkit_cookie_manager_get_accept_policy_finish() to get the result of the operation.
207  */
208 void webkit_cookie_manager_get_accept_policy(WebKitCookieManager* manager, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
209 {
210     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
211
212     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
213
214     // The policy is the same in all process pools having the same session ID, so just ask any.
215     const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
216     if (processPools.isEmpty()) {
217         g_task_return_int(task.get(), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
218         return;
219     }
220
221     processPools[0]->supplement<WebCookieManagerProxy>()->getHTTPCookieAcceptPolicy(manager->priv->sessionID(), [task = WTFMove(task)](HTTPCookieAcceptPolicy policy) {
222         g_task_return_int(task.get(), toWebKitCookieAcceptPolicy(policy));
223     });
224 }
225
226 /**
227  * webkit_cookie_manager_get_accept_policy_finish:
228  * @cookie_manager: a #WebKitCookieManager
229  * @result: a #GAsyncResult
230  * @error: return location for error or %NULL to ignore
231  *
232  * Finish an asynchronous operation started with webkit_cookie_manager_get_accept_policy().
233  *
234  * Returns: the cookie acceptance policy of @cookie_manager as a #WebKitCookieAcceptPolicy.
235  */
236 WebKitCookieAcceptPolicy webkit_cookie_manager_get_accept_policy_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
237 {
238     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
239     g_return_val_if_fail(g_task_is_valid(result, manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
240
241     gssize returnValue = g_task_propagate_int(G_TASK(result), error);
242     return returnValue == -1 ? WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY : static_cast<WebKitCookieAcceptPolicy>(returnValue);
243 }
244
245 /**
246  * webkit_cookie_manager_add_cookie:
247  * @cookie_manager: a #WebKitCookieManager
248  * @cookie: the #SoupCookie to be added
249  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
250  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
251  * @user_data: (closure): the data to pass to callback function
252  *
253  * Asynchronously add a #SoupCookie to the underlying storage.
254  *
255  * When the operation is finished, @callback will be called. You can then call
256  * webkit_cookie_manager_add_cookie_finish() to get the result of the operation.
257  *
258  * Since: 2.20
259  */
260 void webkit_cookie_manager_add_cookie(WebKitCookieManager* manager, SoupCookie* cookie, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
261 {
262     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
263     g_return_if_fail(cookie);
264
265     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
266
267     // Cookies are read/written from/to the same SQLite database on disk regardless
268     // of the process we access them from, so just use the first process pool.
269     const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
270     processPools[0]->supplement<WebCookieManagerProxy>()->setCookies(manager->priv->sessionID(), { WebCore::Cookie(cookie) }, [task = WTFMove(task)]() {
271         g_task_return_boolean(task.get(), TRUE);
272     });
273 }
274
275 /**
276  * webkit_cookie_manager_add_cookie_finish:
277  * @cookie_manager: a #WebKitCookieManager
278  * @result: a #GAsyncResult
279  * @error: return location for error or %NULL to ignore
280  *
281  * Finish an asynchronous operation started with webkit_cookie_manager_add_cookie().
282  *
283  * Returns: %TRUE if the cookie was added or %FALSE in case of error.
284  *
285  * Since: 2.20
286  */
287 gboolean webkit_cookie_manager_add_cookie_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
288 {
289     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), FALSE);
290     g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
291
292     return g_task_propagate_boolean(G_TASK(result), error);
293 }
294
295 /**
296  * webkit_cookie_manager_get_cookies:
297  * @cookie_manager: a #WebKitCookieManager
298  * @uri: the URI associated to the cookies to be retrieved
299  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
300  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
301  * @user_data: (closure): the data to pass to callback function
302  *
303  * Asynchronously get a list of #SoupCookie from @cookie_manager associated with @uri, which
304  * must be either an HTTP or an HTTPS URL.
305  *
306  * When the operation is finished, @callback will be called. You can then call
307  * webkit_cookie_manager_get_cookies_finish() to get the result of the operation.
308  *
309  * Since: 2.20
310  */
311 void webkit_cookie_manager_get_cookies(WebKitCookieManager* manager, const gchar* uri, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
312 {
313     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
314     g_return_if_fail(uri);
315
316     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
317
318     // Cookies are read/written from/to the same SQLite database on disk regardless
319     // of the process we access them from, so just use the first process pool.
320     const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
321     processPools[0]->supplement<WebCookieManagerProxy>()->getCookies(manager->priv->sessionID(), URL(URL(), String::fromUTF8(uri)), [task = WTFMove(task)](const Vector<WebCore::Cookie>& cookies) {
322         GList* cookiesList = nullptr;
323         for (auto& cookie : cookies)
324             cookiesList = g_list_prepend(cookiesList, cookie.toSoupCookie());
325
326         g_task_return_pointer(task.get(), g_list_reverse(cookiesList), [](gpointer data) {
327             g_list_free_full(static_cast<GList*>(data), reinterpret_cast<GDestroyNotify>(soup_cookie_free));
328         });
329     });
330 }
331
332 /**
333  * webkit_cookie_manager_get_cookies_finish:
334  * @cookie_manager: a #WebKitCookieManager
335  * @result: a #GAsyncResult
336  * @error: return location for error or %NULL to ignore
337  *
338  * Finish an asynchronous operation started with webkit_cookie_manager_get_cookies().
339  * The return value is a #GSList of #SoupCookie instances which should be released
340  * with g_list_free_full() and soup_cookie_free().
341  *
342  * Returns: (element-type SoupCookie) (transfer full): A #GList of #SoupCookie instances.
343  *
344  * Since: 2.20
345  */
346 GList* webkit_cookie_manager_get_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
347 {
348     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), nullptr);
349     g_return_val_if_fail(g_task_is_valid(result, manager), nullptr);
350
351     return reinterpret_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
352 }
353
354 /**
355  * webkit_cookie_manager_delete_cookie:
356  * @cookie_manager: a #WebKitCookieManager
357  * @cookie: the #SoupCookie to be deleted
358  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
359  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
360  * @user_data: (closure): the data to pass to callback function
361  *
362  * Asynchronously delete a #SoupCookie from the current session.
363  *
364  * When the operation is finished, @callback will be called. You can then call
365  * webkit_cookie_manager_delete_cookie_finish() to get the result of the operation.
366  *
367  * Since: 2.20
368  */
369 void webkit_cookie_manager_delete_cookie(WebKitCookieManager* manager, SoupCookie* cookie, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
370 {
371     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
372     g_return_if_fail(cookie);
373
374     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
375
376     // Cookies are read/written from/to the same SQLite database on disk regardless
377     // of the process we access them from, so just use the first process pool.
378     const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
379     processPools[0]->supplement<WebCookieManagerProxy>()->deleteCookie(manager->priv->sessionID(), WebCore::Cookie(cookie), [task = WTFMove(task)]() {
380         g_task_return_boolean(task.get(), TRUE);
381     });
382 }
383
384 /**
385  * webkit_cookie_manager_delete_cookie_finish:
386  * @cookie_manager: a #WebKitCookieManager
387  * @result: a #GAsyncResult
388  * @error: return location for error or %NULL to ignore
389  *
390  * Finish an asynchronous operation started with webkit_cookie_manager_delete_cookie().
391  *
392  * Returns: %TRUE if the cookie was deleted or %FALSE in case of error.
393  *
394  * Since: 2.20
395  */
396 gboolean webkit_cookie_manager_delete_cookie_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
397 {
398     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), FALSE);
399     g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
400
401     return g_task_propagate_boolean(G_TASK(result), error);
402 }
403
404 #if PLATFORM(GTK)
405 /**
406  * webkit_cookie_manager_get_domains_with_cookies:
407  * @cookie_manager: a #WebKitCookieManager
408  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
409  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
410  * @user_data: (closure): the data to pass to callback function
411  *
412  * Asynchronously get the list of domains for which @cookie_manager contains cookies.
413  *
414  * When the operation is finished, @callback will be called. You can then call
415  * webkit_cookie_manager_get_domains_with_cookies_finish() to get the result of the operation.
416  *
417  * Deprecated: 2.16: Use webkit_website_data_manager_fetch() instead.
418  */
419 void webkit_cookie_manager_get_domains_with_cookies(WebKitCookieManager* manager, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
420 {
421     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
422
423     GTask* task = g_task_new(manager, cancellable, callback, userData);
424     webkit_website_data_manager_fetch(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, cancellable, [](GObject* object, GAsyncResult* result, gpointer userData) {
425         GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
426         GError* error = nullptr;
427         GUniquePtr<GList> dataList(webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(object), result, &error));
428         if (error) {
429             g_task_return_error(task.get(), error);
430             return;
431         }
432
433         GPtrArray* domains = g_ptr_array_sized_new(g_list_length(dataList.get()));
434         for (GList* item = dataList.get(); item; item = g_list_next(item)) {
435             auto* data = static_cast<WebKitWebsiteData*>(item->data);
436             g_ptr_array_add(domains, g_strdup(webkit_website_data_get_name(data)));
437             webkit_website_data_unref(data);
438         }
439         g_ptr_array_add(domains, nullptr);
440         g_task_return_pointer(task.get(), g_ptr_array_free(domains, FALSE), reinterpret_cast<GDestroyNotify>(g_strfreev));
441     }, task);
442 }
443
444 /**
445  * webkit_cookie_manager_get_domains_with_cookies_finish:
446  * @cookie_manager: a #WebKitCookieManager
447  * @result: a #GAsyncResult
448  * @error: return location for error or %NULL to ignore
449  *
450  * Finish an asynchronous operation started with webkit_cookie_manager_get_domains_with_cookies().
451  * The return value is a %NULL terminated list of strings which should
452  * be released with g_strfreev().
453  *
454  * Returns: (transfer full) (array zero-terminated=1): A %NULL terminated array of domain names
455  *    or %NULL in case of error.
456  *
457  * Deprecated: 2.16: Use webkit_website_data_manager_fetch_finish() instead.
458  */
459 gchar** webkit_cookie_manager_get_domains_with_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
460 {
461     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), nullptr);
462     g_return_val_if_fail(g_task_is_valid(result, manager), nullptr);
463
464     return reinterpret_cast<char**>(g_task_propagate_pointer(G_TASK(result), error));
465 }
466
467 /**
468  * webkit_cookie_manager_delete_cookies_for_domain:
469  * @cookie_manager: a #WebKitCookieManager
470  * @domain: a domain name
471  *
472  * Remove all cookies of @cookie_manager for the given @domain.
473  *
474  * Deprecated: 2.16: Use webkit_website_data_manager_remove() instead.
475  */
476 void webkit_cookie_manager_delete_cookies_for_domain(WebKitCookieManager* manager, const gchar* domain)
477 {
478     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
479     g_return_if_fail(domain);
480
481     WebsiteDataRecord record;
482     record.addCookieHostName(String::fromUTF8(domain));
483     auto* data = webkitWebsiteDataCreate(WTFMove(record));
484     GList dataList = { data, nullptr, nullptr };
485     webkit_website_data_manager_remove(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, &dataList, nullptr, nullptr, nullptr);
486     webkit_website_data_unref(data);
487 }
488
489 /**
490  * webkit_cookie_manager_delete_all_cookies:
491  * @cookie_manager: a #WebKitCookieManager
492  *
493  * Delete all cookies of @cookie_manager
494  *
495  * Deprecated: 2.16: Use webkit_website_data_manager_clear() instead.
496  */
497 void webkit_cookie_manager_delete_all_cookies(WebKitCookieManager* manager)
498 {
499     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
500
501     webkit_website_data_manager_clear(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, 0, nullptr, nullptr, nullptr);
502 }
503 #endif