Move URL from WebCore to WTF
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitGLib / TestCookieManager.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 Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 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
23 #include "WebKitTestServer.h"
24 #include "WebViewTest.h"
25 #include <glib/gstdio.h>
26 #include <wtf/glib/GUniquePtrSoup.h>
27
28 static WebKitTestServer* kServer;
29
30 static const char* kFirstPartyDomain = "127.0.0.1";
31 static const char* kThirdPartyDomain = "localhost";
32
33 static const char* kCookieName = "foo";
34 static const char* kCookieValue = "bar";
35 static const char* kCookiePath = "/";
36
37 static const char* kCookiePathNew = "/new";
38 static const char* kCookieValueNew = "new-value";
39
40 static const char* kIndexHtmlFormat =
41     "<html><body>"
42     " <p>WebKitGTK+ Cookie Manager test</p>"
43     " <img src='http://localhost:%u/image.png' width=5 height=5></img>"
44     "</body></html>";
45
46 class CookieManagerTest: public WebViewTest {
47 public:
48     MAKE_GLIB_TEST_FIXTURE(CookieManagerTest);
49
50     static void cookiesChangedCallback(WebKitCookieManager*, CookieManagerTest* test)
51     {
52         test->m_cookiesChanged = true;
53         if (test->m_finishLoopWhenCookiesChange && !(--test->m_cookiesExpectedToChangeCount))
54             g_main_loop_quit(test->m_mainLoop);
55     }
56
57     CookieManagerTest()
58         : WebViewTest()
59         , m_cookieManager(webkit_web_context_get_cookie_manager(webkit_web_view_get_context(m_webView)))
60     {
61         g_assert(webkit_website_data_manager_get_cookie_manager(webkit_web_context_get_website_data_manager(webkit_web_view_get_context(m_webView))) == m_cookieManager);
62         g_signal_connect(m_cookieManager, "changed", G_CALLBACK(cookiesChangedCallback), this);
63     }
64
65     ~CookieManagerTest()
66     {
67         g_strfreev(m_domains);
68         g_list_free_full(m_cookies, reinterpret_cast<GDestroyNotify>(soup_cookie_free));
69
70         g_signal_handlers_disconnect_matched(m_cookieManager, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
71         if (m_cookiesTextFile)
72             g_unlink(m_cookiesTextFile.get());
73         if (m_cookiesSQLiteFile)
74             g_unlink(m_cookiesSQLiteFile.get());
75     }
76
77     void setPersistentStorage(WebKitCookiePersistentStorage storage)
78     {
79         const char* filename = 0;
80         switch (storage) {
81         case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
82             if (!m_cookiesTextFile)
83                 m_cookiesTextFile.reset(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
84             filename = m_cookiesTextFile.get();
85             break;
86         case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
87             if (!m_cookiesSQLiteFile)
88                 m_cookiesSQLiteFile.reset(g_build_filename(Test::dataDirectory(), "cookies.db", nullptr));
89             filename = m_cookiesSQLiteFile.get();
90             break;
91         default:
92             g_assert_not_reached();
93         }
94         webkit_cookie_manager_set_persistent_storage(m_cookieManager, filename, storage);
95     }
96
97     static void getAcceptPolicyReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
98     {
99         GUniqueOutPtr<GError> error;
100         WebKitCookieAcceptPolicy policy = webkit_cookie_manager_get_accept_policy_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
101         g_assert(!error.get());
102
103         CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
104         test->m_acceptPolicy = policy;
105         g_main_loop_quit(test->m_mainLoop);
106     }
107
108     WebKitCookieAcceptPolicy getAcceptPolicy()
109     {
110         m_acceptPolicy = WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY;
111         webkit_cookie_manager_get_accept_policy(m_cookieManager, 0, getAcceptPolicyReadyCallback, this);
112         g_main_loop_run(m_mainLoop);
113
114         return m_acceptPolicy;
115     }
116
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
172     void setAcceptPolicy(WebKitCookieAcceptPolicy policy)
173     {
174         webkit_cookie_manager_set_accept_policy(m_cookieManager, policy);
175     }
176
177     static void getDomainsReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
178     {
179         GUniqueOutPtr<GError> error;
180         G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
181         char** domains = webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
182         G_GNUC_END_IGNORE_DEPRECATIONS;
183         g_assert(!error.get());
184
185         CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
186         test->m_domains = domains;
187         g_main_loop_quit(test->m_mainLoop);
188     }
189
190     char** getDomains()
191     {
192         g_strfreev(m_domains);
193         m_domains = 0;
194         G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
195         webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, 0, getDomainsReadyCallback, this);
196         G_GNUC_END_IGNORE_DEPRECATIONS;
197         g_main_loop_run(m_mainLoop);
198
199         return m_domains;
200     }
201
202     bool hasDomain(const char* domain)
203     {
204         if (!m_domains)
205             return false;
206
207         for (size_t i = 0; m_domains[i]; ++i) {
208             if (g_str_equal(m_domains[i], domain))
209                 return true;
210         }
211         return false;
212     }
213
214     void deleteCookiesForDomain(const char* domain)
215     {
216         G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
217         webkit_cookie_manager_delete_cookies_for_domain(m_cookieManager, domain);
218         G_GNUC_END_IGNORE_DEPRECATIONS;
219     }
220
221     void deleteAllCookies()
222     {
223         G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
224         webkit_cookie_manager_delete_all_cookies(m_cookieManager);
225         G_GNUC_END_IGNORE_DEPRECATIONS;
226     }
227
228     void waitUntilCookiesChanged(int cookiesExpectedToChangeCount = 1)
229     {
230         m_cookiesChanged = false;
231         m_cookiesExpectedToChangeCount = cookiesExpectedToChangeCount;
232         m_finishLoopWhenCookiesChange = true;
233         g_main_loop_run(m_mainLoop);
234         m_finishLoopWhenCookiesChange = false;
235     }
236
237     WebKitCookieManager* m_cookieManager { nullptr };
238     WebKitCookieAcceptPolicy m_acceptPolicy { WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY };
239     char** m_domains { nullptr };
240     GList* m_cookies { nullptr };
241     bool m_cookiesChanged { false };
242     int m_cookiesExpectedToChangeCount { 0 };
243     bool m_finishLoopWhenCookiesChange { false };
244     GUniquePtr<char> m_cookiesTextFile;
245     GUniquePtr<char> m_cookiesSQLiteFile;
246 };
247
248 static void testCookieManagerAcceptPolicy(CookieManagerTest* test, gconstpointer)
249 {
250     // Default policy is NO_THIRD_PARTY.
251     g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY);
252     test->loadURI(kServer->getURIForPath("/index.html").data());
253     test->waitUntilLoadFinished();
254     char** domains = test->getDomains();
255     g_assert(domains);
256     g_assert_cmpint(g_strv_length(domains), ==, 1);
257     g_assert_cmpstr(domains[0], ==, kFirstPartyDomain);
258     test->deleteAllCookies();
259
260     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
261     g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
262     test->loadURI(kServer->getURIForPath("/index.html").data());
263     test->waitUntilLoadFinished();
264     domains = test->getDomains();
265     g_assert(domains);
266     g_assert_cmpint(g_strv_length(domains), ==, 2);
267     g_assert(test->hasDomain(kFirstPartyDomain));
268     g_assert(test->hasDomain(kThirdPartyDomain));
269     test->deleteAllCookies();
270
271     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_NEVER);
272     g_assert_cmpint(test->getAcceptPolicy(), ==, WEBKIT_COOKIE_POLICY_ACCEPT_NEVER);
273     test->loadURI(kServer->getURIForPath("/index.html").data());
274     test->waitUntilLoadFinished();
275     domains = test->getDomains();
276     g_assert(domains);
277     g_assert_cmpint(g_strv_length(domains), ==, 0);
278 }
279
280 static 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
348 static 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
447 static 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);
495 }
496
497 static void testCookieManagerDeleteCookies(CookieManagerTest* test, gconstpointer)
498 {
499     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
500     test->loadURI(kServer->getURIForPath("/index.html").data());
501     test->waitUntilLoadFinished();
502     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);
503
504     // Delete first party cookies.
505     test->deleteCookiesForDomain(kFirstPartyDomain);
506     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 1);
507
508     // Delete third party cookies.
509     test->deleteCookiesForDomain(kThirdPartyDomain);
510     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
511
512     test->loadURI(kServer->getURIForPath("/index.html").data());
513     test->waitUntilLoadFinished();
514     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 2);
515
516     // Delete all cookies.
517     test->deleteAllCookies();
518     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
519 }
520
521 static void testCookieManagerCookiesChanged(CookieManagerTest* test, gconstpointer)
522 {
523     g_assert(!test->m_cookiesChanged);
524     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
525     test->loadURI(kServer->getURIForPath("/index.html").data());
526     test->waitUntilLoadFinished();
527     g_assert(test->m_cookiesChanged);
528
529     test->deleteCookiesForDomain(kFirstPartyDomain);
530     test->waitUntilCookiesChanged();
531     g_assert(test->m_cookiesChanged);
532
533     test->deleteAllCookies();
534     test->waitUntilCookiesChanged();
535     g_assert(test->m_cookiesChanged);
536 }
537
538 static void testCookieManagerPersistentStorage(CookieManagerTest* test, gconstpointer)
539 {
540     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
541
542     // Text storage using a new file.
543     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
544     char** domains = test->getDomains();
545     g_assert(domains);
546     g_assert_cmpint(g_strv_length(domains), ==, 0);
547
548     test->loadURI(kServer->getURIForPath("/index.html").data());
549     test->waitUntilLoadFinished();
550     g_assert(test->m_cookiesChanged);
551     domains = test->getDomains();
552     g_assert(domains);
553     g_assert_cmpint(g_strv_length(domains), ==, 2);
554
555
556     // SQLite storage using a new file.
557     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
558     domains = test->getDomains();
559     g_assert(domains);
560     g_assert_cmpint(g_strv_length(domains), ==, 0);
561
562     test->loadURI(kServer->getURIForPath("/index.html").data());
563     test->waitUntilLoadFinished();
564     g_assert(test->m_cookiesChanged);
565     domains = test->getDomains();
566     g_assert(domains);
567     g_assert_cmpint(g_strv_length(domains), ==, 2);
568
569     // Text storage using an existing file.
570     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
571     domains = test->getDomains();
572     g_assert(domains);
573     g_assert_cmpint(g_strv_length(domains), ==, 2);
574     test->deleteAllCookies();
575     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
576
577     // SQLite storage with an existing file.
578     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
579     domains = test->getDomains();
580     g_assert(domains);
581     g_assert_cmpint(g_strv_length(domains), ==, 2);
582     test->deleteAllCookies();
583     g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
584 }
585
586 static void testCookieManagerPersistentStorageDeleteAll(CookieManagerTest* test, gconstpointer)
587 {
588     // This checks that we can remove all the cookies of an existing file before a web process is created.
589     // See bug https://bugs.webkit.org/show_bug.cgi?id=175265.
590     static const char cookiesFileFormat[] = "127.0.0.1\tFALSE\t/\tFALSE\t%ld\tfoo\tbar\nlocalhost\tFALSE\t/\tFALSE\t%ld\tbaz\tqux\n";
591     time_t expires = time(nullptr) + 60;
592     GUniquePtr<char> cookiesFileContents(g_strdup_printf(cookiesFileFormat, expires, expires));
593     GUniquePtr<char> cookiesFile(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
594     g_assert(g_file_set_contents(cookiesFile.get(), cookiesFileContents.get(), -1, nullptr));
595
596     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
597     test->deleteAllCookies();
598     // Changed signal is emitted for every deleted cookie, twice in this case.
599     test->waitUntilCookiesChanged(2);
600
601     // Ensure the web process is created and load something without cookies.
602     test->m_cookiesChanged = false;
603     test->loadURI(kServer->getURIForPath("/no-cookies.html").data());
604     test->waitUntilLoadFinished();
605     g_assert(!test->m_cookiesChanged);
606     char** domains = test->getDomains();
607     g_assert(domains);
608     g_assert_cmpint(g_strv_length(domains), ==, 0);
609 }
610
611 static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
612 {
613     if (loadEvent != WEBKIT_LOAD_FINISHED)
614         return;
615     g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
616     test->quitMainLoop();
617 }
618
619 static void testCookieManagerEphemeral(CookieManagerTest* test, gconstpointer)
620 {
621     test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
622     test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
623     char** domains = test->getDomains();
624     g_assert(domains);
625     g_assert_cmpint(g_strv_length(domains), ==, 0);
626
627     auto webView = Test::adoptView(g_object_new(WEBKIT_TYPE_WEB_VIEW,
628 #if PLATFORM(WPE)
629         "backend", Test::createWebViewBackend(),
630 #endif
631         "web-context", webkit_web_view_get_context(test->m_webView),
632         "is-ephemeral", TRUE,
633         nullptr));
634     g_assert(webkit_web_view_is_ephemeral(webView.get()));
635     g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get())));
636
637     g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
638     webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/index.html").data());
639     g_main_loop_run(test->m_mainLoop);
640
641     domains = test->getDomains();
642     g_assert(domains);
643     g_assert_cmpint(g_strv_length(domains), ==, 0);
644
645     auto* viewDataManager = webkit_web_view_get_website_data_manager(webView.get());
646     g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(viewDataManager));
647     test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewDataManager));
648     g_assert(viewDataManager != webkit_web_context_get_website_data_manager(webkit_web_view_get_context(test->m_webView)));
649     auto* cookieManager = webkit_website_data_manager_get_cookie_manager(viewDataManager);
650     g_assert(WEBKIT_IS_COOKIE_MANAGER(cookieManager));
651     test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(cookieManager));
652     g_assert(cookieManager != test->m_cookieManager);
653     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
654     webkit_cookie_manager_get_domains_with_cookies(cookieManager, nullptr, [](GObject* object, GAsyncResult* result, gpointer userData) {
655         auto* test = static_cast<CookieManagerTest*>(userData);
656         GUniquePtr<char*> domains(webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, nullptr));
657         g_assert(domains);
658         g_assert_cmpint(g_strv_length(domains.get()), ==, 1);
659         g_assert_cmpstr(domains.get()[0], ==, kFirstPartyDomain);
660         test->quitMainLoop();
661     }, test);
662     G_GNUC_END_IGNORE_DEPRECATIONS;
663     g_main_loop_run(test->m_mainLoop);
664 }
665
666 static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
667 {
668     if (message->method != SOUP_METHOD_GET) {
669         soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
670         return;
671     }
672
673     soup_message_set_status(message, SOUP_STATUS_OK);
674     gchar* header_str = g_strdup_printf("%s=%s; Max-Age=60", kCookieName, kCookieValue);
675
676     if (g_str_equal(path, "/index.html")) {
677         char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server));
678         soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
679         soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml));
680     } else if (g_str_equal(path, "/image.png"))
681         soup_message_headers_replace(message->response_headers, "Set-Cookie", header_str);
682     else if (g_str_equal(path, "/no-cookies.html")) {
683         static const char* indexHtml = "<html><body><p>No cookies</p></body></html>";
684         soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHtml, strlen(indexHtml));
685     } else
686         soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
687     soup_message_body_complete(message->response_body);
688 }
689
690 void beforeAll()
691 {
692     kServer = new WebKitTestServer();
693     kServer->run(serverCallback);
694
695     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);
699     CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies);
700     CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged);
701     CookieManagerTest::add("WebKitCookieManager", "persistent-storage", testCookieManagerPersistentStorage);
702     CookieManagerTest::add("WebKitCookieManager", "persistent-storage-delete-all", testCookieManagerPersistentStorageDeleteAll);
703     CookieManagerTest::add("WebKitCookieManager", "ephemeral", testCookieManagerEphemeral);
704 }
705
706 void afterAll()
707 {
708     delete kServer;
709 }