1/*
2 * This file is part of the WebKit open source project.
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 "WebKitDOMXPathResult.h"
22
23#include <WebCore/CSSImportRule.h>
24#include "DOMObjectCache.h"
25#include <WebCore/DOMException.h>
26#include <WebCore/Document.h>
27#include <WebCore/JSExecState.h>
28#include "WebKitDOMNodePrivate.h"
29#include "WebKitDOMPrivate.h"
30#include "WebKitDOMXPathResultPrivate.h"
31#include "ConvertToUTF8String.h"
32#include <wtf/GetPtr.h>
33#include <wtf/RefPtr.h>
34
35#define WEBKIT_DOM_XPATH_RESULT_GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE(obj, WEBKIT_DOM_TYPE_XPATH_RESULT, WebKitDOMXPathResultPrivate)
36
37typedef struct _WebKitDOMXPathResultPrivate {
38 RefPtr<WebCore::XPathResult> coreObject;
39} WebKitDOMXPathResultPrivate;
40
41G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
42
43namespace WebKit {
44
45WebKitDOMXPathResult* kit(WebCore::XPathResult* obj)
46{
47 if (!obj)
48 return 0;
49
50 if (gpointer ret = DOMObjectCache::get(obj))
51 return WEBKIT_DOM_XPATH_RESULT(ret);
52
53 return wrapXPathResult(obj);
54}
55
56WebCore::XPathResult* core(WebKitDOMXPathResult* request)
57{
58 return request ? static_cast<WebCore::XPathResult*>(WEBKIT_DOM_OBJECT(request)->coreObject) : 0;
59}
60
61WebKitDOMXPathResult* wrapXPathResult(WebCore::XPathResult* coreObject)
62{
63 ASSERT(coreObject);
64 return WEBKIT_DOM_XPATH_RESULT(g_object_new(WEBKIT_DOM_TYPE_XPATH_RESULT, "core-object", coreObject, nullptr));
65}
66
67} // namespace WebKit
68
69G_DEFINE_TYPE(WebKitDOMXPathResult, webkit_dom_xpath_result, WEBKIT_DOM_TYPE_OBJECT)
70
71enum {
72 DOM_XPATH_RESULT_PROP_0,
73 DOM_XPATH_RESULT_PROP_RESULT_TYPE,
74 DOM_XPATH_RESULT_PROP_NUMBER_VALUE,
75 DOM_XPATH_RESULT_PROP_STRING_VALUE,
76 DOM_XPATH_RESULT_PROP_BOOLEAN_VALUE,
77 DOM_XPATH_RESULT_PROP_SINGLE_NODE_VALUE,
78 DOM_XPATH_RESULT_PROP_INVALID_ITERATOR_STATE,
79 DOM_XPATH_RESULT_PROP_SNAPSHOT_LENGTH,
80};
81
82static void webkit_dom_xpath_result_finalize(GObject* object)
83{
84 WebKitDOMXPathResultPrivate* priv = WEBKIT_DOM_XPATH_RESULT_GET_PRIVATE(object);
85
86 WebKit::DOMObjectCache::forget(priv->coreObject.get());
87
88 priv->~WebKitDOMXPathResultPrivate();
89 G_OBJECT_CLASS(webkit_dom_xpath_result_parent_class)->finalize(object);
90}
91
92static void webkit_dom_xpath_result_get_property(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec)
93{
94 WebKitDOMXPathResult* self = WEBKIT_DOM_XPATH_RESULT(object);
95
96 switch (propertyId) {
97 case DOM_XPATH_RESULT_PROP_RESULT_TYPE:
98 g_value_set_uint(value, webkit_dom_xpath_result_get_result_type(self));
99 break;
100 case DOM_XPATH_RESULT_PROP_NUMBER_VALUE:
101 g_value_set_double(value, webkit_dom_xpath_result_get_number_value(self, nullptr));
102 break;
103 case DOM_XPATH_RESULT_PROP_STRING_VALUE:
104 g_value_take_string(value, webkit_dom_xpath_result_get_string_value(self, nullptr));
105 break;
106 case DOM_XPATH_RESULT_PROP_BOOLEAN_VALUE:
107 g_value_set_boolean(value, webkit_dom_xpath_result_get_boolean_value(self, nullptr));
108 break;
109 case DOM_XPATH_RESULT_PROP_SINGLE_NODE_VALUE:
110 g_value_set_object(value, webkit_dom_xpath_result_get_single_node_value(self, nullptr));
111 break;
112 case DOM_XPATH_RESULT_PROP_INVALID_ITERATOR_STATE:
113 g_value_set_boolean(value, webkit_dom_xpath_result_get_invalid_iterator_state(self));
114 break;
115 case DOM_XPATH_RESULT_PROP_SNAPSHOT_LENGTH:
116 g_value_set_ulong(value, webkit_dom_xpath_result_get_snapshot_length(self, nullptr));
117 break;
118 default:
119 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec);
120 break;
121 }
122}
123
124static GObject* webkit_dom_xpath_result_constructor(GType type, guint constructPropertiesCount, GObjectConstructParam* constructProperties)
125{
126 GObject* object = G_OBJECT_CLASS(webkit_dom_xpath_result_parent_class)->constructor(type, constructPropertiesCount, constructProperties);
127
128 WebKitDOMXPathResultPrivate* priv = WEBKIT_DOM_XPATH_RESULT_GET_PRIVATE(object);
129 priv->coreObject = static_cast<WebCore::XPathResult*>(WEBKIT_DOM_OBJECT(object)->coreObject);
130 WebKit::DOMObjectCache::put(priv->coreObject.get(), object);
131
132 return object;
133}
134
135static void webkit_dom_xpath_result_class_init(WebKitDOMXPathResultClass* requestClass)
136{
137 GObjectClass* gobjectClass = G_OBJECT_CLASS(requestClass);
138 g_type_class_add_private(gobjectClass, sizeof(WebKitDOMXPathResultPrivate));
139 gobjectClass->constructor = webkit_dom_xpath_result_constructor;
140 gobjectClass->finalize = webkit_dom_xpath_result_finalize;
141 gobjectClass->get_property = webkit_dom_xpath_result_get_property;
142
143 g_object_class_install_property(
144 gobjectClass,
145 DOM_XPATH_RESULT_PROP_RESULT_TYPE,
146 g_param_spec_uint(
147 "result-type",
148 "XPathResult:result-type",
149 "read-only gushort XPathResult:result-type",
150 0, G_MAXUINT, 0,
151 WEBKIT_PARAM_READABLE));
152
153 g_object_class_install_property(
154 gobjectClass,
155 DOM_XPATH_RESULT_PROP_NUMBER_VALUE,
156 g_param_spec_double(
157 "number-value",
158 "XPathResult:number-value",
159 "read-only gdouble XPathResult:number-value",
160 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
161 WEBKIT_PARAM_READABLE));
162
163 g_object_class_install_property(
164 gobjectClass,
165 DOM_XPATH_RESULT_PROP_STRING_VALUE,
166 g_param_spec_string(
167 "string-value",
168 "XPathResult:string-value",
169 "read-only gchar* XPathResult:string-value",
170 "",
171 WEBKIT_PARAM_READABLE));
172
173 g_object_class_install_property(
174 gobjectClass,
175 DOM_XPATH_RESULT_PROP_BOOLEAN_VALUE,
176 g_param_spec_boolean(
177 "boolean-value",
178 "XPathResult:boolean-value",
179 "read-only gboolean XPathResult:boolean-value",
180 FALSE,
181 WEBKIT_PARAM_READABLE));
182
183 g_object_class_install_property(
184 gobjectClass,
185 DOM_XPATH_RESULT_PROP_SINGLE_NODE_VALUE,
186 g_param_spec_object(
187 "single-node-value",
188 "XPathResult:single-node-value",
189 "read-only WebKitDOMNode* XPathResult:single-node-value",
190 WEBKIT_DOM_TYPE_NODE,
191 WEBKIT_PARAM_READABLE));
192
193 g_object_class_install_property(
194 gobjectClass,
195 DOM_XPATH_RESULT_PROP_INVALID_ITERATOR_STATE,
196 g_param_spec_boolean(
197 "invalid-iterator-state",
198 "XPathResult:invalid-iterator-state",
199 "read-only gboolean XPathResult:invalid-iterator-state",
200 FALSE,
201 WEBKIT_PARAM_READABLE));
202
203 g_object_class_install_property(
204 gobjectClass,
205 DOM_XPATH_RESULT_PROP_SNAPSHOT_LENGTH,
206 g_param_spec_ulong(
207 "snapshot-length",
208 "XPathResult:snapshot-length",
209 "read-only gulong XPathResult:snapshot-length",
210 0, G_MAXULONG, 0,
211 WEBKIT_PARAM_READABLE));
212
213}
214
215static void webkit_dom_xpath_result_init(WebKitDOMXPathResult* request)
216{
217 WebKitDOMXPathResultPrivate* priv = WEBKIT_DOM_XPATH_RESULT_GET_PRIVATE(request);
218 new (priv) WebKitDOMXPathResultPrivate();
219}
220
221WebKitDOMNode* webkit_dom_xpath_result_iterate_next(WebKitDOMXPathResult* self, GError** error)
222{
223 WebCore::JSMainThreadNullState state;
224 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
225 g_return_val_if_fail(!error || !*error, 0);
226 WebCore::XPathResult* item = WebKit::core(self);
227 auto result = item->iterateNext();
228 if (result.hasException()) {
229 auto description = WebCore::DOMException::description(result.releaseException().code());
230 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
231 return nullptr;
232 }
233 return WebKit::kit(result.releaseReturnValue());
234}
235
236WebKitDOMNode* webkit_dom_xpath_result_snapshot_item(WebKitDOMXPathResult* self, gulong index, GError** error)
237{
238 WebCore::JSMainThreadNullState state;
239 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
240 g_return_val_if_fail(!error || !*error, 0);
241 WebCore::XPathResult* item = WebKit::core(self);
242 auto result = item->snapshotItem(index);
243 if (result.hasException()) {
244 auto description = WebCore::DOMException::description(result.releaseException().code());
245 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
246 return nullptr;
247 }
248 return WebKit::kit(result.releaseReturnValue());
249}
250
251gushort webkit_dom_xpath_result_get_result_type(WebKitDOMXPathResult* self)
252{
253 WebCore::JSMainThreadNullState state;
254 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
255 WebCore::XPathResult* item = WebKit::core(self);
256 gushort result = item->resultType();
257 return result;
258}
259
260gdouble webkit_dom_xpath_result_get_number_value(WebKitDOMXPathResult* self, GError** error)
261{
262 WebCore::JSMainThreadNullState state;
263 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
264 g_return_val_if_fail(!error || !*error, 0);
265 WebCore::XPathResult* item = WebKit::core(self);
266 auto result = item->numberValue();
267 if (result.hasException()) {
268 auto description = WebCore::DOMException::description(result.releaseException().code());
269 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
270 return 0;
271 }
272 return result.releaseReturnValue();
273}
274
275gchar* webkit_dom_xpath_result_get_string_value(WebKitDOMXPathResult* self, GError** error)
276{
277 WebCore::JSMainThreadNullState state;
278 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
279 g_return_val_if_fail(!error || !*error, 0);
280 WebCore::XPathResult* item = WebKit::core(self);
281 auto result = item->stringValue();
282 if (result.hasException())
283 return nullptr;
284 return convertToUTF8String(result.releaseReturnValue());
285}
286
287gboolean webkit_dom_xpath_result_get_boolean_value(WebKitDOMXPathResult* self, GError** error)
288{
289 WebCore::JSMainThreadNullState state;
290 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), FALSE);
291 g_return_val_if_fail(!error || !*error, FALSE);
292 WebCore::XPathResult* item = WebKit::core(self);
293 auto result = item->booleanValue();
294 if (result.hasException()) {
295 auto description = WebCore::DOMException::description(result.releaseException().code());
296 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
297 return false;
298 }
299 return result.releaseReturnValue();
300}
301
302WebKitDOMNode* webkit_dom_xpath_result_get_single_node_value(WebKitDOMXPathResult* self, GError** error)
303{
304 WebCore::JSMainThreadNullState state;
305 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
306 g_return_val_if_fail(!error || !*error, 0);
307 WebCore::XPathResult* item = WebKit::core(self);
308 auto result = item->singleNodeValue();
309 if (result.hasException()) {
310 auto description = WebCore::DOMException::description(result.releaseException().code());
311 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
312 return nullptr;
313 }
314 return WebKit::kit(result.releaseReturnValue());
315}
316
317gboolean webkit_dom_xpath_result_get_invalid_iterator_state(WebKitDOMXPathResult* self)
318{
319 WebCore::JSMainThreadNullState state;
320 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), FALSE);
321 WebCore::XPathResult* item = WebKit::core(self);
322 gboolean result = item->invalidIteratorState();
323 return result;
324}
325
326gulong webkit_dom_xpath_result_get_snapshot_length(WebKitDOMXPathResult* self, GError** error)
327{
328 WebCore::JSMainThreadNullState state;
329 g_return_val_if_fail(WEBKIT_DOM_IS_XPATH_RESULT(self), 0);
330 g_return_val_if_fail(!error || !*error, 0);
331 WebCore::XPathResult* item = WebKit::core(self);
332 auto result = item->snapshotLength();
333 if (result.hasException()) {
334 auto description = WebCore::DOMException::description(result.releaseException().code());
335 g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.legacyCode, description.name);
336 }
337 return result.releaseReturnValue();
338}
339
340G_GNUC_END_IGNORE_DEPRECATIONS;
341