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 "WebKitSecurityOrigin.h"
22
23#include "WebKitSecurityOriginPrivate.h"
24#include <wtf/URL.h>
25#include <wtf/text/CString.h>
26
27/**
28 * SECTION: WebKitSecurityOrigin
29 * @Short_description: A security boundary for websites
30 * @Title: WebKitSecurityOrigin
31 *
32 * #WebKitSecurityOrigin is a representation of a security domain
33 * defined by websites. A security origin normally consists of a
34 * protocol, a hostname, and a port number. It is also possible for a
35 * security origin to be opaque, as defined by the HTML standard, in
36 * which case it has no associated protocol, host, or port.
37 *
38 * Websites with the same security origin can access each other's
39 * resources for client-side scripting or database access.
40 *
41 * Since: 2.16
42 */
43
44struct _WebKitSecurityOrigin {
45 _WebKitSecurityOrigin(Ref<WebCore::SecurityOrigin>&& coreSecurityOrigin)
46 : securityOrigin(WTFMove(coreSecurityOrigin))
47 {
48 }
49
50 Ref<WebCore::SecurityOrigin> securityOrigin;
51 CString protocol;
52 CString host;
53 int referenceCount { 1 };
54};
55
56G_DEFINE_BOXED_TYPE(WebKitSecurityOrigin, webkit_security_origin, webkit_security_origin_ref, webkit_security_origin_unref)
57
58WebKitSecurityOrigin* webkitSecurityOriginCreate(Ref<WebCore::SecurityOrigin>&& coreSecurityOrigin)
59{
60 WebKitSecurityOrigin* origin = static_cast<WebKitSecurityOrigin*>(fastMalloc(sizeof(WebKitSecurityOrigin)));
61 new (origin) WebKitSecurityOrigin(WTFMove(coreSecurityOrigin));
62 return origin;
63}
64
65WebCore::SecurityOrigin& webkitSecurityOriginGetSecurityOrigin(WebKitSecurityOrigin* origin)
66{
67 ASSERT(origin);
68 return origin->securityOrigin.get();
69}
70
71/**
72 * webkit_security_origin_new:
73 * @protocol: The protocol for the new origin
74 * @host: The host for the new origin
75 * @port: The port number for the new origin, or 0 to indicate the
76 * default port for @protocol
77 *
78 * Create a new security origin from the provided protocol, host and
79 * port.
80 *
81 * Returns: (transfer full): A #WebKitSecurityOrigin.
82 *
83 * Since: 2.16
84 */
85WebKitSecurityOrigin* webkit_security_origin_new(const gchar* protocol, const gchar* host, guint16 port)
86{
87 g_return_val_if_fail(protocol, nullptr);
88 g_return_val_if_fail(host, nullptr);
89
90 Optional<uint16_t> optionalPort;
91 if (port)
92 optionalPort = port;
93
94 return webkitSecurityOriginCreate(WebCore::SecurityOrigin::create(String::fromUTF8(protocol), String::fromUTF8(host), optionalPort));
95}
96
97/**
98 * webkit_security_origin_new_for_uri:
99 * @uri: The URI for the new origin
100 *
101 * Create a new security origin from the provided URI. Components of
102 * @uri other than protocol, host, and port do not affect the created
103 * #WebKitSecurityOrigin.
104 *
105 * Returns: (transfer full): A #WebKitSecurityOrigin.
106 *
107 * Since: 2.16
108 */
109WebKitSecurityOrigin* webkit_security_origin_new_for_uri(const gchar* uri)
110{
111 g_return_val_if_fail(uri, nullptr);
112
113 return webkitSecurityOriginCreate(WebCore::SecurityOrigin::create(URL(URL(), String::fromUTF8(uri))));
114}
115
116/**
117 * webkit_security_origin_ref:
118 * @origin: a #WebKitSecurityOrigin
119 *
120 * Atomically increments the reference count of @origin by one.
121 * This function is MT-safe and may be called from any thread.
122 *
123 * Returns: The passed #WebKitSecurityOrigin
124 *
125 * Since: 2.16
126 */
127WebKitSecurityOrigin* webkit_security_origin_ref(WebKitSecurityOrigin* origin)
128{
129 g_return_val_if_fail(origin, nullptr);
130
131 g_atomic_int_inc(&origin->referenceCount);
132 return origin;
133}
134
135/**
136 * webkit_security_origin_unref:
137 * @origin: A #WebKitSecurityOrigin
138 *
139 * Atomically decrements the reference count of @origin by one.
140 * If the reference count drops to 0, all memory allocated by
141 * #WebKitSecurityOrigin is released. This function is MT-safe and may be
142 * called from any thread.
143 *
144 * Since: 2.16
145 */
146void webkit_security_origin_unref(WebKitSecurityOrigin* origin)
147{
148 g_return_if_fail(origin);
149
150 if (g_atomic_int_dec_and_test(&origin->referenceCount)) {
151 origin->~WebKitSecurityOrigin();
152 fastFree(origin);
153 }
154}
155
156/**
157 * webkit_security_origin_get_protocol:
158 * @origin: a #WebKitSecurityOrigin
159 *
160 * Gets the protocol of @origin, or %NULL if @origin is opaque.
161 *
162 * Returns: (allow-none): The protocol of the #WebKitSecurityOrigin
163 *
164 * Since: 2.16
165 */
166const gchar* webkit_security_origin_get_protocol(WebKitSecurityOrigin* origin)
167{
168 g_return_val_if_fail(origin, nullptr);
169
170 if (origin->securityOrigin->protocol().isEmpty())
171 return nullptr;
172
173 if (origin->protocol.isNull())
174 origin->protocol = origin->securityOrigin->protocol().utf8();
175 return origin->protocol.data();
176}
177
178/**
179 * webkit_security_origin_get_host:
180 * @origin: a #WebKitSecurityOrigin
181 *
182 * Gets the hostname of @origin, or %NULL if @origin is opaque or if its
183 * protocol does not require a host component.
184 *
185 * Returns: (allow-none): The host of the #WebKitSecurityOrigin
186 *
187 * Since: 2.16
188 */
189const gchar* webkit_security_origin_get_host(WebKitSecurityOrigin* origin)
190{
191 g_return_val_if_fail(origin, nullptr);
192
193 if (origin->securityOrigin->host().isEmpty())
194 return nullptr;
195
196 if (origin->host.isNull())
197 origin->host = origin->securityOrigin->host().utf8();
198 return origin->host.data();
199}
200
201/**
202 * webkit_security_origin_get_port:
203 * @origin: a #WebKitSecurityOrigin
204 *
205 * Gets the port of @origin. This function will always return 0 if the
206 * port is the default port for the given protocol. For example,
207 * http://example.com has the same security origin as
208 * http://example.com:80, and this function will return 0 for a
209 * #WebKitSecurityOrigin constructed from either URI. It will also
210 * return 0 if @origin is opaque.
211 *
212 * Returns: The port of the #WebKitSecurityOrigin.
213 *
214 * Since: 2.16
215 */
216guint16 webkit_security_origin_get_port(WebKitSecurityOrigin* origin)
217{
218 g_return_val_if_fail(origin, 0);
219
220 return origin->securityOrigin->port().valueOr(0);
221}
222
223/**
224 * webkit_security_origin_is_opaque:
225 * @origin: a #WebKitSecurityOrigin
226 *
227 * Gets whether @origin is an opaque security origin, which does not
228 * possess an associated protocol, host, or port.
229 *
230 * Returns: %TRUE if @origin is opaque.
231 *
232 * Since: 2.16
233 */
234gboolean webkit_security_origin_is_opaque(WebKitSecurityOrigin* origin)
235{
236 g_return_val_if_fail(origin, TRUE);
237
238 return origin->securityOrigin->isUnique();
239}
240
241/**
242 * webkit_security_origin_to_string:
243 * @origin: a #WebKitSecurityOrigin
244 *
245 * Gets a string representation of @origin. The string representation
246 * is a valid URI with only protocol, host, and port components. It may
247 * be %NULL, but usually only if @origin is opaque.
248 *
249 * Returns: (allow-none) (transfer full): a URI representing @origin.
250 *
251 * Since: 2.16
252 */
253gchar* webkit_security_origin_to_string(WebKitSecurityOrigin* origin)
254{
255 g_return_val_if_fail(origin, nullptr);
256
257 CString cstring = origin->securityOrigin->toString().utf8();
258 return cstring == "null" ? nullptr : g_strdup (cstring.data());
259}
260