1/*
2 * Copyright (C) 2009 Martin Robinson, Jan Michael C. Alonzo
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 "webkitsecurityorigin.h"
22
23#include "DatabaseTracker.h"
24#include "PlatformString.h"
25#include "webkitglobalsprivate.h"
26#include "webkitsecurityoriginprivate.h"
27#include <glib/gi18n-lib.h>
28#include <wtf/text/CString.h>
29
30/**
31 * SECTION:webkitsecurityorigin
32 * @short_description: A security boundary for web sites
33 *
34 * #WebKitSecurityOrigin is a representation of a security domain defined
35 * by web sites. An origin consists of a host name, a protocol, and a port
36 * number. Web sites with the same security origin can access each other's
37 * resources for client-side scripting or database access.
38 *
39 * Use #webkit_web_frame_get_security_origin to get the security origin of a
40 * #WebKitWebFrame.
41 *
42 * Database quotas and usages are also defined per security origin. The
43 * cumulative disk usage of an origin's databases may be retrieved with
44 * #webkit_security_origin_get_web_database_usage. An origin's quota can be
45 * adjusted with #webkit_security_origin_set_web_database_quota.
46 */
47
48using namespace WebKit;
49
50enum {
51    PROP_0,
52
53    PROP_PROTOCOL,
54    PROP_HOST,
55    PROP_PORT,
56    PROP_DATABASE_USAGE,
57    PROP_DATABASE_QUOTA
58};
59
60G_DEFINE_TYPE(WebKitSecurityOrigin, webkit_security_origin, G_TYPE_OBJECT)
61
62static void webkit_security_origin_finalize(GObject* object)
63{
64    WebKitSecurityOrigin* securityOrigin = WEBKIT_SECURITY_ORIGIN(object);
65    WebKitSecurityOriginPrivate* priv = securityOrigin->priv;
66
67    g_free(priv->protocol);
68    g_free(priv->host);
69
70    G_OBJECT_CLASS(webkit_security_origin_parent_class)->finalize(object);
71}
72
73static void webkit_security_origin_dispose(GObject* object)
74{
75    WebKitSecurityOrigin* securityOrigin = WEBKIT_SECURITY_ORIGIN(object);
76    WebKitSecurityOriginPrivate* priv = securityOrigin->priv;
77
78    if (!priv->disposed) {
79        priv->coreOrigin->deref();
80        g_hash_table_destroy(priv->webDatabases);
81        priv->disposed = true;
82    }
83
84    G_OBJECT_CLASS(webkit_security_origin_parent_class)->dispose(object);
85}
86
87static void webkit_security_origin_set_property(GObject* object, guint propId, const GValue* value, GParamSpec* pspec)
88{
89    WebKitSecurityOrigin* securityOrigin = WEBKIT_SECURITY_ORIGIN(object);
90
91    switch (propId) {
92    case PROP_DATABASE_QUOTA:
93        webkit_security_origin_set_web_database_quota(securityOrigin, g_value_get_uint64(value));
94        break;
95    default:
96        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
97        break;
98    }
99}
100
101static void webkit_security_origin_get_property(GObject* object, guint propId, GValue* value, GParamSpec* pspec)
102{
103    WebKitSecurityOrigin* securityOrigin = WEBKIT_SECURITY_ORIGIN(object);
104
105    switch (propId) {
106    case PROP_PROTOCOL:
107        g_value_set_string(value, webkit_security_origin_get_protocol(securityOrigin));
108        break;
109    case PROP_HOST:
110        g_value_set_string(value, webkit_security_origin_get_host(securityOrigin));
111        break;
112    case PROP_PORT:
113        g_value_set_uint(value, webkit_security_origin_get_port(securityOrigin));
114        break;
115    case PROP_DATABASE_USAGE:
116        g_value_set_uint64(value, webkit_security_origin_get_web_database_usage(securityOrigin));
117        break;
118    case PROP_DATABASE_QUOTA:
119        g_value_set_uint64(value, webkit_security_origin_get_web_database_quota(securityOrigin));
120        break;
121    default:
122        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec);
123        break;
124    }
125}
126
127static GHashTable* webkit_security_origins()
128{
129    static GHashTable* securityOrigins = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
130    return securityOrigins;
131}
132
133static void webkit_security_origin_class_init(WebKitSecurityOriginClass* klass)
134{
135    GObjectClass* gobjectClass = G_OBJECT_CLASS(klass);
136    gobjectClass->dispose = webkit_security_origin_dispose;
137    gobjectClass->finalize = webkit_security_origin_finalize;
138    gobjectClass->set_property = webkit_security_origin_set_property;
139    gobjectClass->get_property = webkit_security_origin_get_property;
140
141     /**
142      * WebKitSecurityOrigin:protocol:
143      *
144      * The protocol of the security origin.
145      *
146      * Since: 1.1.14
147      */
148     g_object_class_install_property(gobjectClass, PROP_PROTOCOL,
149                                     g_param_spec_string("protocol",
150                                                         _("Protocol"),
151                                                         _("The protocol of the security origin"),
152                                                         NULL,
153                                                         WEBKIT_PARAM_READABLE));
154
155     /**
156      * WebKitSecurityOrigin:host:
157      *
158      * The host of the security origin.
159      *
160      * Since: 1.1.14
161      */
162     g_object_class_install_property(gobjectClass, PROP_HOST,
163                                     g_param_spec_string("host",
164                                                         _("Host"),
165                                                         _("The host of the security origin"),
166                                                         NULL,
167                                                         WEBKIT_PARAM_READABLE));
168
169     /**
170      * WebKitSecurityOrigin:port:
171      *
172      * The port of the security origin.
173      *
174      * Since: 1.1.14
175      */
176     g_object_class_install_property(gobjectClass, PROP_PORT,
177                                     g_param_spec_uint("port",
178                                                       _("Port"),
179                                                       _("The port of the security origin"),
180                                                       0, G_MAXUSHORT, 0,
181                                                       WEBKIT_PARAM_READABLE));
182
183      /**
184      * WebKitSecurityOrigin:web-database-usage:
185      *
186      * The cumulative size of all web databases in the security origin in bytes.
187      *
188      * Since: 1.1.14
189      */
190      g_object_class_install_property(gobjectClass, PROP_DATABASE_USAGE,
191                                      g_param_spec_uint64("web-database-usage",
192                                                          _("Web Database Usage"),
193                                                          _("The cumulative size of all web databases in the security origin"),
194                                                          0, G_MAXUINT64, 0,
195                                                          WEBKIT_PARAM_READABLE));
196      /**
197      * WebKitSecurityOrigin:web-database-quota:
198      *
199      * The web database qouta of the security origin in bytes.
200      *
201      * Since: 1.1.14
202      */
203      g_object_class_install_property(gobjectClass, PROP_DATABASE_QUOTA,
204                                      g_param_spec_uint64("web-database-quota",
205                                                          _("Web Database Quota"),
206                                                          _("The web database quota of the security origin in bytes"),
207                                                          0, G_MAXUINT64, 0,
208                                                          WEBKIT_PARAM_READWRITE));
209
210    g_type_class_add_private(klass, sizeof(WebKitSecurityOriginPrivate));
211}
212
213static void webkit_security_origin_init(WebKitSecurityOrigin* securityOrigin)
214{
215    WebKitSecurityOriginPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(securityOrigin, WEBKIT_TYPE_SECURITY_ORIGIN, WebKitSecurityOriginPrivate);
216    priv->webDatabases = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
217    securityOrigin->priv = priv;
218}
219
220/**
221 * webkit_security_origin_get_protocol:
222 * @securityOrigin: a #WebKitSecurityOrigin
223 *
224 * Returns the protocol for the security origin.
225 *
226 * Returns: the protocol for the security origin
227 *
228 * Since: 1.1.14
229 **/
230G_CONST_RETURN gchar* webkit_security_origin_get_protocol(WebKitSecurityOrigin* securityOrigin)
231{
232    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), NULL);
233
234    WebKitSecurityOriginPrivate* priv = securityOrigin->priv;
235    WTF::String protocol =  priv->coreOrigin->protocol();
236
237    if (!priv->protocol)
238        priv->protocol = g_strdup(protocol.utf8().data());
239
240    return priv->protocol;
241}
242
243/**
244 * webkit_security_origin_get_host:
245 * @securityOrigin: a #WebKitSecurityOrigin
246 *
247 * Returns the hostname for the security origin.
248 *
249 * Returns: the hostname for the security origin
250 *
251 * Since: 1.1.14
252 **/
253G_CONST_RETURN gchar* webkit_security_origin_get_host(WebKitSecurityOrigin* securityOrigin)
254{
255    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), NULL);
256
257    WebKitSecurityOriginPrivate* priv = securityOrigin->priv;
258    WTF::String host =  priv->coreOrigin->host();
259
260    if (!priv->host)
261        priv->host = g_strdup(host.utf8().data());
262
263    return priv->host;
264}
265
266/**
267 * webkit_security_origin_get_port:
268 * @securityOrigin: a #WebKitSecurityOrigin
269 *
270 * Returns the port for the security origin.
271 *
272 * Returns: the port for the security origin
273 *
274 * Since: 1.1.14
275 **/
276guint webkit_security_origin_get_port(WebKitSecurityOrigin* securityOrigin)
277{
278    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), 0);
279
280    WebCore::SecurityOrigin* coreOrigin = core(securityOrigin);
281    return coreOrigin->port();
282}
283
284/**
285 * webkit_security_origin_get_web_database_usage:
286 * @securityOrigin: a #WebKitSecurityOrigin
287 *
288 * Returns the cumulative size of all Web Database database's in the origin
289 * in bytes.
290 *
291 * Returns: the cumulative size of all databases
292 *
293 * Since: 1.1.14
294 **/
295guint64 webkit_security_origin_get_web_database_usage(WebKitSecurityOrigin* securityOrigin)
296{
297    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), 0);
298
299#if ENABLE(DATABASE)
300    WebCore::SecurityOrigin* coreOrigin = core(securityOrigin);
301    return WebCore::DatabaseTracker::tracker().usageForOrigin(coreOrigin);
302#else
303    return 0;
304#endif
305}
306
307/**
308 * webkit_security_origin_get_web_database_quota:
309 * @securityOrigin: a #WebKitSecurityOrigin
310 *
311 * Returns the quota for Web Database storage of the security origin
312 * in bytes.
313 *
314 * Returns: the Web Database quota
315 *
316 * Since: 1.1.14
317 **/
318guint64 webkit_security_origin_get_web_database_quota(WebKitSecurityOrigin* securityOrigin)
319{
320    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), 0);
321
322#if ENABLE(DATABASE)
323    WebCore::SecurityOrigin* coreOrigin = core(securityOrigin);
324    return WebCore::DatabaseTracker::tracker().quotaForOrigin(coreOrigin);
325#else
326    return 0;
327#endif
328}
329
330/**
331 * webkit_security_origin_set_web_database_quota:
332 * @securityOrigin: a #WebKitSecurityOrigin
333 * @quota: a new Web Database quota in bytes
334 *
335 * Adjust the quota for Web Database storage of the security origin
336 *
337 * Since: 1.1.14
338 **/
339void webkit_security_origin_set_web_database_quota(WebKitSecurityOrigin* securityOrigin, guint64 quota)
340{
341    g_return_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin));
342
343#if ENABLE(DATABASE)
344    WebCore::SecurityOrigin* coreOrigin = core(securityOrigin);
345    WebCore::DatabaseTracker::tracker().setQuota(coreOrigin, quota);
346#endif
347}
348
349/**
350 * webkit_security_origin_get_all_web_databases:
351 * @securityOrigin: a #WebKitSecurityOrigin
352 *
353 * Returns a list of all Web Databases in the security origin.
354 *
355 * Returns: (transfer container) (element-type WebKitWebDatabase): a
356 * #GList of databases in the security origin.
357 *
358 * Since: 1.1.14
359 **/
360GList* webkit_security_origin_get_all_web_databases(WebKitSecurityOrigin* securityOrigin)
361{
362    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), NULL);
363    GList* databases = NULL;
364
365#if ENABLE(DATABASE)
366    WebCore::SecurityOrigin* coreOrigin = core(securityOrigin);
367    Vector<WTF::String> databaseNames;
368
369    if (!WebCore::DatabaseTracker::tracker().databaseNamesForOrigin(coreOrigin, databaseNames))
370        return NULL;
371
372    for (unsigned i = 0; i < databaseNames.size(); ++i) {
373        WebKitWebDatabase* database = webkit_security_origin_get_web_database(securityOrigin, databaseNames[i].utf8().data());
374        databases = g_list_append(databases, database);
375    }
376#endif
377
378    return databases;
379}
380
381WebKitWebDatabase* webkit_security_origin_get_web_database(WebKitSecurityOrigin* securityOrigin, const gchar* databaseName)
382{
383    g_return_val_if_fail(WEBKIT_IS_SECURITY_ORIGIN(securityOrigin), NULL);
384
385    WebKitSecurityOriginPrivate* priv = securityOrigin->priv;
386    GHashTable* databaseHash = priv->webDatabases;
387    WebKitWebDatabase* database = (WebKitWebDatabase*) g_hash_table_lookup(databaseHash, databaseName);
388
389    if (!database) {
390        database =  WEBKIT_WEB_DATABASE(g_object_new(WEBKIT_TYPE_WEB_DATABASE,
391                                       "security-origin", securityOrigin,
392                                       "name", databaseName,
393                                        NULL));
394        g_hash_table_insert(databaseHash, g_strdup(databaseName), database);
395    }
396
397    return database;
398}
399
400namespace WebKit {
401
402WebCore::SecurityOrigin* core(WebKitSecurityOrigin* securityOrigin)
403{
404    ASSERT(securityOrigin);
405
406    return securityOrigin->priv->coreOrigin.get();
407}
408
409WebKitSecurityOrigin* kit(WebCore::SecurityOrigin* coreOrigin)
410{
411    ASSERT(coreOrigin);
412
413    GHashTable* table = webkit_security_origins();
414    WebKitSecurityOrigin* origin = (WebKitSecurityOrigin*) g_hash_table_lookup(table, coreOrigin);
415
416    if (!origin) {
417        origin = WEBKIT_SECURITY_ORIGIN(g_object_new(WEBKIT_TYPE_SECURITY_ORIGIN, NULL));
418        origin->priv->coreOrigin = coreOrigin;
419        g_hash_table_insert(table, coreOrigin, origin);
420    }
421
422    return origin;
423}
424
425}
426