1 /*
2 * Copyright (C) 2009 Collabora Ltd.
3 * Copyright (C) 2009 Igalia S.L.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "webkithittestresult.h"
23
24 #include "GOwnPtr.h"
25 #include "HitTestResult.h"
26 #include "KURL.h"
27 #include "WebKitDOMBinding.h"
28 #include "WebKitDOMNode.h"
29 #include "webkitenumtypes.h"
30 #include "webkitglobals.h"
31 #include "webkitglobalsprivate.h"
32 #include <glib/gi18n-lib.h>
33 #include <wtf/text/CString.h>
34
35 /**
36 * SECTION:webkithittestresult
37 * @short_description: The target of a mouse event
38 *
39 * This class holds context information about the coordinates
40 * specified by a GDK event.
41 */
42
43 G_DEFINE_TYPE(WebKitHitTestResult, webkit_hit_test_result, G_TYPE_OBJECT)
44
45 struct _WebKitHitTestResultPrivate {
46 guint context;
47 char* linkURI;
48 char* imageURI;
49 char* mediaURI;
50 WebKitDOMNode* innerNode;
51 };
52
53 enum {
54 PROP_0,
55
56 PROP_CONTEXT,
57 PROP_LINK_URI,
58 PROP_IMAGE_URI,
59 PROP_MEDIA_URI,
60 PROP_INNER_NODE
61 };
62
webkit_hit_test_result_finalize(GObject * object)63 static void webkit_hit_test_result_finalize(GObject* object)
64 {
65 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object);
66 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv;
67
68 g_free(priv->linkURI);
69 g_free(priv->imageURI);
70 g_free(priv->mediaURI);
71
72 G_OBJECT_CLASS(webkit_hit_test_result_parent_class)->finalize(object);
73 }
74
webkit_hit_test_result_dispose(GObject * object)75 static void webkit_hit_test_result_dispose(GObject* object)
76 {
77 g_object_unref(WEBKIT_HIT_TEST_RESULT(object)->priv->innerNode);
78
79 G_OBJECT_CLASS(webkit_hit_test_result_parent_class)->dispose(object);
80 }
81
webkit_hit_test_result_get_property(GObject * object,guint propertyID,GValue * value,GParamSpec * pspec)82 static void webkit_hit_test_result_get_property(GObject* object, guint propertyID, GValue* value, GParamSpec* pspec)
83 {
84 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object);
85 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv;
86
87 switch(propertyID) {
88 case PROP_CONTEXT:
89 g_value_set_flags(value, priv->context);
90 break;
91 case PROP_LINK_URI:
92 g_value_set_string(value, priv->linkURI);
93 break;
94 case PROP_IMAGE_URI:
95 g_value_set_string(value, priv->imageURI);
96 break;
97 case PROP_MEDIA_URI:
98 g_value_set_string(value, priv->mediaURI);
99 break;
100 case PROP_INNER_NODE:
101 g_value_set_object(value, priv->innerNode);
102 break;
103 default:
104 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
105 }
106 }
107
webkit_hit_test_result_set_property(GObject * object,guint propertyID,const GValue * value,GParamSpec * pspec)108 static void webkit_hit_test_result_set_property(GObject* object, guint propertyID, const GValue* value, GParamSpec* pspec)
109 {
110 WebKitHitTestResult* web_hit_test_result = WEBKIT_HIT_TEST_RESULT(object);
111 WebKitHitTestResultPrivate* priv = web_hit_test_result->priv;
112
113 switch(propertyID) {
114 case PROP_CONTEXT:
115 priv->context = g_value_get_flags(value);
116 break;
117 case PROP_LINK_URI:
118 g_free (priv->linkURI);
119 priv->linkURI = g_value_dup_string(value);
120 break;
121 case PROP_IMAGE_URI:
122 g_free (priv->imageURI);
123 priv->imageURI = g_value_dup_string(value);
124 break;
125 case PROP_MEDIA_URI:
126 g_free (priv->mediaURI);
127 priv->mediaURI = g_value_dup_string(value);
128 break;
129 case PROP_INNER_NODE:
130 priv->innerNode = static_cast<WebKitDOMNode*>(g_value_get_object(value));
131 break;
132 default:
133 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyID, pspec);
134 }
135 }
136
webkit_hit_test_result_class_init(WebKitHitTestResultClass * webHitTestResultClass)137 static void webkit_hit_test_result_class_init(WebKitHitTestResultClass* webHitTestResultClass)
138 {
139 GObjectClass* objectClass = G_OBJECT_CLASS(webHitTestResultClass);
140
141 objectClass->finalize = webkit_hit_test_result_finalize;
142 objectClass->dispose = webkit_hit_test_result_dispose;
143 objectClass->get_property = webkit_hit_test_result_get_property;
144 objectClass->set_property = webkit_hit_test_result_set_property;
145
146 webkitInit();
147
148 /**
149 * WebKitHitTestResult:context:
150 *
151 * Flags indicating the kind of target that received the event.
152 *
153 * Since: 1.1.15
154 */
155 g_object_class_install_property(objectClass, PROP_CONTEXT,
156 g_param_spec_flags("context",
157 _("Context"),
158 _("Flags indicating the kind of target that received the event."),
159 WEBKIT_TYPE_HIT_TEST_RESULT_CONTEXT,
160 WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT,
161 static_cast<GParamFlags>((WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY))));
162
163 /**
164 * WebKitHitTestResult:link-uri:
165 *
166 * The URI to which the target that received the event points, if any.
167 *
168 * Since: 1.1.15
169 */
170 g_object_class_install_property(objectClass, PROP_LINK_URI,
171 g_param_spec_string("link-uri",
172 _("Link URI"),
173 _("The URI to which the target that received the event points, if any."),
174 NULL,
175 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)));
176
177 /**
178 * WebKitHitTestResult:image-uri:
179 *
180 * The URI of the image that is part of the target that received the event, if any.
181 *
182 * Since: 1.1.15
183 */
184 g_object_class_install_property(objectClass, PROP_IMAGE_URI,
185 g_param_spec_string("image-uri",
186 _("Image URI"),
187 _("The URI of the image that is part of the target that received the event, if any."),
188 NULL,
189 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)));
190
191 /**
192 * WebKitHitTestResult:media-uri:
193 *
194 * The URI of the media that is part of the target that received the event, if any.
195 *
196 * Since: 1.1.15
197 */
198 g_object_class_install_property(objectClass, PROP_MEDIA_URI,
199 g_param_spec_string("media-uri",
200 _("Media URI"),
201 _("The URI of the media that is part of the target that received the event, if any."),
202 NULL,
203 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)));
204
205 /**
206 * WebKitHitTestResult:inner-node:
207 *
208 * The DOM node at the coordinates where the hit test
209 * happened. Keep in mind that the node might not be
210 * representative of the information given in the context
211 * property, since WebKit uses a series of heuristics to figure
212 * out that information. One common example is inner-node having
213 * the text node inside the anchor (<a>) tag; WebKit knows the
214 * whole context and will put WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK
215 * in the 'context' property, but the user might be confused by
216 * the lack of any link tag in 'inner-node'.
217 *
218 * Since: 1.3.2
219 */
220 g_object_class_install_property(objectClass, PROP_INNER_NODE,
221 g_param_spec_object("inner-node",
222 _("Inner node"),
223 _("The inner DOM node associated with the hit test result."),
224 WEBKIT_TYPE_DOM_NODE,
225 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
226
227 g_type_class_add_private(webHitTestResultClass, sizeof(WebKitHitTestResultPrivate));
228 }
229
webkit_hit_test_result_init(WebKitHitTestResult * web_hit_test_result)230 static void webkit_hit_test_result_init(WebKitHitTestResult* web_hit_test_result)
231 {
232 web_hit_test_result->priv = G_TYPE_INSTANCE_GET_PRIVATE(web_hit_test_result, WEBKIT_TYPE_HIT_TEST_RESULT, WebKitHitTestResultPrivate);
233 }
234
235 namespace WebKit {
236
kit(const WebCore::HitTestResult & result)237 WebKitHitTestResult* kit(const WebCore::HitTestResult& result)
238 {
239 guint context = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
240 GOwnPtr<char> linkURI(0);
241 GOwnPtr<char> imageURI(0);
242 GOwnPtr<char> mediaURI(0);
243 WebKitDOMNode* node = 0;
244
245 if (!result.absoluteLinkURL().isEmpty()) {
246 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
247 linkURI.set(g_strdup(result.absoluteLinkURL().string().utf8().data()));
248 }
249
250 if (!result.absoluteImageURL().isEmpty()) {
251 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
252 imageURI.set(g_strdup(result.absoluteImageURL().string().utf8().data()));
253 }
254
255 if (!result.absoluteMediaURL().isEmpty()) {
256 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
257 mediaURI.set(g_strdup(result.absoluteMediaURL().string().utf8().data()));
258 }
259
260 if (result.isSelected())
261 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
262
263 if (result.isContentEditable())
264 context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
265
266 if (result.innerNonSharedNode())
267 node = kit(result.innerNonSharedNode());
268
269 return WEBKIT_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_HIT_TEST_RESULT,
270 "link-uri", linkURI.get(),
271 "image-uri", imageURI.get(),
272 "media-uri", mediaURI.get(),
273 "context", context,
274 "inner-node", node,
275 NULL));
276 }
277
278 }
279