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 Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 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 "WebKitWebsiteData.h"
22
23#include "WebKitSecurityOriginPrivate.h"
24#include "WebKitWebsiteDataPrivate.h"
25#include <glib/gi18n-lib.h>
26#include <wtf/HashTable.h>
27#include <wtf/Vector.h>
28
29using namespace WebKit;
30
31/**
32 * SECTION: WebKitWebsiteData
33 * @Short_description: Website data
34 * @Title: WebKitWebsiteData
35 * @See_also: #WebKitWebsiteDataManager
36 *
37 * WebKitWebsiteData represents data stored in the client by a particular website.
38 * A website is normally a set of URLs grouped by domain name. You can get the website name,
39 * which is usually the domain, with webkit_website_data_get_name().
40 * Documents loaded from the file system, like file:// URIs, are all grouped in the same WebKitWebsiteData
41 * with the name "Local files".
42 *
43 * A website can store different types of data in the client side. #WebKitWebsiteDataTypes is an enum containing
44 * all the possible data types; use webkit_website_data_get_types() to get the bitmask of data types.
45 * It's also possible to know the size of the data stored for some of the #WebKitWebsiteDataTypes by using
46 * webkit_website_data_get_size().
47 *
48 * A list of WebKitWebsiteData can be retrieved with webkit_website_data_manager_fetch(). See #WebKitWebsiteDataManager
49 * for more information.
50 *
51 * Since: 2.16
52 */
53struct _WebKitWebsiteData {
54 explicit _WebKitWebsiteData(WebsiteDataRecord&& websiteDataDecord)
55 : record(WTFMove(websiteDataDecord))
56 {
57 }
58
59 WebsiteDataRecord record;
60 CString displayName;
61 int referenceCount { 1 };
62};
63
64G_DEFINE_BOXED_TYPE(WebKitWebsiteData, webkit_website_data, webkit_website_data_ref, webkit_website_data_unref)
65
66static bool recordContainsSupportedDataTypes(const WebsiteDataRecord& record)
67{
68 return record.types.containsAny({
69 WebsiteDataType::MemoryCache,
70 WebsiteDataType::DiskCache,
71 WebsiteDataType::OfflineWebApplicationCache,
72 WebsiteDataType::SessionStorage,
73 WebsiteDataType::LocalStorage,
74 WebsiteDataType::WebSQLDatabases,
75 WebsiteDataType::IndexedDBDatabases,
76#if ENABLE(NETSCAPE_PLUGIN_API)
77 WebsiteDataType::PlugInData,
78#endif
79 WebsiteDataType::Cookies,
80 WebsiteDataType::DeviceIdHashSalt
81 });
82}
83
84static WebKitWebsiteDataTypes toWebKitWebsiteDataTypes(OptionSet<WebsiteDataType> types)
85{
86 uint32_t returnValue = 0;
87 if (types.contains(WebsiteDataType::MemoryCache))
88 returnValue |= WEBKIT_WEBSITE_DATA_MEMORY_CACHE;
89 if (types.contains(WebsiteDataType::DiskCache))
90 returnValue |= WEBKIT_WEBSITE_DATA_DISK_CACHE;
91 if (types.contains(WebsiteDataType::OfflineWebApplicationCache))
92 returnValue |= WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE;
93 if (types.contains(WebsiteDataType::SessionStorage))
94 returnValue |= WEBKIT_WEBSITE_DATA_SESSION_STORAGE;
95 if (types.contains(WebsiteDataType::LocalStorage))
96 returnValue |= WEBKIT_WEBSITE_DATA_LOCAL_STORAGE;
97 if (types.contains(WebsiteDataType::WebSQLDatabases))
98 returnValue |= WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES;
99 if (types.contains(WebsiteDataType::IndexedDBDatabases))
100 returnValue |= WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES;
101#if ENABLE(NETSCAPE_PLUGIN_API)
102 if (types.contains(WebsiteDataType::PlugInData))
103 returnValue |= WEBKIT_WEBSITE_DATA_PLUGIN_DATA;
104#endif
105 if (types.contains(WebsiteDataType::Cookies))
106 returnValue |= WEBKIT_WEBSITE_DATA_COOKIES;
107 if (types.contains(WebsiteDataType::DeviceIdHashSalt))
108 returnValue |= WEBKIT_WEBSITE_DATA_DEVICE_ID_HASH_SALT;
109 return static_cast<WebKitWebsiteDataTypes>(returnValue);
110}
111
112WebKitWebsiteData* webkitWebsiteDataCreate(WebsiteDataRecord&& record)
113{
114 if (!recordContainsSupportedDataTypes(record))
115 return nullptr;
116
117 WebKitWebsiteData* websiteData = static_cast<WebKitWebsiteData*>(fastMalloc(sizeof(WebKitWebsiteData)));
118 new (websiteData) WebKitWebsiteData(WTFMove(record));
119 return websiteData;
120}
121
122const WebKit::WebsiteDataRecord& webkitWebsiteDataGetRecord(WebKitWebsiteData* websiteData)
123{
124 ASSERT(websiteData);
125 return websiteData->record;
126}
127
128/**
129 * webkit_website_data_ref:
130 * @website_data: a #WebKitWebsiteData
131 *
132 * Atomically increments the reference count of @website_data by one.
133 * This function is MT-safe and may be called from any thread.
134 *
135 * Returns: The passed #WebKitWebsiteData
136 *
137 * Since: 2.16
138 */
139WebKitWebsiteData* webkit_website_data_ref(WebKitWebsiteData* websiteData)
140{
141 g_return_val_if_fail(websiteData, nullptr);
142
143 g_atomic_int_inc(&websiteData->referenceCount);
144 return websiteData;
145}
146
147/**
148 * webkit_website_data_unref:
149 * @website_data: A #WebKitWebsiteData
150 *
151 * Atomically decrements the reference count of @website_data by one.
152 * If the reference count drops to 0, all memory allocated by
153 * #WebKitWebsiteData is released. This function is MT-safe and may be
154 * called from any thread.
155 *
156 * Since: 2.16
157 */
158void webkit_website_data_unref(WebKitWebsiteData* websiteData)
159{
160 g_return_if_fail(websiteData);
161
162 if (g_atomic_int_dec_and_test(&websiteData->referenceCount)) {
163 websiteData->~WebKitWebsiteData();
164 fastFree(websiteData);
165 }
166}
167
168/**
169 * webkit_website_data_get_name:
170 * @website_data: a #WebKitWebsiteData
171 *
172 * Gets the name of #WebKitWebsiteData. This is the website name, normally represented by
173 * a domain or host name. All local documents are grouped in the same #WebKitWebsiteData using
174 * the name "Local files".
175 *
176 * Returns: the website name of @website_data.
177 *
178 * Since: 2.16
179 */
180const char* webkit_website_data_get_name(WebKitWebsiteData* websiteData)
181{
182 g_return_val_if_fail(websiteData, nullptr);
183
184 if (websiteData->displayName.isNull()) {
185 if (websiteData->record.displayName == "Local documents on your computer")
186 websiteData->displayName = _("Local files");
187 else
188 websiteData->displayName = websiteData->record.displayName.utf8();
189 }
190 return websiteData->displayName.data();
191}
192
193/**
194 * webkit_website_data_get_types:
195 * @website_data: a #WebKitWebsiteData
196 *
197 * Gets the types of data stored in the client for a #WebKitWebsiteData. These are the
198 * types actually present, not the types queried with webkit_website_data_manager_fetch().
199 *
200 * Returns: a bitmask of #WebKitWebsiteDataTypes in @website_data
201 *
202 * Since: 2.16
203 */
204WebKitWebsiteDataTypes webkit_website_data_get_types(WebKitWebsiteData* websiteData)
205{
206 g_return_val_if_fail(websiteData, static_cast<WebKitWebsiteDataTypes>(0));
207
208 return toWebKitWebsiteDataTypes(websiteData->record.types);
209}
210
211/**
212 * webkit_website_data_get_size:
213 * @website_data: a #WebKitWebsiteData
214 * @types: a bitmask of #WebKitWebsiteDataTypes
215 *
216 * Gets the size of the data of types @types in a #WebKitWebsiteData.
217 * Note that currently the data size is only known for %WEBKIT_WEBSITE_DATA_DISK_CACHE data type
218 * so for all other types 0 will be returned.
219 *
220 * Returns: the size of @website_data for the given @types.
221 *
222 * Since: 2.16
223 */
224guint64 webkit_website_data_get_size(WebKitWebsiteData* websiteData, WebKitWebsiteDataTypes types)
225{
226 g_return_val_if_fail(websiteData, 0);
227
228 if (!types || !websiteData->record.size)
229 return 0;
230
231 guint64 totalSize = 0;
232 for (auto type : websiteData->record.size->typeSizes.keys()) {
233 if (type & types)
234 totalSize += websiteData->record.size->typeSizes.get(type);
235 }
236
237 return totalSize;
238}
239