Start of support for multiple WebsiteDataStore/SessionIDs per process
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / WebKitWebsiteDataManager.cpp
1 /*
2  * Copyright (C) 2015 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 #include "WebKitWebsiteDataManager.h"
22
23 #include "APIWebsiteDataStore.h"
24 #include "WebKitCookieManagerPrivate.h"
25 #include "WebKitWebsiteDataManagerPrivate.h"
26 #include "WebKitWebsiteDataPrivate.h"
27 #include "WebsiteDataFetchOption.h"
28 #include <WebCore/FileSystem.h>
29 #include <glib/gi18n-lib.h>
30 #include <wtf/glib/GUniquePtr.h>
31
32 using namespace WebKit;
33
34 /**
35  * SECTION: WebKitWebsiteDataManager
36  * @Short_description: Website data manager
37  * @Title: WebKitWebsiteDataManager
38  * @See_also: #WebKitWebContext, #WebKitWebsiteData
39  *
40  * WebKitWebsiteDataManager allows you to manage the data that websites
41  * can store in the client file system like databases or caches.
42  * You can use WebKitWebsiteDataManager to configure the local directories
43  * where the Website data will be stored, by creating a new manager with
44  * webkit_website_data_manager_new() passing the values you want to set.
45  * You can set all the possible configuration values or only some of them,
46  * a default value will be used automatically for the configuration options
47  * not provided. #WebKitWebsiteDataManager:base-data-directory and
48  * #WebKitWebsiteDataManager:base-cache-directory are two special properties
49  * that can be used to set a common base directory for all Website data and
50  * caches. It's possible to provide both, a base directory and a specific value,
51  * but in that case, the specific value takes precedence over the base directory.
52  * The newly created WebKitWebsiteDataManager must be passed as a construct property
53  * to a #WebKitWebContext, you can use webkit_web_context_new_with_website_data_manager()
54  * to create a new #WebKitWebContext with a WebKitWebsiteDataManager.
55  * In case you don't want to set any specific configuration, you don't need to create
56  * a WebKitWebsiteDataManager, the #WebKitWebContext will create a WebKitWebsiteDataManager
57  * with the default configuration. To get the WebKitWebsiteDataManager of a #WebKitWebContext
58  * you can use webkit_web_context_get_website_data_manager().
59  *
60  * A WebKitWebsiteDataManager can also be ephemeral and then all the directories configuration
61  * is not needed because website data will never persist. You can create an ephemeral WebKitWebsiteDataManager
62  * with webkit_website_data_manager_new_ephemeral(). Then you can pass an ephemeral WebKitWebsiteDataManager to
63  * a #WebKitWebContext to make it ephemeral or use webkit_web_context_new_ephemeral() and the WebKitWebsiteDataManager
64  * will be automatically created by the #WebKitWebContext.
65  *
66  * WebKitWebsiteDataManager can also be used to fetch websites data, remove data
67  * stored by particular websites, or clear data for all websites modified since a given
68  * period of time.
69  *
70  * Since: 2.10
71  */
72
73 using namespace WebKit;
74
75 enum {
76     PROP_0,
77
78     PROP_BASE_DATA_DIRECTORY,
79     PROP_BASE_CACHE_DIRECTORY,
80     PROP_LOCAL_STORAGE_DIRECTORY,
81     PROP_DISK_CACHE_DIRECTORY,
82     PROP_APPLICATION_CACHE_DIRECTORY,
83     PROP_INDEXEDDB_DIRECTORY,
84     PROP_WEBSQL_DIRECTORY,
85     PROP_IS_EPHEMERAL
86 };
87
88 struct _WebKitWebsiteDataManagerPrivate {
89     ~_WebKitWebsiteDataManagerPrivate()
90     {
91         ASSERT(processPools.isEmpty());
92     }
93
94     RefPtr<API::WebsiteDataStore> websiteDataStore;
95     GUniquePtr<char> baseDataDirectory;
96     GUniquePtr<char> baseCacheDirectory;
97     GUniquePtr<char> localStorageDirectory;
98     GUniquePtr<char> diskCacheDirectory;
99     GUniquePtr<char> applicationCacheDirectory;
100     GUniquePtr<char> indexedDBDirectory;
101     GUniquePtr<char> webSQLDirectory;
102
103     GRefPtr<WebKitCookieManager> cookieManager;
104     Vector<WebProcessPool*> processPools;
105 };
106
107 WEBKIT_DEFINE_TYPE(WebKitWebsiteDataManager, webkit_website_data_manager, G_TYPE_OBJECT)
108
109 static void webkitWebsiteDataManagerGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* paramSpec)
110 {
111     WebKitWebsiteDataManager* manager = WEBKIT_WEBSITE_DATA_MANAGER(object);
112
113     switch (propID) {
114     case PROP_BASE_DATA_DIRECTORY:
115         g_value_set_string(value, webkit_website_data_manager_get_base_data_directory(manager));
116         break;
117     case PROP_BASE_CACHE_DIRECTORY:
118         g_value_set_string(value, webkit_website_data_manager_get_base_cache_directory(manager));
119         break;
120     case PROP_LOCAL_STORAGE_DIRECTORY:
121         g_value_set_string(value, webkit_website_data_manager_get_local_storage_directory(manager));
122         break;
123     case PROP_DISK_CACHE_DIRECTORY:
124         g_value_set_string(value, webkit_website_data_manager_get_disk_cache_directory(manager));
125         break;
126     case PROP_APPLICATION_CACHE_DIRECTORY:
127         g_value_set_string(value, webkit_website_data_manager_get_offline_application_cache_directory(manager));
128         break;
129     case PROP_INDEXEDDB_DIRECTORY:
130         g_value_set_string(value, webkit_website_data_manager_get_indexeddb_directory(manager));
131         break;
132     case PROP_WEBSQL_DIRECTORY:
133         g_value_set_string(value, webkit_website_data_manager_get_websql_directory(manager));
134         break;
135     case PROP_IS_EPHEMERAL:
136         g_value_set_boolean(value, webkit_website_data_manager_is_ephemeral(manager));
137         break;
138     default:
139         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
140     }
141 }
142
143 static void webkitWebsiteDataManagerSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* paramSpec)
144 {
145     WebKitWebsiteDataManager* manager = WEBKIT_WEBSITE_DATA_MANAGER(object);
146
147     switch (propID) {
148     case PROP_BASE_DATA_DIRECTORY:
149         manager->priv->baseDataDirectory.reset(g_value_dup_string(value));
150         break;
151     case PROP_BASE_CACHE_DIRECTORY:
152         manager->priv->baseCacheDirectory.reset(g_value_dup_string(value));
153         break;
154     case PROP_LOCAL_STORAGE_DIRECTORY:
155         manager->priv->localStorageDirectory.reset(g_value_dup_string(value));
156         break;
157     case PROP_DISK_CACHE_DIRECTORY:
158         manager->priv->diskCacheDirectory.reset(g_value_dup_string(value));
159         break;
160     case PROP_APPLICATION_CACHE_DIRECTORY:
161         manager->priv->applicationCacheDirectory.reset(g_value_dup_string(value));
162         break;
163     case PROP_INDEXEDDB_DIRECTORY:
164         manager->priv->indexedDBDirectory.reset(g_value_dup_string(value));
165         break;
166     case PROP_WEBSQL_DIRECTORY:
167         manager->priv->webSQLDirectory.reset(g_value_dup_string(value));
168         break;
169     case PROP_IS_EPHEMERAL:
170         if (g_value_get_boolean(value))
171             manager->priv->websiteDataStore = API::WebsiteDataStore::createNonPersistentDataStore();
172         break;
173     default:
174         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
175     }
176 }
177
178 static void webkitWebsiteDataManagerConstructed(GObject* object)
179 {
180     G_OBJECT_CLASS(webkit_website_data_manager_parent_class)->constructed(object);
181
182     WebKitWebsiteDataManagerPrivate* priv = WEBKIT_WEBSITE_DATA_MANAGER(object)->priv;
183     if (priv->baseDataDirectory) {
184         if (!priv->localStorageDirectory)
185             priv->localStorageDirectory.reset(g_build_filename(priv->baseDataDirectory.get(), "localstorage", nullptr));
186         if (!priv->indexedDBDirectory)
187             priv->indexedDBDirectory.reset(g_build_filename(priv->baseDataDirectory.get(), "databases", "indexeddb", nullptr));
188         if (!priv->webSQLDirectory)
189             priv->webSQLDirectory.reset(g_build_filename(priv->baseDataDirectory.get(), "databases", nullptr));
190     }
191
192     if (priv->baseCacheDirectory) {
193         if (!priv->diskCacheDirectory)
194             priv->diskCacheDirectory.reset(g_strdup(priv->baseCacheDirectory.get()));
195         if (!priv->applicationCacheDirectory)
196             priv->applicationCacheDirectory.reset(g_build_filename(priv->baseCacheDirectory.get(), "applications", nullptr));
197     }
198 }
199
200 static void webkit_website_data_manager_class_init(WebKitWebsiteDataManagerClass* findClass)
201 {
202     GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
203
204     gObjectClass->get_property = webkitWebsiteDataManagerGetProperty;
205     gObjectClass->set_property = webkitWebsiteDataManagerSetProperty;
206     gObjectClass->constructed = webkitWebsiteDataManagerConstructed;
207
208     /**
209      * WebKitWebsiteDataManager:base-data-directory:
210      *
211      * The base directory for Website data. This is used as a base directory
212      * for any Website data when no specific data directory has been provided.
213      *
214      * Since: 2.10
215      */
216     g_object_class_install_property(
217         gObjectClass,
218         PROP_BASE_DATA_DIRECTORY,
219         g_param_spec_string(
220             "base-data-directory",
221             _("Base Data Directory"),
222             _("The base directory for Website data"),
223             nullptr,
224             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
225
226     /**
227      * WebKitWebsiteDataManager:base-cache-directory:
228      *
229      * The base directory for Website cache. This is used as a base directory
230      * for any Website cache when no specific cache directory has been provided.
231      *
232      * Since: 2.10
233      */
234     g_object_class_install_property(
235         gObjectClass,
236         PROP_BASE_CACHE_DIRECTORY,
237         g_param_spec_string(
238             "base-cache-directory",
239             _("Base Cache Directory"),
240             _("The base directory for Website cache"),
241             nullptr,
242             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
243
244     /**
245      * WebKitWebsiteDataManager:local-storage-directory:
246      *
247      * The directory where local storage data will be stored.
248      *
249      * Since: 2.10
250      */
251     g_object_class_install_property(
252         gObjectClass,
253         PROP_LOCAL_STORAGE_DIRECTORY,
254         g_param_spec_string(
255             "local-storage-directory",
256             _("Local Storage Directory"),
257             _("The directory where local storage data will be stored"),
258             nullptr,
259             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
260
261     /**
262      * WebKitWebsiteDataManager:disk-cache-directory:
263      *
264      * The directory where HTTP disk cache will be stored.
265      *
266      * Since: 2.10
267      */
268     g_object_class_install_property(
269         gObjectClass,
270         PROP_DISK_CACHE_DIRECTORY,
271         g_param_spec_string(
272             "disk-cache-directory",
273             _("Disk Cache Directory"),
274             _("The directory where HTTP disk cache will be stored"),
275             nullptr,
276             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
277
278     /**
279      * WebKitWebsiteDataManager:offline-application-cache-directory:
280      *
281      * The directory where offline web application cache will be stored.
282      *
283      * Since: 2.10
284      */
285     g_object_class_install_property(
286         gObjectClass,
287         PROP_APPLICATION_CACHE_DIRECTORY,
288         g_param_spec_string(
289             "offline-application-cache-directory",
290             _("Offline Web Application Cache Directory"),
291             _("The directory where offline web application cache will be stored"),
292             nullptr,
293             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
294
295     /**
296      * WebKitWebsiteDataManager:indexeddb-directory:
297      *
298      * The directory where IndexedDB databases will be stored.
299      *
300      * Since: 2.10
301      */
302     g_object_class_install_property(
303         gObjectClass,
304         PROP_INDEXEDDB_DIRECTORY,
305         g_param_spec_string(
306             "indexeddb-directory",
307             _("IndexedDB Directory"),
308             _("The directory where IndexedDB databases will be stored"),
309             nullptr,
310             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
311
312     /**
313      * WebKitWebsiteDataManager:websql-directory:
314      *
315      * The directory where WebSQL databases will be stored.
316      *
317      * Since: 2.10
318      */
319     g_object_class_install_property(
320         gObjectClass,
321         PROP_WEBSQL_DIRECTORY,
322         g_param_spec_string(
323             "websql-directory",
324             _("WebSQL Directory"),
325             _("The directory where WebSQL databases will be stored"),
326             nullptr,
327             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
328
329     /**
330      * WebKitWebsiteDataManager:is-ephemeral:
331      *
332      * Whether the #WebKitWebsiteDataManager is ephemeral. An ephemeral #WebKitWebsiteDataManager
333      * handles all websites data as non-persistent, and nothing will be written to the client
334      * storage. Note that if you create an ephemeral #WebKitWebsiteDataManager all other construction
335      * parameters to configure data directories will be ignored.
336      *
337      * Since: 2.16
338      */
339     g_object_class_install_property(
340         gObjectClass,
341         PROP_IS_EPHEMERAL,
342         g_param_spec_boolean(
343             "is-ephemeral",
344             "Is Ephemeral",
345             _("Whether the WebKitWebsiteDataManager is ephemeral"),
346             FALSE,
347             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
348 }
349
350 WebKitWebsiteDataManager* webkitWebsiteDataManagerCreate(WebsiteDataStore::Configuration&& configuration)
351 {
352     WebKitWebsiteDataManager* manager = WEBKIT_WEBSITE_DATA_MANAGER(g_object_new(WEBKIT_TYPE_WEBSITE_DATA_MANAGER, nullptr));
353     manager->priv->websiteDataStore = API::WebsiteDataStore::createLegacy(WTFMove(configuration));
354
355     return manager;
356 }
357
358 API::WebsiteDataStore& webkitWebsiteDataManagerGetDataStore(WebKitWebsiteDataManager* manager)
359 {
360     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
361     if (!priv->websiteDataStore) {
362         WebsiteDataStore::Configuration configuration;
363         configuration.localStorageDirectory = !priv->localStorageDirectory ?
364             API::WebsiteDataStore::defaultLocalStorageDirectory() : WebCore::stringFromFileSystemRepresentation(priv->localStorageDirectory.get());
365         configuration.networkCacheDirectory = !priv->diskCacheDirectory ?
366             API::WebsiteDataStore::defaultNetworkCacheDirectory() : WebCore::pathByAppendingComponent(WebCore::stringFromFileSystemRepresentation(priv->diskCacheDirectory.get()), networkCacheSubdirectory);
367         configuration.applicationCacheDirectory = !priv->applicationCacheDirectory ?
368             API::WebsiteDataStore::defaultApplicationCacheDirectory() : WebCore::stringFromFileSystemRepresentation(priv->applicationCacheDirectory.get());
369         configuration.webSQLDatabaseDirectory = !priv->webSQLDirectory ?
370             API::WebsiteDataStore::defaultWebSQLDatabaseDirectory() : WebCore::stringFromFileSystemRepresentation(priv->webSQLDirectory.get());
371         configuration.mediaKeysStorageDirectory = API::WebsiteDataStore::defaultMediaKeysStorageDirectory();
372         priv->websiteDataStore = API::WebsiteDataStore::createLegacy(WTFMove(configuration));
373     }
374
375     return *priv->websiteDataStore;
376 }
377
378 void webkitWebsiteDataManagerAddProcessPool(WebKitWebsiteDataManager* manager, WebProcessPool& processPool)
379 {
380     ASSERT(!manager->priv->processPools.contains(&processPool));
381     manager->priv->processPools.append(&processPool);
382 }
383
384 void webkitWebsiteDataManagerRemoveProcessPool(WebKitWebsiteDataManager* manager, WebProcessPool& processPool)
385 {
386     ASSERT(manager->priv->processPools.contains(&processPool));
387     manager->priv->processPools.removeFirst(&processPool);
388 }
389
390 const Vector<WebProcessPool*>& webkitWebsiteDataManagerGetProcessPools(WebKitWebsiteDataManager* manager)
391 {
392     return manager->priv->processPools;
393 }
394
395 /**
396  * webkit_website_data_manager_new:
397  * @first_option_name: name of the first option to set
398  * @...: value of first option, followed by more options, %NULL-terminated
399  *
400  * Creates a new #WebKitWebsiteDataManager with the given options. It must
401  * be passed as construction parameter of a #WebKitWebContext.
402  *
403  * Returns: (transfer full): the newly created #WebKitWebsiteDataManager
404  *
405  * Since: 2.10
406  */
407 WebKitWebsiteDataManager* webkit_website_data_manager_new(const gchar* firstOptionName, ...)
408 {
409     va_list args;
410     va_start(args, firstOptionName);
411     WebKitWebsiteDataManager* manager = WEBKIT_WEBSITE_DATA_MANAGER(g_object_new_valist(WEBKIT_TYPE_WEBSITE_DATA_MANAGER, firstOptionName, args));
412     va_end(args);
413
414     return manager;
415 }
416
417 /**
418  * webkit_website_data_manager_new_ephemeral:
419  *
420  * Creates an ephemeral #WebKitWebsiteDataManager. See #WebKitWebsiteDataManager:is-ephemeral for more details.
421  *
422  * Returns: (transfer full): a new ephemeral #WebKitWebsiteDataManager.
423  *
424  * Since: 2.16
425  */
426 WebKitWebsiteDataManager* webkit_website_data_manager_new_ephemeral()
427 {
428     return WEBKIT_WEBSITE_DATA_MANAGER(g_object_new(WEBKIT_TYPE_WEBSITE_DATA_MANAGER, "is-ephemeral", TRUE, nullptr));
429 }
430
431 /**
432  * webkit_website_data_manager_is_ephemeral:
433  * @manager: a #WebKitWebsiteDataManager
434  *
435  * Get whether a #WebKitWebsiteDataManager is ephemeral. See #WebKitWebsiteDataManager::is-ephemerla for more details.
436  *
437  * Returns: %TRUE if @manager is epheral or %FALSE otherwise.
438  *
439  * Since: 2.16
440  */
441 gboolean webkit_website_data_manager_is_ephemeral(WebKitWebsiteDataManager* manager)
442 {
443     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), FALSE);
444
445     return manager->priv->websiteDataStore && !manager->priv->websiteDataStore->isPersistent();
446 }
447
448 /**
449  * webkit_website_data_manager_get_base_data_directory:
450  * @manager: a #WebKitWebsiteDataManager
451  *
452  * Get the #WebKitWebsiteDataManager:base-data-directory property.
453  *
454  * Returns: (allow-none): the base directory for Website data, or %NULL if
455  *    #WebKitWebsiteDataManager:base-data-directory was not provided or @manager is ephemeral.
456  *
457  * Since: 2.10
458  */
459 const gchar* webkit_website_data_manager_get_base_data_directory(WebKitWebsiteDataManager* manager)
460 {
461     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
462
463     if (manager->priv->websiteDataStore && !manager->priv->websiteDataStore->isPersistent())
464         return nullptr;
465
466     return manager->priv->baseDataDirectory.get();
467 }
468
469 /**
470  * webkit_website_data_manager_get_base_cache_directory:
471  * @manager: a #WebKitWebsiteDataManager
472  *
473  * Get the #WebKitWebsiteDataManager:base-cache-directory property.
474  *
475  * Returns: (allow-none): the base directory for Website cache, or %NULL if
476  *    #WebKitWebsiteDataManager:base-cache-directory was not provided or @manager is ephemeral.
477  *
478  * Since: 2.10
479  */
480 const gchar* webkit_website_data_manager_get_base_cache_directory(WebKitWebsiteDataManager* manager)
481 {
482     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
483
484     if (manager->priv->websiteDataStore && !manager->priv->websiteDataStore->isPersistent())
485         return nullptr;
486
487     return manager->priv->baseCacheDirectory.get();
488 }
489
490 /**
491  * webkit_website_data_manager_get_local_storage_directory:
492  * @manager: a #WebKitWebsiteDataManager
493  *
494  * Get the #WebKitWebsiteDataManager:local-storage-directory property.
495  *
496  * Returns: (allow-none): the directory where local storage data is stored or %NULL if @manager is ephemeral.
497  *
498  * Since: 2.10
499  */
500 const gchar* webkit_website_data_manager_get_local_storage_directory(WebKitWebsiteDataManager* manager)
501 {
502     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
503
504     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
505     if (priv->websiteDataStore && !priv->websiteDataStore->isPersistent())
506         return nullptr;
507
508     if (!priv->localStorageDirectory)
509         priv->localStorageDirectory.reset(g_strdup(API::WebsiteDataStore::defaultLocalStorageDirectory().utf8().data()));
510     return priv->localStorageDirectory.get();
511 }
512
513 /**
514  * webkit_website_data_manager_get_disk_cache_directory:
515  * @manager: a #WebKitWebsiteDataManager
516  *
517  * Get the #WebKitWebsiteDataManager:disk-cache-directory property.
518  *
519  * Returns: (allow-none): the directory where HTTP disk cache is stored or %NULL if @manager is ephemeral.
520  *
521  * Since: 2.10
522  */
523 const gchar* webkit_website_data_manager_get_disk_cache_directory(WebKitWebsiteDataManager* manager)
524 {
525     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
526
527     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
528     if (priv->websiteDataStore && !priv->websiteDataStore->isPersistent())
529         return nullptr;
530
531     if (!priv->diskCacheDirectory) {
532         // The default directory already has the subdirectory.
533         priv->diskCacheDirectory.reset(g_strdup(WebCore::directoryName(API::WebsiteDataStore::defaultNetworkCacheDirectory()).utf8().data()));
534     }
535     return priv->diskCacheDirectory.get();
536 }
537
538 /**
539  * webkit_website_data_manager_get_offline_application_cache_directory:
540  * @manager: a #WebKitWebsiteDataManager
541  *
542  * Get the #WebKitWebsiteDataManager:offline-application-cache-directory property.
543  *
544  * Returns: (allow-none): the directory where offline web application cache is stored or %NULL if @manager is ephemeral.
545  *
546  * Since: 2.10
547  */
548 const gchar* webkit_website_data_manager_get_offline_application_cache_directory(WebKitWebsiteDataManager* manager)
549 {
550     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
551
552     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
553     if (priv->websiteDataStore && !priv->websiteDataStore->isPersistent())
554         return nullptr;
555
556     if (!priv->applicationCacheDirectory)
557         priv->applicationCacheDirectory.reset(g_strdup(API::WebsiteDataStore::defaultApplicationCacheDirectory().utf8().data()));
558     return priv->applicationCacheDirectory.get();
559 }
560
561 /**
562  * webkit_website_data_manager_get_indexeddb_directory:
563  * @manager: a #WebKitWebsiteDataManager
564  *
565  * Get the #WebKitWebsiteDataManager:indexeddb-directory property.
566  *
567  * Returns: (allow-none): the directory where IndexedDB databases are stored or %NULL if @manager is ephemeral.
568  *
569  * Since: 2.10
570  */
571 const gchar* webkit_website_data_manager_get_indexeddb_directory(WebKitWebsiteDataManager* manager)
572 {
573     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
574
575     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
576     if (priv->websiteDataStore && !priv->websiteDataStore->isPersistent())
577         return nullptr;
578
579     if (!priv->indexedDBDirectory)
580         priv->indexedDBDirectory.reset(g_strdup(API::WebsiteDataStore::defaultIndexedDBDatabaseDirectory().utf8().data()));
581     return priv->indexedDBDirectory.get();
582 }
583
584 /**
585  * webkit_website_data_manager_get_websql_directory:
586  * @manager: a #WebKitWebsiteDataManager
587  *
588  * Get the #WebKitWebsiteDataManager:websql-directory property.
589  *
590  * Returns: (allow-none): the directory where WebSQL databases are stored or %NULL if @manager is ephemeral.
591  *
592  * Since: 2.10
593  */
594 const gchar* webkit_website_data_manager_get_websql_directory(WebKitWebsiteDataManager* manager)
595 {
596     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
597
598     WebKitWebsiteDataManagerPrivate* priv = manager->priv;
599     if (priv->websiteDataStore && !priv->websiteDataStore->isPersistent())
600         return nullptr;
601
602     if (!priv->webSQLDirectory)
603         priv->webSQLDirectory.reset(g_strdup(API::WebsiteDataStore::defaultWebSQLDatabaseDirectory().utf8().data()));
604     return priv->webSQLDirectory.get();
605 }
606
607 /**
608  * webkit_website_data_manager_get_cookie_manager:
609  * @manager: a #WebKitWebsiteDataManager
610  *
611  * Get the #WebKitCookieManager of @manager.
612  *
613  * Returns: (transfer none): a #WebKitCookieManager
614  *
615  * Since: 2.16
616  */
617 WebKitCookieManager* webkit_website_data_manager_get_cookie_manager(WebKitWebsiteDataManager* manager)
618 {
619     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
620
621     if (!manager->priv->cookieManager)
622         manager->priv->cookieManager = adoptGRef(webkitCookieManagerCreate(manager));
623
624     return manager->priv->cookieManager.get();
625 }
626
627 static OptionSet<WebsiteDataType> toWebsiteDataTypes(WebKitWebsiteDataTypes types)
628 {
629     OptionSet<WebsiteDataType> returnValue;
630     if (types & WEBKIT_WEBSITE_DATA_MEMORY_CACHE)
631         returnValue |= WebsiteDataType::MemoryCache;
632     if (types & WEBKIT_WEBSITE_DATA_DISK_CACHE)
633         returnValue |= WebsiteDataType::DiskCache;
634     if (types & WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE)
635         returnValue |= WebsiteDataType::OfflineWebApplicationCache;
636     if (types & WEBKIT_WEBSITE_DATA_SESSION_STORAGE)
637         returnValue |= WebsiteDataType::SessionStorage;
638     if (types & WEBKIT_WEBSITE_DATA_LOCAL_STORAGE)
639         returnValue |= WebsiteDataType::LocalStorage;
640     if (types & WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES)
641         returnValue |= WebsiteDataType::WebSQLDatabases;
642     if (types & WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES)
643         returnValue |= WebsiteDataType::IndexedDBDatabases;
644 #if ENABLE(NETSCAPE_PLUGIN_API)
645     if (types & WEBKIT_WEBSITE_DATA_PLUGIN_DATA)
646         returnValue |= WebsiteDataType::PlugInData;
647 #endif
648     if (types & WEBKIT_WEBSITE_DATA_COOKIES)
649         returnValue |= WebsiteDataType::Cookies;
650     return returnValue;
651 }
652
653 /**
654  * webkit_website_data_manager_fetch:
655  * @manager: a #WebKitWebsiteDataManager
656  * @types: #WebKitWebsiteDataTypes
657  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
658  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
659  * @user_data: (closure): the data to pass to callback function
660  *
661  * Asynchronously get the list of #WebKitWebsiteData for the given @types.
662  *
663  * When the operation is finished, @callback will be called. You can then call
664  * webkit_website_data_manager_fetch_finish() to get the result of the operation.
665  *
666  * Since: 2.16
667  */
668 void webkit_website_data_manager_fetch(WebKitWebsiteDataManager* manager, WebKitWebsiteDataTypes types, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
669 {
670     g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
671
672     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
673     manager->priv->websiteDataStore->websiteDataStore().fetchData(toWebsiteDataTypes(types), WebsiteDataFetchOption::ComputeSizes, [task = WTFMove(task)] (Vector<WebsiteDataRecord> records) {
674         GList* dataList = nullptr;
675         while (!records.isEmpty()) {
676             if (auto* data = webkitWebsiteDataCreate(records.takeLast()))
677                 dataList = g_list_prepend(dataList, data);
678         }
679
680         g_task_return_pointer(task.get(), dataList, [](gpointer data) {
681             g_list_free_full(static_cast<GList*>(data), reinterpret_cast<GDestroyNotify>(webkit_website_data_unref));
682         });
683     });
684 }
685
686 /**
687  * webkit_website_data_manager_fetch_finish:
688  * @manager: a #WebKitWebsiteDataManager
689  * @result: a #GAsyncResult
690  * @error: return location for error or %NULL to ignore
691  *
692  * Finish an asynchronous operation started with webkit_website_data_manager_fetch().
693  *
694  * Returns: (element-type WebKitWebsiteData) (transfer full): a #GList of #WebKitWebsiteData. You must free the #GList with
695  *    g_list_free() and unref the #WebKitWebsiteData<!-- -->s with webkit_website_data_unref() when you're done with them.
696  *
697  * Since: 2.16
698  */
699 GList* webkit_website_data_manager_fetch_finish(WebKitWebsiteDataManager* manager, GAsyncResult* result, GError** error)
700 {
701     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
702     g_return_val_if_fail(g_task_is_valid(result, manager), nullptr);
703
704     return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
705 }
706
707 /**
708  * webkit_website_data_manager_remove:
709  * @manager: a #WebKitWebsiteDataManager
710  * @types: #WebKitWebsiteDataTypes
711  * @website_data: (element-type WebKitWebsiteData): a #GList of #WebKitWebsiteData
712  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
713  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
714  * @user_data: (closure): the data to pass to callback function
715  *
716  * Asynchronously removes the website data of the for the given @types for websites in the given @website_data list.
717  * Use webkit_website_data_manager_clear() if you want to remove the website data for all sites.
718  *
719  * When the operation is finished, @callback will be called. You can then call
720  * webkit_website_data_manager_remove_finish() to get the result of the operation.
721  *
722  * Since: 2.16
723  */
724 void webkit_website_data_manager_remove(WebKitWebsiteDataManager* manager, WebKitWebsiteDataTypes types, GList* websiteData, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
725 {
726     g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
727     g_return_if_fail(websiteData);
728
729     Vector<WebsiteDataRecord> records;
730     for (GList* item = websiteData; item; item = g_list_next(item)) {
731         WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(item->data);
732
733         if (webkit_website_data_get_types(data) & types)
734             records.append(webkitWebsiteDataGetRecord(data));
735     }
736
737     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
738     if (records.isEmpty()) {
739         g_task_return_boolean(task.get(), TRUE);
740         return;
741     }
742
743     manager->priv->websiteDataStore->websiteDataStore().removeData(toWebsiteDataTypes(types), records, [task = WTFMove(task)] {
744         g_task_return_boolean(task.get(), TRUE);
745     });
746 }
747
748 /**
749  * webkit_website_data_manager_remove_finish:
750  * @manager: a #WebKitWebsiteDataManager
751  * @result: a #GAsyncResult
752  * @error: return location for error or %NULL to ignore
753  *
754  * Finish an asynchronous operation started with webkit_website_data_manager_remove().
755  *
756  * Returns: %TRUE if website data resources were successfully removed, or %FALSE otherwise.
757  *
758  * Since: 2.16
759  */
760 gboolean webkit_website_data_manager_remove_finish(WebKitWebsiteDataManager* manager, GAsyncResult* result, GError** error)
761 {
762     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), FALSE);
763     g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
764
765     return g_task_propagate_boolean(G_TASK(result), error);
766 }
767
768 /**
769  * webkit_website_data_manager_clear:
770  * @manager: a #WebKitWebsiteDataManager
771  * @types: #WebKitWebsiteDataTypes
772  * @timespan: a #GTimeSpan
773  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
774  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
775  * @user_data: (closure): the data to pass to callback function
776  *
777  * Asynchronously clear the website data of the given @types modified in the past @timespan.
778  * If @timespan is 0, all website data will be removed.
779  *
780  * When the operation is finished, @callback will be called. You can then call
781  * webkit_website_data_manager_clear_finish() to get the result of the operation.
782  *
783  * Due to implementation limitations, this function does not currently delete
784  * any stored cookies if @timespan is nonzero. This behavior may change in the
785  * future.
786  *
787  * Since: 2.16
788  */
789 void webkit_website_data_manager_clear(WebKitWebsiteDataManager* manager, WebKitWebsiteDataTypes types, GTimeSpan timeSpan, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
790 {
791     g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
792
793     std::chrono::system_clock::time_point timePoint = timeSpan ? std::chrono::system_clock::now() - std::chrono::microseconds(timeSpan) : std::chrono::system_clock::from_time_t(0);
794     GRefPtr<GTask> task = adoptGRef(g_task_new(manager, cancellable, callback, userData));
795     manager->priv->websiteDataStore->websiteDataStore().removeData(toWebsiteDataTypes(types), timePoint, [task = WTFMove(task)] {
796         g_task_return_boolean(task.get(), TRUE);
797     });
798 }
799
800 /**
801  * webkit_website_data_manager_clear_finish:
802  * @manager: a #WebKitWebsiteDataManager
803  * @result: a #GAsyncResult
804  * @error: return location for error or %NULL to ignore
805  *
806  * Finish an asynchronous operation started with webkit_website_data_manager_clear()
807  *
808  * Returns: %TRUE if website data was successfully cleared, or %FALSE otherwise.
809  *
810  * Since: 2.16
811  */
812 gboolean webkit_website_data_manager_clear_finish(WebKitWebsiteDataManager* manager, GAsyncResult* result, GError** error)
813 {
814     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), FALSE);
815     g_return_val_if_fail(g_task_is_valid(result, manager), FALSE);
816
817     return g_task_propagate_boolean(G_TASK(result), error);
818 }