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 <WebCore/GUniquePtrSoup.h> |
26 | #include <glib/gstdio.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(m_webContext.get())) |
60 | { |
61 | g_assert_true(webkit_website_data_manager_get_cookie_manager(webkit_web_context_get_website_data_manager(m_webContext.get())) == 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_no_error(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_no_error(error.get()); |
122 | g_assert_true(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_no_error(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_no_error(error.get()); |
160 | g_assert_true(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_no_error(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_nonnull(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_nonnull(domains); |
266 | g_assert_cmpint(g_strv_length(domains), ==, 2); |
267 | g_assert_true(test->hasDomain(kFirstPartyDomain)); |
268 | g_assert_true(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_nonnull(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_false(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_true(test->m_cookiesChanged); |
528 | |
529 | test->deleteCookiesForDomain(kFirstPartyDomain); |
530 | test->waitUntilCookiesChanged(); |
531 | g_assert_true(test->m_cookiesChanged); |
532 | |
533 | test->deleteAllCookies(); |
534 | test->waitUntilCookiesChanged(); |
535 | g_assert_true(test->m_cookiesChanged); |
536 | } |
537 | |
538 | class CookiePersistentStorageTest : public CookieManagerTest { |
539 | public: |
540 | MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(CookiePersistentStorageTest, setup, teardown); |
541 | |
542 | static void setup() |
543 | { |
544 | WebViewTest::shouldInitializeWebViewInConstructor = false; |
545 | } |
546 | |
547 | static void teardown() |
548 | { |
549 | WebViewTest::shouldInitializeWebViewInConstructor = true; |
550 | } |
551 | }; |
552 | |
553 | static void testCookieManagerPersistentStorage(CookiePersistentStorageTest* test, gconstpointer) |
554 | { |
555 | test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); |
556 | |
557 | g_unlink(test->m_cookiesTextFile.get()); |
558 | g_unlink(test->m_cookiesSQLiteFile.get()); |
559 | |
560 | // Text storage using a new file. |
561 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); |
562 | char** domains = test->getDomains(); |
563 | g_assert_nonnull(domains); |
564 | g_assert_cmpint(g_strv_length(domains), ==, 0); |
565 | |
566 | // Initialization of web view is deferred to ensure it's not required for |
567 | // setting persistent storage to work. |
568 | test->initializeWebView(); |
569 | test->loadURI(kServer->getURIForPath("/index.html" ).data()); |
570 | test->waitUntilLoadFinished(); |
571 | g_assert_true(test->m_cookiesChanged); |
572 | domains = test->getDomains(); |
573 | g_assert_nonnull(domains); |
574 | g_assert_cmpint(g_strv_length(domains), ==, 2); |
575 | g_assert_true(g_file_test(test->m_cookiesTextFile.get(), G_FILE_TEST_EXISTS)); |
576 | |
577 | // SQLite storage using a new file. |
578 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE); |
579 | domains = test->getDomains(); |
580 | g_assert_nonnull(domains); |
581 | g_assert_cmpint(g_strv_length(domains), ==, 0); |
582 | |
583 | test->loadURI(kServer->getURIForPath("/index.html" ).data()); |
584 | test->waitUntilLoadFinished(); |
585 | g_assert_true(test->m_cookiesChanged); |
586 | domains = test->getDomains(); |
587 | g_assert_nonnull(domains); |
588 | g_assert_cmpint(g_strv_length(domains), ==, 2); |
589 | g_assert_true(g_file_test(test->m_cookiesSQLiteFile.get(), G_FILE_TEST_EXISTS)); |
590 | |
591 | // Text storage using an existing file. |
592 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); |
593 | domains = test->getDomains(); |
594 | g_assert_nonnull(domains); |
595 | g_assert_cmpint(g_strv_length(domains), ==, 2); |
596 | test->deleteAllCookies(); |
597 | g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); |
598 | |
599 | // SQLite storage with an existing file. |
600 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE); |
601 | domains = test->getDomains(); |
602 | g_assert_nonnull(domains); |
603 | g_assert_cmpint(g_strv_length(domains), ==, 2); |
604 | test->deleteAllCookies(); |
605 | g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0); |
606 | } |
607 | |
608 | static void testCookieManagerPersistentStorageDeleteAll(CookieManagerTest* test, gconstpointer) |
609 | { |
610 | // This checks that we can remove all the cookies of an existing file before a web process is created. |
611 | // See bug https://bugs.webkit.org/show_bug.cgi?id=175265. |
612 | static const char cookiesFileFormat[] = "127.0.0.1\tFALSE\t/\tFALSE\t%ld\tfoo\tbar\nlocalhost\tFALSE\t/\tFALSE\t%ld\tbaz\tqux\n" ; |
613 | time_t expires = time(nullptr) + 60; |
614 | GUniquePtr<char> cookiesFileContents(g_strdup_printf(cookiesFileFormat, expires, expires)); |
615 | GUniquePtr<char> cookiesFile(g_build_filename(Test::dataDirectory(), "cookies.txt" , nullptr)); |
616 | g_assert_true(g_file_set_contents(cookiesFile.get(), cookiesFileContents.get(), -1, nullptr)); |
617 | |
618 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); |
619 | test->deleteAllCookies(); |
620 | // Changed signal is emitted for every deleted cookie, twice in this case. |
621 | test->waitUntilCookiesChanged(2); |
622 | |
623 | // Ensure the web process is created and load something without cookies. |
624 | test->m_cookiesChanged = false; |
625 | test->loadURI(kServer->getURIForPath("/no-cookies.html" ).data()); |
626 | test->waitUntilLoadFinished(); |
627 | g_assert_false(test->m_cookiesChanged); |
628 | char** domains = test->getDomains(); |
629 | g_assert_nonnull(domains); |
630 | g_assert_cmpint(g_strv_length(domains), ==, 0); |
631 | } |
632 | |
633 | static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test) |
634 | { |
635 | if (loadEvent != WEBKIT_LOAD_FINISHED) |
636 | return; |
637 | g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test); |
638 | test->quitMainLoop(); |
639 | } |
640 | |
641 | static void testCookieManagerEphemeral(CookieManagerTest* test, gconstpointer) |
642 | { |
643 | test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS); |
644 | test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); |
645 | char** domains = test->getDomains(); |
646 | g_assert_nonnull(domains); |
647 | g_assert_cmpint(g_strv_length(domains), ==, 0); |
648 | |
649 | auto webView = Test::adoptView(g_object_new(WEBKIT_TYPE_WEB_VIEW, |
650 | #if PLATFORM(WPE) |
651 | "backend" , Test::createWebViewBackend(), |
652 | #endif |
653 | "web-context" , webkit_web_view_get_context(test->m_webView), |
654 | "is-ephemeral" , TRUE, |
655 | nullptr)); |
656 | g_assert_true(webkit_web_view_is_ephemeral(webView.get())); |
657 | g_assert_false(webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get()))); |
658 | |
659 | g_signal_connect(webView.get(), "load-changed" , G_CALLBACK(ephemeralViewloadChanged), test); |
660 | webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/index.html" ).data()); |
661 | g_main_loop_run(test->m_mainLoop); |
662 | |
663 | domains = test->getDomains(); |
664 | g_assert_nonnull(domains); |
665 | g_assert_cmpint(g_strv_length(domains), ==, 0); |
666 | |
667 | auto* viewDataManager = webkit_web_view_get_website_data_manager(webView.get()); |
668 | g_assert_true(WEBKIT_IS_WEBSITE_DATA_MANAGER(viewDataManager)); |
669 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewDataManager)); |
670 | g_assert_true(viewDataManager != webkit_web_context_get_website_data_manager(webkit_web_view_get_context(test->m_webView))); |
671 | auto* cookieManager = webkit_website_data_manager_get_cookie_manager(viewDataManager); |
672 | g_assert_true(WEBKIT_IS_COOKIE_MANAGER(cookieManager)); |
673 | test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(cookieManager)); |
674 | g_assert_true(cookieManager != test->m_cookieManager); |
675 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS; |
676 | webkit_cookie_manager_get_domains_with_cookies(cookieManager, nullptr, [](GObject* object, GAsyncResult* result, gpointer userData) { |
677 | auto* test = static_cast<CookieManagerTest*>(userData); |
678 | GUniquePtr<char*> domains(webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, nullptr)); |
679 | g_assert_nonnull(domains); |
680 | g_assert_cmpint(g_strv_length(domains.get()), ==, 1); |
681 | g_assert_cmpstr(domains.get()[0], ==, kFirstPartyDomain); |
682 | test->quitMainLoop(); |
683 | }, test); |
684 | G_GNUC_END_IGNORE_DEPRECATIONS; |
685 | g_main_loop_run(test->m_mainLoop); |
686 | } |
687 | |
688 | static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) |
689 | { |
690 | if (message->method != SOUP_METHOD_GET) { |
691 | soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); |
692 | return; |
693 | } |
694 | |
695 | soup_message_set_status(message, SOUP_STATUS_OK); |
696 | gchar* = g_strdup_printf("%s=%s; Max-Age=60" , kCookieName, kCookieValue); |
697 | |
698 | if (g_str_equal(path, "/index.html" )) { |
699 | char* indexHtml = g_strdup_printf(kIndexHtmlFormat, soup_server_get_port(server)); |
700 | soup_message_headers_replace(message->response_headers, "Set-Cookie" , header_str); |
701 | soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, indexHtml, strlen(indexHtml)); |
702 | } else if (g_str_equal(path, "/image.png" )) |
703 | soup_message_headers_replace(message->response_headers, "Set-Cookie" , header_str); |
704 | else if (g_str_equal(path, "/no-cookies.html" )) { |
705 | static const char* indexHtml = "<html><body><p>No cookies</p></body></html>" ; |
706 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHtml, strlen(indexHtml)); |
707 | } else |
708 | soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); |
709 | soup_message_body_complete(message->response_body); |
710 | } |
711 | |
712 | void beforeAll() |
713 | { |
714 | kServer = new WebKitTestServer(); |
715 | kServer->run(serverCallback); |
716 | |
717 | CookieManagerTest::add("WebKitCookieManager" , "accept-policy" , testCookieManagerAcceptPolicy); |
718 | CookieManagerTest::add("WebKitCookieManager" , "add-cookie" , testCookieManagerAddCookie); |
719 | CookieManagerTest::add("WebKitCookieManager" , "get-cookies" , testCookieManagerGetCookies); |
720 | CookieManagerTest::add("WebKitCookieManager" , "delete-cookie" , testCookieManagerDeleteCookie); |
721 | CookieManagerTest::add("WebKitCookieManager" , "delete-cookies" , testCookieManagerDeleteCookies); |
722 | CookieManagerTest::add("WebKitCookieManager" , "cookies-changed" , testCookieManagerCookiesChanged); |
723 | CookiePersistentStorageTest::add("WebKitCookieManager" , "persistent-storage" , testCookieManagerPersistentStorage); |
724 | CookieManagerTest::add("WebKitCookieManager" , "persistent-storage-delete-all" , testCookieManagerPersistentStorageDeleteAll); |
725 | CookieManagerTest::add("WebKitCookieManager" , "ephemeral" , testCookieManagerEphemeral); |
726 | } |
727 | |
728 | void afterAll() |
729 | { |
730 | delete kServer; |
731 | } |
732 | |