Move URL from WebCore to WTF
[WebKit-https.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     ~_WebKitCookieManagerPrivate()
59     {
60         auto sessionID = webkitWebsiteDataManagerGetDataStore(dataManager).websiteDataStore().sessionID();
61         for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(dataManager))
62             processPool->supplement<WebCookieManagerProxy>()->setCookieObserverCallback(sessionID, nullptr);
63     }
64
65     WebKitWebsiteDataManager* dataManager;
66 };
67
68 static guint signals[LAST_SIGNAL] = { 0, };
69
70 WEBKIT_DEFINE_TYPE(WebKitCookieManager, webkit_cookie_manager, G_TYPE_OBJECT)
71
72 static inline SoupCookiePersistentStorageType toSoupCookiePersistentStorageType(WebKitCookiePersistentStorage kitStorage)
73 {
74     switch (kitStorage) {
75     case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
76         return SoupCookiePersistentStorageText;
77     case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
78         return SoupCookiePersistentStorageSQLite;
79     default:
80         ASSERT_NOT_REACHED();
81         return SoupCookiePersistentStorageText;
82     }
83 }
84
85 static inline WebKitCookieAcceptPolicy toWebKitCookieAcceptPolicy(HTTPCookieAcceptPolicy httpPolicy)
86 {
87     switch (httpPolicy) {
88     case HTTPCookieAcceptPolicyAlways:
89         return WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
90     case HTTPCookieAcceptPolicyNever:
91         return WEBKIT_COOKIE_POLICY_ACCEPT_NEVER;
92     case HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain:
93         return WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY;
94     default:
95         ASSERT_NOT_REACHED();
96         return WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS;
97     }
98 }
99
100 static inline HTTPCookieAcceptPolicy toHTTPCookieAcceptPolicy(WebKitCookieAcceptPolicy kitPolicy)
101 {
102     switch (kitPolicy) {
103     case WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS:
104         return HTTPCookieAcceptPolicyAlways;
105     case WEBKIT_COOKIE_POLICY_ACCEPT_NEVER:
106         return HTTPCookieAcceptPolicyNever;
107     case WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY:
108         return HTTPCookieAcceptPolicyOnlyFromMainDocumentDomain;
109     default:
110         ASSERT_NOT_REACHED();
111         return HTTPCookieAcceptPolicyAlways;
112     }
113 }
114
115 static void webkit_cookie_manager_class_init(WebKitCookieManagerClass* findClass)
116 {
117     GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
118
119     /**
120      * WebKitCookieManager::changed:
121      * @cookie_manager: the #WebKitCookieManager
122      *
123      * This signal is emitted when cookies are added, removed or modified.
124      */
125     signals[CHANGED] =
126         g_signal_new("changed",
127                      G_TYPE_FROM_CLASS(gObjectClass),
128                      G_SIGNAL_RUN_LAST,
129                      0, 0, 0,
130                      g_cclosure_marshal_VOID__VOID,
131                      G_TYPE_NONE, 0);
132 }
133
134 WebKitCookieManager* webkitCookieManagerCreate(WebKitWebsiteDataManager* dataManager)
135 {
136     WebKitCookieManager* manager = WEBKIT_COOKIE_MANAGER(g_object_new(WEBKIT_TYPE_COOKIE_MANAGER, nullptr));
137     manager->priv->dataManager = dataManager;
138     auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
139     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager)) {
140         processPool->supplement<WebCookieManagerProxy>()->setCookieObserverCallback(sessionID, [manager] {
141             g_signal_emit(manager, signals[CHANGED], 0);
142         });
143     }
144     return manager;
145 }
146
147 /**
148  * webkit_cookie_manager_set_persistent_storage:
149  * @cookie_manager: a #WebKitCookieManager
150  * @filename: the filename to read to/write from
151  * @storage: a #WebKitCookiePersistentStorage
152  *
153  * Set the @filename where non-session cookies are stored persistently using
154  * @storage as the format to read/write the cookies.
155  * Cookies are initially read from @filename to create an initial set of cookies.
156  * Then, non-session cookies will be written to @filename when the WebKitCookieManager::changed
157  * signal is emitted.
158  * By default, @cookie_manager doesn't store the cookies persistently, so you need to call this
159  * method to keep cookies saved across sessions.
160  *
161  * This method should never be called on a #WebKitCookieManager associated to an ephemeral #WebKitWebsiteDataManager.
162  */
163 void webkit_cookie_manager_set_persistent_storage(WebKitCookieManager* manager, const char* filename, WebKitCookiePersistentStorage storage)
164 {
165     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
166     g_return_if_fail(filename);
167     g_return_if_fail(!webkit_website_data_manager_is_ephemeral(manager->priv->dataManager));
168
169     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
170         processPool->supplement<WebCookieManagerProxy>()->setCookiePersistentStorage(String::fromUTF8(filename), toSoupCookiePersistentStorageType(storage));
171 }
172
173 /**
174  * webkit_cookie_manager_set_accept_policy:
175  * @cookie_manager: a #WebKitCookieManager
176  * @policy: a #WebKitCookieAcceptPolicy
177  *
178  * Set the cookie acceptance policy of @cookie_manager as @policy.
179  */
180 void webkit_cookie_manager_set_accept_policy(WebKitCookieManager* manager, WebKitCookieAcceptPolicy policy)
181 {
182     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
183
184     for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
185         processPool->supplement<WebCookieManagerProxy>()->setHTTPCookieAcceptPolicy(PAL::SessionID::defaultSessionID(), toHTTPCookieAcceptPolicy(policy), [](CallbackBase::Error){});
186 }
187
188 /**
189  * webkit_cookie_manager_get_accept_policy:
190  * @cookie_manager: a #WebKitCookieManager
191  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
192  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
193  * @user_data: (closure): the data to pass to callback function
194  *
195  * Asynchronously get the cookie acceptance policy of @cookie_manager.
196  *
197  * When the operation is finished, @callback will be called. You can then call
198  * webkit_cookie_manager_get_accept_policy_finish() to get the result of the operation.
199  */
200 void webkit_cookie_manager_get_accept_policy(WebKitCookieManager* manager, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
201 {
202     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
203
204     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
205
206     // The policy is the same in all process pools having the same session ID, so just ask any.
207     const auto& processPools = webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager);
208     if (processPools.isEmpty()) {
209         g_task_return_int(task.get(), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
210         return;
211     }
212
213     processPools[0]->supplement<WebCookieManagerProxy>()->getHTTPCookieAcceptPolicy(PAL::SessionID::defaultSessionID(), [task = WTFMove(task)](HTTPCookieAcceptPolicy policy, CallbackBase::Error) {
214         g_task_return_int(task.get(), toWebKitCookieAcceptPolicy(policy));
215     });
216 }
217
218 /**
219  * webkit_cookie_manager_get_accept_policy_finish:
220  * @cookie_manager: a #WebKitCookieManager
221  * @result: a #GAsyncResult
222  * @error: return location for error or %NULL to ignore
223  *
224  * Finish an asynchronous operation started with webkit_cookie_manager_get_accept_policy().
225  *
226  * Returns: the cookie acceptance policy of @cookie_manager as a #WebKitCookieAcceptPolicy.
227  */
228 WebKitCookieAcceptPolicy webkit_cookie_manager_get_accept_policy_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
229 {
230     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
231     g_return_val_if_fail(g_task_is_valid(result, manager), WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
232
233     gssize returnValue = g_task_propagate_int(G_TASK(result), error);
234     return returnValue == -1 ? WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY : static_cast<WebKitCookieAcceptPolicy>(returnValue);
235 }
236
237 /**
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  */
252 void 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  */
288 gboolean 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  */
312 void 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, URL(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  */
356 GList* 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  */
379 void 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  */
415 gboolean 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 #if PLATFORM(GTK)
424 /**
425  * webkit_cookie_manager_get_domains_with_cookies:
426  * @cookie_manager: a #WebKitCookieManager
427  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
428  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
429  * @user_data: (closure): the data to pass to callback function
430  *
431  * Asynchronously get the list of domains for which @cookie_manager contains cookies.
432  *
433  * When the operation is finished, @callback will be called. You can then call
434  * webkit_cookie_manager_get_domains_with_cookies_finish() to get the result of the operation.
435  *
436  * Deprecated: 2.16: Use webkit_website_data_manager_fetch() instead.
437  */
438 void webkit_cookie_manager_get_domains_with_cookies(WebKitCookieManager* manager, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
439 {
440     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
441
442     GTask* task = g_task_new(manager, cancellable, callback, userData);
443     webkit_website_data_manager_fetch(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, cancellable, [](GObject* object, GAsyncResult* result, gpointer userData) {
444         GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
445         GError* error = nullptr;
446         GUniquePtr<GList> dataList(webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(object), result, &error));
447         if (error) {
448             g_task_return_error(task.get(), error);
449             return;
450         }
451
452         GPtrArray* domains = g_ptr_array_sized_new(g_list_length(dataList.get()));
453         for (GList* item = dataList.get(); item; item = g_list_next(item)) {
454             auto* data = static_cast<WebKitWebsiteData*>(item->data);
455             g_ptr_array_add(domains, g_strdup(webkit_website_data_get_name(data)));
456             webkit_website_data_unref(data);
457         }
458         g_ptr_array_add(domains, nullptr);
459         g_task_return_pointer(task.get(), g_ptr_array_free(domains, FALSE), reinterpret_cast<GDestroyNotify>(g_strfreev));
460     }, task);
461 }
462
463 /**
464  * webkit_cookie_manager_get_domains_with_cookies_finish:
465  * @cookie_manager: a #WebKitCookieManager
466  * @result: a #GAsyncResult
467  * @error: return location for error or %NULL to ignore
468  *
469  * Finish an asynchronous operation started with webkit_cookie_manager_get_domains_with_cookies().
470  * The return value is a %NULL terminated list of strings which should
471  * be released with g_strfreev().
472  *
473  * Returns: (transfer full) (array zero-terminated=1): A %NULL terminated array of domain names
474  *    or %NULL in case of error.
475  *
476  * Deprecated: 2.16: Use webkit_website_data_manager_fetch_finish() instead.
477  */
478 gchar** webkit_cookie_manager_get_domains_with_cookies_finish(WebKitCookieManager* manager, GAsyncResult* result, GError** error)
479 {
480     g_return_val_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager), nullptr);
481     g_return_val_if_fail(g_task_is_valid(result, manager), nullptr);
482
483     return reinterpret_cast<char**>(g_task_propagate_pointer(G_TASK(result), error));
484 }
485
486 /**
487  * webkit_cookie_manager_delete_cookies_for_domain:
488  * @cookie_manager: a #WebKitCookieManager
489  * @domain: a domain name
490  *
491  * Remove all cookies of @cookie_manager for the given @domain.
492  *
493  * Deprecated: 2.16: Use webkit_website_data_manager_remove() instead.
494  */
495 void webkit_cookie_manager_delete_cookies_for_domain(WebKitCookieManager* manager, const gchar* domain)
496 {
497     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
498     g_return_if_fail(domain);
499
500     WebsiteDataRecord record;
501     record.addCookieHostName(String::fromUTF8(domain));
502     auto* data = webkitWebsiteDataCreate(WTFMove(record));
503     GList dataList = { data, nullptr, nullptr };
504     webkit_website_data_manager_remove(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, &dataList, nullptr, nullptr, nullptr);
505     webkit_website_data_unref(data);
506 }
507
508 /**
509  * webkit_cookie_manager_delete_all_cookies:
510  * @cookie_manager: a #WebKitCookieManager
511  *
512  * Delete all cookies of @cookie_manager
513  *
514  * Deprecated: 2.16: Use webkit_website_data_manager_clear() instead.
515  */
516 void webkit_cookie_manager_delete_all_cookies(WebKitCookieManager* manager)
517 {
518     g_return_if_fail(WEBKIT_IS_COOKIE_MANAGER(manager));
519
520     webkit_website_data_manager_clear(manager->priv->dataManager, WEBKIT_WEBSITE_DATA_COOKIES, 0, nullptr, nullptr, nullptr);
521 }
522 #endif