| 1 | /* |
| 2 | * Copyright (C) 2017 Igalia S.L. |
| 3 | * |
| 4 | * This library is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Lesser General Public |
| 6 | * License as published by the Free Software Foundation; either |
| 7 | * version 2,1 of the License, or (at your option) any later version. |
| 8 | * |
| 9 | * This library is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | * Library General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Library General Public License |
| 15 | * along with this library; see the file COPYING.LIB. If not, write to |
| 16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 17 | * Boston, MA 02110-1301, USA. |
| 18 | */ |
| 19 | |
| 20 | #include "config.h" |
| 21 | |
| 22 | #include "WebKitTestServer.h" |
| 23 | #include "WebViewTest.h" |
| 24 | #include <glib/gstdio.h> |
| 25 | |
| 26 | static WebKitTestServer* kServer; |
| 27 | |
| 28 | static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) |
| 29 | { |
| 30 | if (message->method != SOUP_METHOD_GET) { |
| 31 | soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); |
| 32 | return; |
| 33 | } |
| 34 | |
| 35 | if (g_str_equal(path, "/empty" )) { |
| 36 | static const char* emptyHTML = "<html><body></body></html>" ; |
| 37 | soup_message_headers_replace(message->response_headers, "Set-Cookie" , "foo=bar; Max-Age=60" ); |
| 38 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, emptyHTML, strlen(emptyHTML)); |
| 39 | soup_message_body_complete(message->response_body); |
| 40 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 41 | } else if (g_str_equal(path, "/appcache" )) { |
| 42 | static const char* appcacheHTML = "<html manifest=appcache.manifest><body></body></html>" ; |
| 43 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheHTML, strlen(appcacheHTML)); |
| 44 | soup_message_body_complete(message->response_body); |
| 45 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 46 | } else if (g_str_equal(path, "/appcache.manifest" )) { |
| 47 | static const char* appcacheManifest = "CACHE MANIFEST\nCACHE:\nappcache/foo.txt\n" ; |
| 48 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheManifest, strlen(appcacheManifest)); |
| 49 | soup_message_body_complete(message->response_body); |
| 50 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 51 | } else if (g_str_equal(path, "/appcache/foo.txt" )) { |
| 52 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, "foo" , 3); |
| 53 | soup_message_body_complete(message->response_body); |
| 54 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 55 | } else if (g_str_equal(path, "/sessionstorage" )) { |
| 56 | static const char* sessionStorageHTML = "<html><body onload=\"sessionStorage.foo = 'bar';\"></body></html>" ; |
| 57 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, sessionStorageHTML, strlen(sessionStorageHTML)); |
| 58 | soup_message_body_complete(message->response_body); |
| 59 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 60 | } else if (g_str_equal(path, "/localstorage" )) { |
| 61 | static const char* localStorageHTML = "<html><body onload=\"localStorage.foo = 'bar';\"></body></html>" ; |
| 62 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, localStorageHTML, strlen(localStorageHTML)); |
| 63 | soup_message_body_complete(message->response_body); |
| 64 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 65 | } else if (g_str_equal(path, "/enumeratedevices" )) { |
| 66 | static const char* enumerateDevicesHTML = "<html><body onload=\"navigator.mediaDevices.enumerateDevices().then(function(devices) { document.title = 'Finished'; })\"></body></html>" ; |
| 67 | soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, enumerateDevicesHTML, strlen(enumerateDevicesHTML)); |
| 68 | soup_message_body_complete(message->response_body); |
| 69 | soup_message_set_status(message, SOUP_STATUS_OK); |
| 70 | } else |
| 71 | soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); |
| 72 | } |
| 73 | |
| 74 | class WebsiteDataTest : public WebViewTest { |
| 75 | public: |
| 76 | MAKE_GLIB_TEST_FIXTURE(WebsiteDataTest); |
| 77 | |
| 78 | |
| 79 | WebsiteDataTest() |
| 80 | : m_manager(webkit_web_context_get_website_data_manager(webkit_web_view_get_context(m_webView))) |
| 81 | { |
| 82 | g_assert_true(WEBKIT_IS_WEBSITE_DATA_MANAGER(m_manager)); |
| 83 | assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_manager)); |
| 84 | // WebsiteDataStore creates a new WebProcessPool when used before any secondary process has been created. |
| 85 | // Ensure we have a web process by always loading about:blank here. |
| 86 | loadURI("about:blank" ); |
| 87 | waitUntilLoadFinished(); |
| 88 | } |
| 89 | |
| 90 | ~WebsiteDataTest() |
| 91 | { |
| 92 | g_list_free_full(m_dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref)); |
| 93 | } |
| 94 | |
| 95 | GList* fetch(WebKitWebsiteDataTypes types) |
| 96 | { |
| 97 | if (m_dataList) { |
| 98 | g_list_free_full(m_dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref)); |
| 99 | m_dataList = nullptr; |
| 100 | } |
| 101 | webkit_website_data_manager_fetch(m_manager, types, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) { |
| 102 | WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData); |
| 103 | test->m_dataList = webkit_website_data_manager_fetch_finish(test->m_manager, result, nullptr); |
| 104 | test->quitMainLoop(); |
| 105 | }, this); |
| 106 | g_main_loop_run(m_mainLoop); |
| 107 | return m_dataList; |
| 108 | } |
| 109 | |
| 110 | void remove(WebKitWebsiteDataTypes types, GList* dataList) |
| 111 | { |
| 112 | webkit_website_data_manager_remove(m_manager, types, dataList, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) { |
| 113 | WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData); |
| 114 | g_assert_true(webkit_website_data_manager_remove_finish(test->m_manager, result, nullptr)); |
| 115 | test->quitMainLoop(); |
| 116 | }, this); |
| 117 | g_main_loop_run(m_mainLoop); |
| 118 | } |
| 119 | |
| 120 | void clear(WebKitWebsiteDataTypes types, GTimeSpan timeSpan) |
| 121 | { |
| 122 | webkit_website_data_manager_clear(m_manager, types, timeSpan, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) { |
| 123 | WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData); |
| 124 | g_assert_true(webkit_website_data_manager_clear_finish(test->m_manager, result, nullptr)); |
| 125 | test->quitMainLoop(); |
| 126 | }, this); |
| 127 | g_main_loop_run(m_mainLoop); |
| 128 | } |
| 129 | |
| 130 | WebKitWebsiteDataManager* m_manager; |
| 131 | GList* m_dataList { nullptr }; |
| 132 | }; |
| 133 | |
| 134 | static void testWebsiteDataConfiguration(WebsiteDataTest* test, gconstpointer) |
| 135 | { |
| 136 | // Base directories are not used by TestMain. |
| 137 | g_assert_null(webkit_website_data_manager_get_base_data_directory(test->m_manager)); |
| 138 | g_assert_null(webkit_website_data_manager_get_base_cache_directory(test->m_manager)); |
| 139 | |
| 140 | GUniquePtr<char> localStorageDirectory(g_build_filename(Test::dataDirectory(), "local-storage" , nullptr)); |
| 141 | g_assert_cmpstr(localStorageDirectory.get(), ==, webkit_website_data_manager_get_local_storage_directory(test->m_manager)); |
| 142 | g_assert_true(g_file_test(localStorageDirectory.get(), G_FILE_TEST_IS_DIR)); |
| 143 | |
| 144 | test->loadURI(kServer->getURIForPath("/empty" ).data()); |
| 145 | test->waitUntilLoadFinished(); |
| 146 | test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');" , nullptr); |
| 147 | GUniquePtr<char> indexedDBDirectory(g_build_filename(Test::dataDirectory(), "indexeddb" , nullptr)); |
| 148 | g_assert_cmpstr(indexedDBDirectory.get(), ==, webkit_website_data_manager_get_indexeddb_directory(test->m_manager)); |
| 149 | g_assert_true(g_file_test(indexedDBDirectory.get(), G_FILE_TEST_IS_DIR)); |
| 150 | |
| 151 | GUniquePtr<char> webSQLDirectory(g_build_filename(Test::dataDirectory(), "websql" , nullptr)); |
| 152 | g_assert_cmpstr(webSQLDirectory.get(), ==, webkit_website_data_manager_get_websql_directory(test->m_manager)); |
| 153 | test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);" , nullptr); |
| 154 | g_assert_true(g_file_test(webSQLDirectory.get(), G_FILE_TEST_IS_DIR)); |
| 155 | |
| 156 | test->loadURI(kServer->getURIForPath("/appcache" ).data()); |
| 157 | test->waitUntilLoadFinished(); |
| 158 | GUniquePtr<char> applicationCacheDirectory(g_build_filename(Test::dataDirectory(), "appcache" , nullptr)); |
| 159 | g_assert_cmpstr(applicationCacheDirectory.get(), ==, webkit_website_data_manager_get_offline_application_cache_directory(test->m_manager)); |
| 160 | GUniquePtr<char> applicationCacheDatabase(g_build_filename(applicationCacheDirectory.get(), "ApplicationCache.db" , nullptr)); |
| 161 | unsigned triesCount = 4; |
| 162 | while (!g_file_test(applicationCacheDatabase.get(), G_FILE_TEST_IS_REGULAR) && --triesCount) |
| 163 | test->wait(0.25); |
| 164 | g_assert_cmpuint(triesCount, >, 0); |
| 165 | |
| 166 | GUniquePtr<char> diskCacheDirectory(g_build_filename(Test::dataDirectory(), "disk-cache" , nullptr)); |
| 167 | g_assert_cmpstr(diskCacheDirectory.get(), ==, webkit_website_data_manager_get_disk_cache_directory(test->m_manager)); |
| 168 | g_assert_true(g_file_test(diskCacheDirectory.get(), G_FILE_TEST_IS_DIR)); |
| 169 | |
| 170 | // Clear all persistent caches, since the data dir is common to all test cases. |
| 171 | static const WebKitWebsiteDataTypes persistentCaches = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_DISK_CACHE | WEBKIT_WEBSITE_DATA_LOCAL_STORAGE |
| 172 | | WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES | WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES | WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE | WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 173 | test->clear(persistentCaches, 0); |
| 174 | g_assert_null(test->fetch(persistentCaches)); |
| 175 | |
| 176 | // The default context should have a different manager with different configuration. |
| 177 | WebKitWebsiteDataManager* defaultManager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default()); |
| 178 | g_assert_true(WEBKIT_IS_WEBSITE_DATA_MANAGER(defaultManager)); |
| 179 | g_assert_true(test->m_manager != defaultManager); |
| 180 | g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(test->m_manager), !=, webkit_website_data_manager_get_local_storage_directory(defaultManager)); |
| 181 | g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(test->m_manager), !=, webkit_website_data_manager_get_indexeddb_directory(defaultManager)); |
| 182 | g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(test->m_manager), !=, webkit_website_data_manager_get_disk_cache_directory(defaultManager)); |
| 183 | g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(test->m_manager), !=, webkit_website_data_manager_get_offline_application_cache_directory(defaultManager)); |
| 184 | g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(test->m_manager), !=, webkit_website_data_manager_get_websql_directory(defaultManager)); |
| 185 | |
| 186 | // Using Test::dataDirectory() we get the default configuration but for a differrent prefix. |
| 187 | GRefPtr<WebKitWebsiteDataManager> baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory" , Test::dataDirectory(), "base-cache-directory" , Test::dataDirectory(), nullptr)); |
| 188 | g_assert_true(WEBKIT_IS_WEBSITE_DATA_MANAGER(baseDataManager.get())); |
| 189 | |
| 190 | localStorageDirectory.reset(g_build_filename(Test::dataDirectory(), "localstorage" , nullptr)); |
| 191 | g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get()); |
| 192 | |
| 193 | indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "databases" , "indexeddb" , nullptr)); |
| 194 | g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get()); |
| 195 | |
| 196 | applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "applications" , nullptr)); |
| 197 | g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get()); |
| 198 | |
| 199 | webSQLDirectory.reset(g_build_filename(Test::dataDirectory(), "databases" , nullptr)); |
| 200 | g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get()); |
| 201 | |
| 202 | g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory()); |
| 203 | |
| 204 | // Any specific configuration provided takes precedence over base dirs. |
| 205 | indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomindexeddb" , nullptr)); |
| 206 | applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomappcache" , nullptr)); |
| 207 | baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory" , Test::dataDirectory(), "base-cache-directory" , Test::dataDirectory(), |
| 208 | "indexeddb-directory" , indexedDBDirectory.get(), "offline-application-cache-directory" , applicationCacheDirectory.get(), nullptr)); |
| 209 | g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get()); |
| 210 | g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get()); |
| 211 | // The result should be the same as previous manager. |
| 212 | g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get()); |
| 213 | g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get()); |
| 214 | g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory()); |
| 215 | } |
| 216 | |
| 217 | static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test) |
| 218 | { |
| 219 | if (loadEvent != WEBKIT_LOAD_FINISHED) |
| 220 | return; |
| 221 | g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test); |
| 222 | test->quitMainLoop(); |
| 223 | } |
| 224 | |
| 225 | static void testWebsiteDataEphemeral(WebViewTest* test, gconstpointer) |
| 226 | { |
| 227 | GRefPtr<WebKitWebsiteDataManager> manager = adoptGRef(webkit_website_data_manager_new_ephemeral()); |
| 228 | g_assert_true(webkit_website_data_manager_is_ephemeral(manager.get())); |
| 229 | g_assert_null(webkit_website_data_manager_get_base_data_directory(manager.get())); |
| 230 | g_assert_null(webkit_website_data_manager_get_base_cache_directory(manager.get())); |
| 231 | g_assert_null(webkit_website_data_manager_get_local_storage_directory(manager.get())); |
| 232 | g_assert_null(webkit_website_data_manager_get_disk_cache_directory(manager.get())); |
| 233 | g_assert_null(webkit_website_data_manager_get_offline_application_cache_directory(manager.get())); |
| 234 | g_assert_null(webkit_website_data_manager_get_indexeddb_directory(manager.get())); |
| 235 | g_assert_null(webkit_website_data_manager_get_websql_directory(manager.get())); |
| 236 | |
| 237 | // Configuration is ignored when is-ephemeral is used. |
| 238 | manager = adoptGRef(WEBKIT_WEBSITE_DATA_MANAGER(g_object_new(WEBKIT_TYPE_WEBSITE_DATA_MANAGER, "base-data-directory" , Test::dataDirectory(), "is-ephemeral" , TRUE, nullptr))); |
| 239 | g_assert_true(webkit_website_data_manager_is_ephemeral(manager.get())); |
| 240 | g_assert_null(webkit_website_data_manager_get_base_data_directory(manager.get())); |
| 241 | |
| 242 | // Non persistent data can be queried in an ephemeral manager. |
| 243 | GRefPtr<WebKitWebContext> webContext = adoptGRef(webkit_web_context_new_with_website_data_manager(manager.get())); |
| 244 | g_assert_true(webkit_web_context_is_ephemeral(webContext.get())); |
| 245 | auto webView = Test::adoptView(Test::createWebView(webContext.get())); |
| 246 | g_assert_true(webkit_web_view_is_ephemeral(webView.get())); |
| 247 | g_assert_true(webkit_web_view_get_website_data_manager(webView.get()) == manager.get()); |
| 248 | |
| 249 | g_signal_connect(webView.get(), "load-changed" , G_CALLBACK(ephemeralViewloadChanged), test); |
| 250 | webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/empty" ).data()); |
| 251 | g_main_loop_run(test->m_mainLoop); |
| 252 | |
| 253 | webkit_website_data_manager_fetch(manager.get(), WEBKIT_WEBSITE_DATA_MEMORY_CACHE, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) { |
| 254 | auto* test = static_cast<WebViewTest*>(userData); |
| 255 | GList* dataList = webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr); |
| 256 | g_assert_nonnull(dataList); |
| 257 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 258 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 259 | g_assert_nonnull(data); |
| 260 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 261 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 262 | webkit_security_origin_unref(origin); |
| 263 | g_list_free_full(dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref)); |
| 264 | test->quitMainLoop(); |
| 265 | }, test); |
| 266 | g_main_loop_run(test->m_mainLoop); |
| 267 | } |
| 268 | |
| 269 | static void testWebsiteDataCache(WebsiteDataTest* test, gconstpointer) |
| 270 | { |
| 271 | static const WebKitWebsiteDataTypes cacheTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 272 | GList* dataList = test->fetch(cacheTypes); |
| 273 | g_assert_null(dataList); |
| 274 | |
| 275 | test->loadURI(kServer->getURIForPath("/empty" ).data()); |
| 276 | test->waitUntilLoadFinished(); |
| 277 | |
| 278 | // Disk cache delays the storing of initial resources for 1 second to avoid |
| 279 | // affecting early page load. So, wait 1 second here to make sure resources |
| 280 | // have already been stored. |
| 281 | test->wait(1); |
| 282 | |
| 283 | dataList = test->fetch(cacheTypes); |
| 284 | g_assert_nonnull(dataList); |
| 285 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 286 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 287 | g_assert_nonnull(data); |
| 288 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 289 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 290 | webkit_security_origin_unref(origin); |
| 291 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, cacheTypes); |
| 292 | // Memory cache size is unknown. |
| 293 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_MEMORY_CACHE), ==, 0); |
| 294 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_DISK_CACHE), >, 0); |
| 295 | |
| 296 | // Try again but only getting disk cache. |
| 297 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 298 | g_assert_nonnull(dataList); |
| 299 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 300 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 301 | g_assert_nonnull(data); |
| 302 | g_assert_true(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 303 | g_assert_false(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_MEMORY_CACHE); |
| 304 | |
| 305 | GUniquePtr<char> fileURL(g_strdup_printf("file://%s/simple.html" , Test::getResourcesDir(Test::WebKit2Resources).data())); |
| 306 | test->loadURI(fileURL.get()); |
| 307 | test->waitUntilLoadFinished(); |
| 308 | |
| 309 | fileURL.reset(g_strdup_printf("file://%s/simple2.html" , Test::getResourcesDir(Test::WebKit2Resources).data())); |
| 310 | test->loadURI(fileURL.get()); |
| 311 | test->waitUntilLoadFinished(); |
| 312 | |
| 313 | // Local files are grouped. |
| 314 | dataList = test->fetch(cacheTypes); |
| 315 | g_assert_nonnull(dataList); |
| 316 | g_assert_cmpuint(g_list_length(dataList), ==, 2); |
| 317 | GList* itemList = g_list_find_custom(dataList, nullptr, [](gconstpointer item, gconstpointer) -> int { |
| 318 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(const_cast<gpointer>(item)); |
| 319 | return g_strcmp0(webkit_website_data_get_name(data), "Local files" ); |
| 320 | }); |
| 321 | g_assert_nonnull(itemList); |
| 322 | data = static_cast<WebKitWebsiteData*>(itemList->data); |
| 323 | g_assert_nonnull(data); |
| 324 | g_assert_true(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_MEMORY_CACHE); |
| 325 | // Local files are never stored in disk cache. |
| 326 | g_assert_false(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 327 | |
| 328 | // Clear data modified since the last microsecond should not clear anything. |
| 329 | // Use disk-cache because memory cache ignores the modified since. |
| 330 | test->clear(WEBKIT_WEBSITE_DATA_DISK_CACHE, 1); |
| 331 | dataList = test->fetch(cacheTypes); |
| 332 | g_assert_nonnull(dataList); |
| 333 | g_assert_cmpuint(g_list_length(dataList), ==, 2); |
| 334 | |
| 335 | // Remove memory cache only for local files. |
| 336 | itemList = g_list_find_custom(dataList, nullptr, [](gconstpointer item, gconstpointer) -> int { |
| 337 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(const_cast<gpointer>(item)); |
| 338 | return g_strcmp0(webkit_website_data_get_name(data), "Local files" ); |
| 339 | }); |
| 340 | g_assert_nonnull(itemList); |
| 341 | GList removeList = { itemList->data, nullptr, nullptr }; |
| 342 | test->remove(WEBKIT_WEBSITE_DATA_MEMORY_CACHE, &removeList); |
| 343 | dataList = test->fetch(cacheTypes); |
| 344 | g_assert_nonnull(dataList); |
| 345 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 346 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 347 | g_assert_true(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 348 | |
| 349 | // Clear all. |
| 350 | test->clear(cacheTypes, 0); |
| 351 | dataList = test->fetch(cacheTypes); |
| 352 | g_assert_null(dataList); |
| 353 | } |
| 354 | |
| 355 | static void testWebsiteDataStorage(WebsiteDataTest* test, gconstpointer) |
| 356 | { |
| 357 | static const WebKitWebsiteDataTypes storageTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_SESSION_STORAGE | WEBKIT_WEBSITE_DATA_LOCAL_STORAGE); |
| 358 | GList* dataList = test->fetch(storageTypes); |
| 359 | g_assert_null(dataList); |
| 360 | |
| 361 | test->loadURI(kServer->getURIForPath("/sessionstorage" ).data()); |
| 362 | test->waitUntilLoadFinished(); |
| 363 | |
| 364 | test->loadURI(kServer->getURIForPath("/localstorage" ).data()); |
| 365 | test->waitUntilLoadFinished(); |
| 366 | |
| 367 | // Local storage uses a 1 second timer to update the database. |
| 368 | test->wait(1); |
| 369 | |
| 370 | dataList = test->fetch(storageTypes); |
| 371 | g_assert_nonnull(dataList); |
| 372 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 373 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 374 | g_assert_nonnull(data); |
| 375 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 376 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 377 | webkit_security_origin_unref(origin); |
| 378 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, storageTypes); |
| 379 | // Storage sizes are unknown. |
| 380 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_SESSION_STORAGE), ==, 0); |
| 381 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_LOCAL_STORAGE), ==, 0); |
| 382 | |
| 383 | // Get also cached data, and clear it. |
| 384 | static const WebKitWebsiteDataTypes cacheAndStorageTypes = static_cast<WebKitWebsiteDataTypes>(storageTypes | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 385 | dataList = test->fetch(cacheAndStorageTypes); |
| 386 | g_assert_nonnull(dataList); |
| 387 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 388 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 389 | g_assert_nonnull(data); |
| 390 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, cacheAndStorageTypes); |
| 391 | test->clear(static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE), 0); |
| 392 | |
| 393 | // Get all types again, but only storage is retrieved now. |
| 394 | dataList = test->fetch(cacheAndStorageTypes); |
| 395 | g_assert_nonnull(dataList); |
| 396 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 397 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 398 | g_assert_nonnull(data); |
| 399 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, storageTypes); |
| 400 | |
| 401 | // Remove the session storage. |
| 402 | GList removeList = { data, nullptr, nullptr }; |
| 403 | test->remove(WEBKIT_WEBSITE_DATA_SESSION_STORAGE, &removeList); |
| 404 | dataList = test->fetch(storageTypes); |
| 405 | g_assert_nonnull(dataList); |
| 406 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 407 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 408 | g_assert_false(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_SESSION_STORAGE); |
| 409 | g_assert_true(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_LOCAL_STORAGE); |
| 410 | |
| 411 | // Clear all. |
| 412 | test->clear(cacheAndStorageTypes, 0); |
| 413 | dataList = test->fetch(cacheAndStorageTypes); |
| 414 | g_assert_null(dataList); |
| 415 | } |
| 416 | |
| 417 | static void testWebsiteDataDatabases(WebsiteDataTest* test, gconstpointer) |
| 418 | { |
| 419 | static const WebKitWebsiteDataTypes databaseTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES | WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES); |
| 420 | GList* dataList = test->fetch(databaseTypes); |
| 421 | g_assert_null(dataList); |
| 422 | |
| 423 | test->loadURI(kServer->getURIForPath("/empty" ).data()); |
| 424 | test->waitUntilLoadFinished(); |
| 425 | test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');" , nullptr); |
| 426 | |
| 427 | dataList = test->fetch(databaseTypes); |
| 428 | g_assert_nonnull(dataList); |
| 429 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 430 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 431 | g_assert_nonnull(data); |
| 432 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 433 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 434 | webkit_security_origin_unref(origin); |
| 435 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES); |
| 436 | // Database sizes are unknown. |
| 437 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES), ==, 0); |
| 438 | |
| 439 | test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);" , nullptr); |
| 440 | dataList = test->fetch(databaseTypes); |
| 441 | g_assert_nonnull(dataList); |
| 442 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 443 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 444 | g_assert_nonnull(data); |
| 445 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, databaseTypes); |
| 446 | // Database sizes are unknown. |
| 447 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES), ==, 0); |
| 448 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES), ==, 0); |
| 449 | |
| 450 | // Remove all databases at once. |
| 451 | GList removeList = { data, nullptr, nullptr }; |
| 452 | test->remove(databaseTypes, &removeList); |
| 453 | dataList = test->fetch(databaseTypes); |
| 454 | g_assert_null(dataList); |
| 455 | |
| 456 | // Clear all. |
| 457 | static const WebKitWebsiteDataTypes cacheAndDatabaseTypes = static_cast<WebKitWebsiteDataTypes>(databaseTypes | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 458 | test->clear(cacheAndDatabaseTypes, 0); |
| 459 | dataList = test->fetch(cacheAndDatabaseTypes); |
| 460 | g_assert_null(dataList); |
| 461 | } |
| 462 | |
| 463 | static void testWebsiteDataAppcache(WebsiteDataTest* test, gconstpointer) |
| 464 | { |
| 465 | GList* dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE); |
| 466 | g_assert_null(dataList); |
| 467 | |
| 468 | test->loadURI(kServer->getURIForPath("/appcache" ).data()); |
| 469 | test->waitUntilLoadFinished(); |
| 470 | |
| 471 | test->wait(1); |
| 472 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE); |
| 473 | g_assert_nonnull(dataList); |
| 474 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 475 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 476 | g_assert_nonnull(data); |
| 477 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 478 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 479 | webkit_security_origin_unref(origin); |
| 480 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE); |
| 481 | // Appcache size is unknown. |
| 482 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE), ==, 0); |
| 483 | |
| 484 | GList removeList = { data, nullptr, nullptr }; |
| 485 | test->remove(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE, &removeList); |
| 486 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE); |
| 487 | g_assert_null(dataList); |
| 488 | |
| 489 | // Clear all. |
| 490 | static const WebKitWebsiteDataTypes cacheAndAppcacheTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 491 | test->clear(cacheAndAppcacheTypes, 0); |
| 492 | dataList = test->fetch(cacheAndAppcacheTypes); |
| 493 | g_assert_null(dataList); |
| 494 | } |
| 495 | |
| 496 | static void testWebsiteDataCookies(WebsiteDataTest* test, gconstpointer) |
| 497 | { |
| 498 | GList* dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES); |
| 499 | g_assert_null(dataList); |
| 500 | |
| 501 | test->loadURI(kServer->getURIForPath("/empty" ).data()); |
| 502 | test->waitUntilLoadFinished(); |
| 503 | |
| 504 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES); |
| 505 | g_assert_nonnull(dataList); |
| 506 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 507 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 508 | g_assert_nonnull(data); |
| 509 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, "127.0.0.1" ); |
| 510 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_COOKIES); |
| 511 | // Cookies size is unknown. |
| 512 | g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_COOKIES), ==, 0); |
| 513 | |
| 514 | GList removeList = { data, nullptr, nullptr }; |
| 515 | test->remove(WEBKIT_WEBSITE_DATA_COOKIES, &removeList); |
| 516 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES); |
| 517 | g_assert_null(dataList); |
| 518 | |
| 519 | // Clear all. |
| 520 | static const WebKitWebsiteDataTypes cacheAndCookieTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_COOKIES | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE); |
| 521 | test->clear(cacheAndCookieTypes, 0); |
| 522 | dataList = test->fetch(cacheAndCookieTypes); |
| 523 | g_assert_null(dataList); |
| 524 | } |
| 525 | |
| 526 | static void testWebsiteDataDeviceIdHashSalt(WebsiteDataTest* test, gconstpointer) |
| 527 | { |
| 528 | WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView); |
| 529 | gboolean enabled = webkit_settings_get_enable_media_stream(settings); |
| 530 | webkit_settings_set_enable_media_stream(settings, TRUE); |
| 531 | |
| 532 | test->clear(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT, 0); |
| 533 | |
| 534 | GList* dataList = test->fetch(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 535 | g_assert_null(dataList); |
| 536 | |
| 537 | test->loadURI(kServer->getURIForPath("/enumeratedevices" ).data()); |
| 538 | test->waitUntilTitleChangedTo("Finished" ); |
| 539 | |
| 540 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 541 | g_assert_nonnull(dataList); |
| 542 | |
| 543 | g_assert_cmpuint(g_list_length(dataList), ==, 1); |
| 544 | WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 545 | g_assert_nonnull(data); |
| 546 | WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/" ).data()); |
| 547 | g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin)); |
| 548 | webkit_security_origin_unref(origin); |
| 549 | g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 550 | |
| 551 | GList removeList = { data, nullptr, nullptr }; |
| 552 | test->remove(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT, &removeList); |
| 553 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 554 | g_assert_null(dataList); |
| 555 | |
| 556 | // Test removing the cookies. |
| 557 | test->loadURI(kServer->getURIForPath("/enumeratedevices" ).data()); |
| 558 | test->waitUntilTitleChangedTo("Finished" ); |
| 559 | |
| 560 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 561 | g_assert_nonnull(dataList); |
| 562 | data = static_cast<WebKitWebsiteData*>(dataList->data); |
| 563 | g_assert_nonnull(data); |
| 564 | |
| 565 | GList removeCookieList = { data, nullptr, nullptr }; |
| 566 | test->remove(WEBKIT_WEBSITE_DATA_COOKIES, &removeCookieList); |
| 567 | dataList = test->fetch(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 568 | g_assert_null(dataList); |
| 569 | |
| 570 | // Clear all. |
| 571 | static const WebKitWebsiteDataTypes cacheAndAppcacheTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT); |
| 572 | test->clear(cacheAndAppcacheTypes, 0); |
| 573 | dataList = test->fetch(cacheAndAppcacheTypes); |
| 574 | g_assert_null(dataList); |
| 575 | |
| 576 | webkit_settings_set_enable_media_stream(settings, enabled); |
| 577 | } |
| 578 | |
| 579 | void beforeAll() |
| 580 | { |
| 581 | kServer = new WebKitTestServer(); |
| 582 | kServer->run(serverCallback); |
| 583 | |
| 584 | WebsiteDataTest::add("WebKitWebsiteData" , "configuration" , testWebsiteDataConfiguration); |
| 585 | WebViewTest::add("WebKitWebsiteData" , "ephemeral" , testWebsiteDataEphemeral); |
| 586 | WebsiteDataTest::add("WebKitWebsiteData" , "cache" , testWebsiteDataCache); |
| 587 | WebsiteDataTest::add("WebKitWebsiteData" , "storage" , testWebsiteDataStorage); |
| 588 | WebsiteDataTest::add("WebKitWebsiteData" , "databases" , testWebsiteDataDatabases); |
| 589 | WebsiteDataTest::add("WebKitWebsiteData" , "appcache" , testWebsiteDataAppcache); |
| 590 | WebsiteDataTest::add("WebKitWebsiteData" , "cookies" , testWebsiteDataCookies); |
| 591 | WebsiteDataTest::add("WebKitWebsiteData" , "deviceidhashsalt" , testWebsiteDataDeviceIdHashSalt); |
| 592 | } |
| 593 | |
| 594 | void afterAll() |
| 595 | { |
| 596 | delete kServer; |
| 597 | } |
| 598 | |