1/*
2 * Copyright (C) 2018 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 "WebKitDOMNode.h"
22
23#include "DOMObjectCache.h"
24#include "WebKitDOMNodePrivate.h"
25#include "WebKitDOMPrivate.h"
26#include <WebCore/JSNode.h>
27#include <jsc/JSCContextPrivate.h>
28#include <jsc/JSCValuePrivate.h>
29#include <wtf/RefPtr.h>
30
31#if PLATFORM(GTK)
32#include "WebKitDOMEventTarget.h"
33#endif
34
35#define WEBKIT_DOM_NODE_GET_PRIVATE(obj) G_TYPE_INSTANCE_GET_PRIVATE(obj, WEBKIT_DOM_TYPE_NODE, WebKitDOMNodePrivate)
36
37typedef struct _WebKitDOMNodePrivate {
38 ~_WebKitDOMNodePrivate()
39 {
40 WebKit::DOMObjectCache::forget(coreObject.get());
41 }
42
43 RefPtr<WebCore::Node> coreObject;
44} WebKitDOMNodePrivate;
45
46namespace WebKit {
47
48WebKitDOMNode* kit(WebCore::Node* obj)
49{
50 if (!obj)
51 return nullptr;
52
53 if (gpointer ret = DOMObjectCache::get(obj))
54 return WEBKIT_DOM_NODE(ret);
55
56 return wrap(obj);
57}
58
59WebCore::Node* core(WebKitDOMNode* node)
60{
61 return node ? webkitDOMNodeGetCoreObject(node) : nullptr;
62}
63
64WebKitDOMNode* wrapNode(WebCore::Node* coreObject)
65{
66 ASSERT(coreObject);
67#if PLATFORM(GTK)
68 return WEBKIT_DOM_NODE(g_object_new(WEBKIT_DOM_TYPE_NODE, "core-object", coreObject, nullptr));
69#else
70 auto* node = WEBKIT_DOM_NODE(g_object_new(WEBKIT_DOM_TYPE_NODE, nullptr));
71 webkitDOMNodeSetCoreObject(node, coreObject);
72 return node;
73#endif
74}
75
76} // namespace WebKit
77
78#if PLATFORM(GTK)
79G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
80G_DEFINE_TYPE_WITH_CODE(WebKitDOMNode, webkit_dom_node, WEBKIT_DOM_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(WEBKIT_DOM_TYPE_EVENT_TARGET, webkitDOMNodeDOMEventTargetInit))
81G_GNUC_END_IGNORE_DEPRECATIONS;
82#else
83WEBKIT_DEFINE_TYPE(WebKitDOMNode, webkit_dom_node, WEBKIT_DOM_TYPE_OBJECT)
84#endif
85
86#if PLATFORM(GTK)
87static GObject* webkitDOMNodeConstructor(GType type, guint constructPropertiesCount, GObjectConstructParam* constructProperties)
88{
89 GObject* object = G_OBJECT_CLASS(webkit_dom_node_parent_class)->constructor(type, constructPropertiesCount, constructProperties);
90
91 webkitDOMNodeSetCoreObject(WEBKIT_DOM_NODE(object), static_cast<WebCore::Node*>(WEBKIT_DOM_OBJECT(object)->coreObject));
92
93 return object;
94}
95
96static void webkitDOMNodeFinalize(GObject* object)
97{
98 WebKitDOMNode* node = WEBKIT_DOM_NODE(object);
99
100 WebKitDOMNodePrivate* priv = WEBKIT_DOM_NODE_GET_PRIVATE(node);
101 priv->~WebKitDOMNodePrivate();
102
103 G_OBJECT_CLASS(webkit_dom_node_parent_class)->finalize(object);
104}
105
106static void webkit_dom_node_init(WebKitDOMNode* node)
107{
108 WebKitDOMNodePrivate* priv = WEBKIT_DOM_NODE_GET_PRIVATE(node);
109 new (priv) WebKitDOMNodePrivate();
110}
111#endif
112
113static void webkit_dom_node_class_init(WebKitDOMNodeClass* nodeClass)
114{
115#if PLATFORM(GTK)
116 GObjectClass* gobjectClass = G_OBJECT_CLASS(nodeClass);
117 g_type_class_add_private(gobjectClass, sizeof(WebKitDOMNodePrivate));
118 gobjectClass->constructor = webkitDOMNodeConstructor;
119 gobjectClass->finalize = webkitDOMNodeFinalize;
120 webkitDOMNodeInstallProperties(gobjectClass);
121#endif
122}
123
124void webkitDOMNodeSetCoreObject(WebKitDOMNode* node, WebCore::Node* coreObject)
125{
126 WebKitDOMNodePrivate* priv = WEBKIT_DOM_NODE_GET_PRIVATE(node);
127 priv->coreObject = coreObject;
128 WebKit::DOMObjectCache::put(coreObject, node);
129}
130
131WebCore::Node* webkitDOMNodeGetCoreObject(WebKitDOMNode* node)
132{
133 WebKitDOMNodePrivate* priv = WEBKIT_DOM_NODE_GET_PRIVATE(node);
134 return priv->coreObject.get();
135}
136
137/**
138 * webkit_dom_node_for_js_value:
139 * @value: a #JSCValue
140 *
141 * Get the #WebKitDOMNode for the DOM node referenced by @value.
142 *
143 * Returns: (transfer none): a #WebKitDOMNode, or %NULL if @value doesn't reference a DOM node.
144 *
145 * Since: 2.22
146 */
147WebKitDOMNode* webkit_dom_node_for_js_value(JSCValue* value)
148{
149 g_return_val_if_fail(JSC_IS_VALUE(value), nullptr);
150 g_return_val_if_fail(jsc_value_is_object(value), nullptr);
151
152 auto* jsObject = JSValueToObject(jscContextGetJSContext(jsc_value_get_context(value)), jscValueGetJSValue(value), nullptr);
153 return jsObject ? WebKit::kit(WebCore::JSNode::toWrapped(*toJS(jsObject)->vm(), toJS(jsObject))) : nullptr;
154}
155