1/* 2 * Copyright (C) 2012 Igalia S.L. 3 * Copyright (C) 2012 Intel Corporation 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 "UnitTestUtils/EWK2UnitTestBase.h" 24#include "UnitTestUtils/EWK2UnitTestServer.h" 25#include <stdio.h> 26#include <stdlib.h> 27#include <unistd.h> 28 29using namespace EWK2UnitTest; 30using namespace WTF; 31 32extern EWK2UnitTestEnvironment* environment; 33 34static const char FIRST_PARTY_DOMAIN[] = "127.0.0.1"; 35static const char THIRD_PARTY_DOMAIN[] = "localhost"; 36static const char INDEX_HTML_STRING[] = 37 "<html><body>" 38 " <p>EFLWebKit2 Cookie Manager test</p>" 39 " <img src='http://localhost:%u/image.png' width=5 height=5></img>" 40 "</body></html>"; 41 42class EWK2CookieManagerTest : public EWK2UnitTestBase { 43public: 44 static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) 45 { 46 if (message->method != SOUP_METHOD_GET) { 47 soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); 48 return; 49 } 50 51 soup_message_set_status(message, SOUP_STATUS_OK); 52 if (!strcmp(path, "/index.html")) { 53 Eina_Strbuf* buffer = eina_strbuf_new(); 54 eina_strbuf_append_printf(buffer, INDEX_HTML_STRING, soup_server_get_port(server)); 55 soup_message_headers_replace(message->response_headers, "Set-Cookie", "foo=bar; Max-Age=60"); 56 soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, eina_strbuf_string_steal(buffer), eina_strbuf_length_get(buffer)); 57 eina_strbuf_free(buffer); 58 } else if (!strcmp(path, "/image.png")) 59 soup_message_headers_replace(message->response_headers, "Set-Cookie", "baz=qux; Max-Age=60"); 60 else 61 soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); 62 63 soup_message_body_complete(message->response_body); 64 } 65 66 static void getAcceptPolicyCallback(Ewk_Cookie_Accept_Policy policy, void* event_info) 67 { 68 Ewk_Cookie_Accept_Policy* ret = static_cast<Ewk_Cookie_Accept_Policy*>(event_info); 69 *ret = policy; 70 ecore_main_loop_quit(); 71 } 72 73 static void getHostnamesWithCookiesCallback(Eina_List* hostnames, void* event_info) 74 { 75 Eina_List** ret = static_cast<Eina_List**>(event_info); 76 Eina_List* l; 77 void* data; 78 EINA_LIST_FOREACH(hostnames, l, data) 79 *ret = eina_list_append(*ret, eina_stringshare_ref(static_cast<char*>(data))); 80 ecore_main_loop_quit(); 81 } 82 83 static int compareHostNames(const void* hostName1, const void* hostName2) 84 { 85 return strcmp(static_cast<const char*>(hostName1), static_cast<const char*>(hostName2)); 86 } 87 88 static void onCookiesChanged(void *eventInfo) 89 { 90 bool* cookiesChanged = static_cast<bool*>(eventInfo); 91 *cookiesChanged = true; 92 } 93 94protected: 95 Ewk_Cookie_Accept_Policy getAcceptPolicy(Ewk_Cookie_Manager* manager) 96 { 97 Ewk_Cookie_Accept_Policy policy = EWK_COOKIE_ACCEPT_POLICY_ALWAYS; 98 ewk_cookie_manager_accept_policy_async_get(manager, getAcceptPolicyCallback, &policy); 99 ecore_main_loop_begin(); 100 return policy; 101 } 102 103 Eina_List* getHostnamesWithCookies(Ewk_Cookie_Manager* manager) 104 { 105 Eina_List* ret = 0; 106 ewk_cookie_manager_hostnames_with_cookies_async_get(manager, getHostnamesWithCookiesCallback, &ret); 107 ecore_main_loop_begin(); 108 return ret; 109 } 110 111 void freeHostNames(Eina_List* hostnames) 112 { 113 void* data; 114 EINA_LIST_FREE(hostnames, data) 115 eina_stringshare_del(static_cast<char*>(data)); 116 } 117 118 int countHostnamesWithCookies(Ewk_Cookie_Manager* manager) 119 { 120 Eina_List* hostnames = getHostnamesWithCookies(manager); 121 int count = eina_list_count(hostnames); 122 freeHostNames(hostnames); 123 return count; 124 } 125}; 126 127TEST_F(EWK2CookieManagerTest, ewk_cookie_manager_accept_policy) 128{ 129 std::unique_ptr<EWK2UnitTestServer> httpServer = std::make_unique<EWK2UnitTestServer>(); 130 httpServer->run(serverCallback); 131 132 Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_view_context_get(webView())); 133 ASSERT_TRUE(cookieManager); 134 135 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 136 137 // Default policy is EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY. 138 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY, getAcceptPolicy(cookieManager)); 139 140 Eina_List* hostnames = getHostnamesWithCookies(cookieManager); 141 ASSERT_EQ(1, eina_list_count(hostnames)); 142 ASSERT_STREQ(FIRST_PARTY_DOMAIN, static_cast<char*>(eina_list_nth(hostnames, 0))); 143 freeHostNames(hostnames); 144 ewk_cookie_manager_cookies_clear(cookieManager); 145 146 // Change policy to EWK_COOKIE_ACCEPT_POLICY_ALWAYS 147 ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_ALWAYS); 148 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_ALWAYS, getAcceptPolicy(cookieManager)); 149 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 150 151 hostnames = getHostnamesWithCookies(cookieManager); 152 ASSERT_EQ(2, eina_list_count(hostnames)); 153 hostnames = eina_list_sort(hostnames, eina_list_count(hostnames), compareHostNames); 154 ASSERT_STREQ(FIRST_PARTY_DOMAIN, static_cast<char*>(eina_list_nth(hostnames, 0))); 155 ASSERT_STREQ(THIRD_PARTY_DOMAIN, static_cast<char*>(eina_list_nth(hostnames, 1))); 156 freeHostNames(hostnames); 157 ewk_cookie_manager_cookies_clear(cookieManager); 158 159 // Change policy to EWK_COOKIE_ACCEPT_POLICY_NEVER 160 ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_NEVER); 161 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_NEVER, getAcceptPolicy(cookieManager)); 162 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 163 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 164} 165 166TEST_F(EWK2CookieManagerTest, ewk_cookie_manager_changes_watch) 167{ 168 std::unique_ptr<EWK2UnitTestServer> httpServer = std::make_unique<EWK2UnitTestServer>(); 169 httpServer->run(serverCallback); 170 171 Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_view_context_get(webView())); 172 ASSERT_TRUE(cookieManager); 173 174 // Load default test page to guarantee that WebProcess or NetworkProcess is launched. 175 ASSERT_TRUE(loadUrlSync(environment->defaultTestPageUrl())); 176 177 ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_ALWAYS); 178 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_ALWAYS, getAcceptPolicy(cookieManager)); 179 180 // Watch for changes 181 bool cookiesChanged = false; 182 ewk_cookie_manager_changes_watch(cookieManager, onCookiesChanged, &cookiesChanged); 183 184 // Check for cookie changes notifications 185 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 186 187 ASSERT_TRUE(waitUntilTrue(cookiesChanged)); 188 189 cookiesChanged = false; 190 ewk_cookie_manager_cookies_clear(cookieManager); 191 ASSERT_TRUE(waitUntilTrue(cookiesChanged)); 192 193 // Stop watching for notifications 194 ewk_cookie_manager_changes_watch(cookieManager, 0, 0); 195 cookiesChanged = false; 196 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 197 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 198 ASSERT_FALSE(cookiesChanged); 199 200 // Watch again for notifications 201 ewk_cookie_manager_changes_watch(cookieManager, onCookiesChanged, &cookiesChanged); 202 203 // Make sure we don't get notifications when loading setting an existing persistent storage 204 char storageDirectory[] = "/tmp/ewk2_cookie_manager-XXXXXX"; 205 ASSERT_TRUE(mkdtemp(storageDirectory)); 206 char textStorage1[64]; 207 snprintf(textStorage1, sizeof(textStorage1), "%s/txt-cookie1", storageDirectory); 208 char textStorage2[64]; 209 snprintf(textStorage2, sizeof(textStorage2), "%s/txt-cookie2", storageDirectory); 210 211 ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage1, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 212 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 213 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 214 215 cookiesChanged = false; 216 ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage2, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 217 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 218 219 ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage1, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 220 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 221 222 ASSERT_FALSE(cookiesChanged); 223 224 // Final clean up. 225 ewk_cookie_manager_changes_watch(cookieManager, 0, 0); 226 unlink(textStorage1); 227 unlink(textStorage2); 228 rmdir(storageDirectory); 229} 230 231TEST_F(EWK2CookieManagerTest, ewk_cookie_manager_cookies_delete) 232{ 233 std::unique_ptr<EWK2UnitTestServer> httpServer = std::make_unique<EWK2UnitTestServer>(); 234 httpServer->run(serverCallback); 235 236 Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_view_context_get(webView())); 237 ASSERT_TRUE(cookieManager); 238 239 // Load default test page to guarantee that WebProcess or NetworkProcess is launched. 240 ASSERT_TRUE(loadUrlSync(environment->defaultTestPageUrl())); 241 242 ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_ALWAYS); 243 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_ALWAYS, getAcceptPolicy(cookieManager)); 244 245 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 246 Eina_List* hostnames = getHostnamesWithCookies(cookieManager); 247 ASSERT_EQ(2, eina_list_count(hostnames)); 248 freeHostNames(hostnames); 249 250 // Delete first party cookie 251 ewk_cookie_manager_hostname_cookies_clear(cookieManager, FIRST_PARTY_DOMAIN); 252 hostnames = getHostnamesWithCookies(cookieManager); 253 ASSERT_EQ(1, eina_list_count(hostnames)); 254 ASSERT_STREQ(THIRD_PARTY_DOMAIN, static_cast<char*>(eina_list_nth(hostnames, 0))); 255 freeHostNames(hostnames); 256 257 // Delete third party cookie 258 ewk_cookie_manager_hostname_cookies_clear(cookieManager, THIRD_PARTY_DOMAIN); 259 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 260 261 // Get all cookies again 262 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 263 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 264 265 // Clear all cookies 266 ewk_cookie_manager_cookies_clear(cookieManager); 267 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 268} 269 270TEST_F(EWK2CookieManagerTest, DISABLED_ewk_cookie_manager_permanent_storage) 271{ 272 std::unique_ptr<EWK2UnitTestServer> httpServer = std::make_unique<EWK2UnitTestServer>(); 273 httpServer->run(serverCallback); 274 275 // Generate unique names for cookie storages. 276 char storageDirectory[] = "/tmp/ewk2_cookie_manager-XXXXXX"; 277 ASSERT_TRUE(mkdtemp(storageDirectory)); 278 char textStorage[64]; 279 snprintf(textStorage, sizeof(textStorage), "%s/txt-cookie", storageDirectory); 280 char sqliteStorage[64]; 281 snprintf(sqliteStorage, sizeof(sqliteStorage), "%s/sqlite-cookie", storageDirectory); 282 283 Ewk_Cookie_Manager* cookieManager = ewk_context_cookie_manager_get(ewk_view_context_get(webView())); 284 ASSERT_TRUE(cookieManager); 285 286 // Load default test page to guarantee that WebProcess or NetworkProcess is launched. 287 ASSERT_TRUE(loadUrlSync(environment->defaultTestPageUrl())); 288 289 ewk_cookie_manager_accept_policy_set(cookieManager, EWK_COOKIE_ACCEPT_POLICY_ALWAYS); 290 ASSERT_EQ(EWK_COOKIE_ACCEPT_POLICY_ALWAYS, getAcceptPolicy(cookieManager)); 291 292 // Text storage using a new file. 293 ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 294 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 295 296 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 297 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 298 299 // SQLite storage using a new file. 300 ewk_cookie_manager_persistent_storage_set(cookieManager, sqliteStorage, EWK_COOKIE_PERSISTENT_STORAGE_SQLITE); 301 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 302 303 ASSERT_TRUE(loadUrlSync(httpServer->getURLForPath("/index.html").data())); 304 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 305 306 // Text storage using an existing file. 307 ewk_cookie_manager_persistent_storage_set(cookieManager, textStorage, EWK_COOKIE_PERSISTENT_STORAGE_TEXT); 308 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 309 ewk_cookie_manager_cookies_clear(cookieManager); 310 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 311 312 // SQLite storage with an existing file. 313 ewk_cookie_manager_persistent_storage_set(cookieManager, sqliteStorage, EWK_COOKIE_PERSISTENT_STORAGE_SQLITE); 314 ASSERT_EQ(2, countHostnamesWithCookies(cookieManager)); 315 ewk_cookie_manager_cookies_clear(cookieManager); 316 ASSERT_EQ(0, countHostnamesWithCookies(cookieManager)); 317 318 // Final clean up. 319 unlink(textStorage); 320 unlink(sqliteStorage); 321 rmdir(storageDirectory); 322} 323