1 /*
2 Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3
4 This file is part of the KDE project
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23
24 #if ENABLE(SVG)
25 #include "SVGElementInstance.h"
26
27 #include "ContainerNodeAlgorithms.h"
28 #include "Document.h"
29 #include "Event.h"
30 #include "EventException.h"
31 #include "EventListener.h"
32 #include "EventNames.h"
33 #include "FrameView.h"
34 #include "SVGElementInstanceList.h"
35 #include "SVGUseElement.h"
36
37 #include <wtf/RefCountedLeakCounter.h>
38
39 #if USE(JSC)
40 #include "GCController.h"
41 #endif
42
43 namespace WebCore {
44
45 #ifndef NDEBUG
46 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
47 #endif
48
SVGElementInstance(SVGUseElement * useElement,SVGElement * originalElement)49 SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement)
50 : m_needsUpdate(false)
51 , m_useElement(useElement)
52 , m_element(originalElement)
53 , m_previousSibling(0)
54 , m_nextSibling(0)
55 , m_firstChild(0)
56 , m_lastChild(0)
57 {
58 ASSERT(m_useElement);
59 ASSERT(m_element);
60
61 // Register as instance for passed element.
62 m_element->mapInstanceToElement(this);
63
64 #ifndef NDEBUG
65 instanceCounter.increment();
66 #endif
67 }
68
~SVGElementInstance()69 SVGElementInstance::~SVGElementInstance()
70 {
71 #ifndef NDEBUG
72 instanceCounter.decrement();
73 #endif
74
75 // Deregister as instance for passed element.
76 m_element->removeInstanceMapping(this);
77
78 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
79 }
80
childNodes()81 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
82 {
83 return SVGElementInstanceList::create(this);
84 }
85
setShadowTreeElement(SVGElement * element)86 void SVGElementInstance::setShadowTreeElement(SVGElement* element)
87 {
88 ASSERT(element);
89 m_shadowTreeElement = element;
90 }
91
forgetWrapper()92 void SVGElementInstance::forgetWrapper()
93 {
94 #if USE(JSC)
95 // FIXME: This is fragile, as discussed with Sam. Need to find a better solution.
96 // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;".
97 // We still have to recreate this wrapper somehow. The gc collection below, won't catch it.
98
99 // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects
100 // are still holding RefPtrs of SVGElementInstance objects, which prevent us to
101 // be deleted (and the shadow tree is not destructed as well). Force JS GC.
102 gcController().garbageCollectNow();
103 #endif
104 }
105
appendChild(PassRefPtr<SVGElementInstance> child)106 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
107 {
108 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
109 }
110
invalidateAllInstancesOfElement(SVGElement * element)111 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
112 {
113 if (!element)
114 return;
115
116 HashSet<SVGElementInstance*> set = element->instancesForElement();
117 if (set.isEmpty())
118 return;
119
120 // Find all use elements referencing the instances - ask them _once_ to rebuild.
121 HashSet<SVGElementInstance*>::const_iterator it = set.begin();
122 const HashSet<SVGElementInstance*>::const_iterator end = set.end();
123
124 for (; it != end; ++it)
125 (*it)->setNeedsUpdate(true);
126 }
127
setNeedsUpdate(bool value)128 void SVGElementInstance::setNeedsUpdate(bool value)
129 {
130 m_needsUpdate = value;
131
132 if (m_needsUpdate)
133 correspondingUseElement()->setNeedsStyleRecalc();
134 }
135
scriptExecutionContext() const136 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
137 {
138 if (SVGElement* element = correspondingElement())
139 return element->document();
140 return 0;
141 }
142
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)143 void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
144 {
145 if (SVGElement* element = correspondingElement())
146 element->addEventListener(eventType, listener, useCapture);
147 }
148
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)149 void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
150 {
151 if (SVGElement* element = correspondingElement())
152 element->removeEventListener(eventType, listener, useCapture);
153 }
154
dispatchEvent(PassRefPtr<Event> e,ExceptionCode & ec)155 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec)
156 {
157 RefPtr<Event> evt(e);
158 ASSERT(!eventDispatchForbidden());
159 if (!evt || evt->type().isEmpty()) {
160 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
161 return false;
162 }
163
164 // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()!
165 SVGElement* element = shadowTreeElement();
166 if (!element)
167 return false;
168
169 evt->setTarget(this);
170
171 RefPtr<FrameView> view = element->document()->view();
172 return element->dispatchGenericEvent(evt.release());
173 }
174
onabort() const175 EventListener* SVGElementInstance::onabort() const
176 {
177 return correspondingElement()->getAttributeEventListener(eventNames().abortEvent);
178 }
179
setOnabort(PassRefPtr<EventListener> eventListener)180 void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener)
181 {
182 correspondingElement()->setAttributeEventListener(eventNames().abortEvent, eventListener);
183 }
184
onblur() const185 EventListener* SVGElementInstance::onblur() const
186 {
187 return correspondingElement()->getAttributeEventListener(eventNames().blurEvent);
188 }
189
setOnblur(PassRefPtr<EventListener> eventListener)190 void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener)
191 {
192 correspondingElement()->setAttributeEventListener(eventNames().blurEvent, eventListener);
193 }
194
onchange() const195 EventListener* SVGElementInstance::onchange() const
196 {
197 return correspondingElement()->getAttributeEventListener(eventNames().changeEvent);
198 }
199
setOnchange(PassRefPtr<EventListener> eventListener)200 void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener)
201 {
202 correspondingElement()->setAttributeEventListener(eventNames().changeEvent, eventListener);
203 }
204
onclick() const205 EventListener* SVGElementInstance::onclick() const
206 {
207 return correspondingElement()->getAttributeEventListener(eventNames().clickEvent);
208 }
209
setOnclick(PassRefPtr<EventListener> eventListener)210 void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener)
211 {
212 correspondingElement()->setAttributeEventListener(eventNames().clickEvent, eventListener);
213 }
214
oncontextmenu() const215 EventListener* SVGElementInstance::oncontextmenu() const
216 {
217 return correspondingElement()->getAttributeEventListener(eventNames().contextmenuEvent);
218 }
219
setOncontextmenu(PassRefPtr<EventListener> eventListener)220 void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener)
221 {
222 correspondingElement()->setAttributeEventListener(eventNames().contextmenuEvent, eventListener);
223 }
224
ondblclick() const225 EventListener* SVGElementInstance::ondblclick() const
226 {
227 return correspondingElement()->getAttributeEventListener(eventNames().dblclickEvent);
228 }
229
setOndblclick(PassRefPtr<EventListener> eventListener)230 void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener)
231 {
232 correspondingElement()->setAttributeEventListener(eventNames().dblclickEvent, eventListener);
233 }
234
onerror() const235 EventListener* SVGElementInstance::onerror() const
236 {
237 return correspondingElement()->getAttributeEventListener(eventNames().errorEvent);
238 }
239
setOnerror(PassRefPtr<EventListener> eventListener)240 void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener)
241 {
242 correspondingElement()->setAttributeEventListener(eventNames().errorEvent, eventListener);
243 }
244
onfocus() const245 EventListener* SVGElementInstance::onfocus() const
246 {
247 return correspondingElement()->getAttributeEventListener(eventNames().focusEvent);
248 }
249
setOnfocus(PassRefPtr<EventListener> eventListener)250 void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener)
251 {
252 correspondingElement()->setAttributeEventListener(eventNames().focusEvent, eventListener);
253 }
254
oninput() const255 EventListener* SVGElementInstance::oninput() const
256 {
257 return correspondingElement()->getAttributeEventListener(eventNames().inputEvent);
258 }
259
setOninput(PassRefPtr<EventListener> eventListener)260 void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener)
261 {
262 correspondingElement()->setAttributeEventListener(eventNames().inputEvent, eventListener);
263 }
264
onkeydown() const265 EventListener* SVGElementInstance::onkeydown() const
266 {
267 return correspondingElement()->getAttributeEventListener(eventNames().keydownEvent);
268 }
269
setOnkeydown(PassRefPtr<EventListener> eventListener)270 void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener)
271 {
272 correspondingElement()->setAttributeEventListener(eventNames().keydownEvent, eventListener);
273 }
274
onkeypress() const275 EventListener* SVGElementInstance::onkeypress() const
276 {
277 return correspondingElement()->getAttributeEventListener(eventNames().keypressEvent);
278 }
279
setOnkeypress(PassRefPtr<EventListener> eventListener)280 void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener)
281 {
282 correspondingElement()->setAttributeEventListener(eventNames().keypressEvent, eventListener);
283 }
284
onkeyup() const285 EventListener* SVGElementInstance::onkeyup() const
286 {
287 return correspondingElement()->getAttributeEventListener(eventNames().keyupEvent);
288 }
289
setOnkeyup(PassRefPtr<EventListener> eventListener)290 void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener)
291 {
292 correspondingElement()->setAttributeEventListener(eventNames().keyupEvent, eventListener);
293 }
294
onload() const295 EventListener* SVGElementInstance::onload() const
296 {
297 return correspondingElement()->getAttributeEventListener(eventNames().loadEvent);
298 }
299
setOnload(PassRefPtr<EventListener> eventListener)300 void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener)
301 {
302 correspondingElement()->setAttributeEventListener(eventNames().loadEvent, eventListener);
303 }
304
onmousedown() const305 EventListener* SVGElementInstance::onmousedown() const
306 {
307 return correspondingElement()->getAttributeEventListener(eventNames().mousedownEvent);
308 }
309
setOnmousedown(PassRefPtr<EventListener> eventListener)310 void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener)
311 {
312 correspondingElement()->setAttributeEventListener(eventNames().mousedownEvent, eventListener);
313 }
314
onmousemove() const315 EventListener* SVGElementInstance::onmousemove() const
316 {
317 return correspondingElement()->getAttributeEventListener(eventNames().mousemoveEvent);
318 }
319
setOnmousemove(PassRefPtr<EventListener> eventListener)320 void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener)
321 {
322 correspondingElement()->setAttributeEventListener(eventNames().mousemoveEvent, eventListener);
323 }
324
onmouseout() const325 EventListener* SVGElementInstance::onmouseout() const
326 {
327 return correspondingElement()->getAttributeEventListener(eventNames().mouseoutEvent);
328 }
329
setOnmouseout(PassRefPtr<EventListener> eventListener)330 void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener)
331 {
332 correspondingElement()->setAttributeEventListener(eventNames().mouseoutEvent, eventListener);
333 }
334
onmouseover() const335 EventListener* SVGElementInstance::onmouseover() const
336 {
337 return correspondingElement()->getAttributeEventListener(eventNames().mouseoverEvent);
338 }
339
setOnmouseover(PassRefPtr<EventListener> eventListener)340 void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener)
341 {
342 correspondingElement()->setAttributeEventListener(eventNames().mouseoverEvent, eventListener);
343 }
344
onmouseup() const345 EventListener* SVGElementInstance::onmouseup() const
346 {
347 return correspondingElement()->getAttributeEventListener(eventNames().mouseupEvent);
348 }
349
setOnmouseup(PassRefPtr<EventListener> eventListener)350 void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener)
351 {
352 correspondingElement()->setAttributeEventListener(eventNames().mouseupEvent, eventListener);
353 }
354
onmousewheel() const355 EventListener* SVGElementInstance::onmousewheel() const
356 {
357 return correspondingElement()->getAttributeEventListener(eventNames().mousewheelEvent);
358 }
359
setOnmousewheel(PassRefPtr<EventListener> eventListener)360 void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener)
361 {
362 correspondingElement()->setAttributeEventListener(eventNames().mousewheelEvent, eventListener);
363 }
364
onbeforecut() const365 EventListener* SVGElementInstance::onbeforecut() const
366 {
367 return correspondingElement()->getAttributeEventListener(eventNames().beforecutEvent);
368 }
369
setOnbeforecut(PassRefPtr<EventListener> eventListener)370 void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener)
371 {
372 correspondingElement()->setAttributeEventListener(eventNames().beforecutEvent, eventListener);
373 }
374
oncut() const375 EventListener* SVGElementInstance::oncut() const
376 {
377 return correspondingElement()->getAttributeEventListener(eventNames().cutEvent);
378 }
379
setOncut(PassRefPtr<EventListener> eventListener)380 void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener)
381 {
382 correspondingElement()->setAttributeEventListener(eventNames().cutEvent, eventListener);
383 }
384
onbeforecopy() const385 EventListener* SVGElementInstance::onbeforecopy() const
386 {
387 return correspondingElement()->getAttributeEventListener(eventNames().beforecopyEvent);
388 }
389
setOnbeforecopy(PassRefPtr<EventListener> eventListener)390 void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener)
391 {
392 correspondingElement()->setAttributeEventListener(eventNames().beforecopyEvent, eventListener);
393 }
394
oncopy() const395 EventListener* SVGElementInstance::oncopy() const
396 {
397 return correspondingElement()->getAttributeEventListener(eventNames().copyEvent);
398 }
399
setOncopy(PassRefPtr<EventListener> eventListener)400 void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener)
401 {
402 correspondingElement()->setAttributeEventListener(eventNames().copyEvent, eventListener);
403 }
404
onbeforepaste() const405 EventListener* SVGElementInstance::onbeforepaste() const
406 {
407 return correspondingElement()->getAttributeEventListener(eventNames().beforepasteEvent);
408 }
409
setOnbeforepaste(PassRefPtr<EventListener> eventListener)410 void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener)
411 {
412 correspondingElement()->setAttributeEventListener(eventNames().beforepasteEvent, eventListener);
413 }
414
onpaste() const415 EventListener* SVGElementInstance::onpaste() const
416 {
417 return correspondingElement()->getAttributeEventListener(eventNames().pasteEvent);
418 }
419
setOnpaste(PassRefPtr<EventListener> eventListener)420 void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener)
421 {
422 correspondingElement()->setAttributeEventListener(eventNames().pasteEvent, eventListener);
423 }
424
ondragenter() const425 EventListener* SVGElementInstance::ondragenter() const
426 {
427 return correspondingElement()->getAttributeEventListener(eventNames().dragenterEvent);
428 }
429
setOndragenter(PassRefPtr<EventListener> eventListener)430 void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener)
431 {
432 correspondingElement()->setAttributeEventListener(eventNames().dragenterEvent, eventListener);
433 }
434
ondragover() const435 EventListener* SVGElementInstance::ondragover() const
436 {
437 return correspondingElement()->getAttributeEventListener(eventNames().dragoverEvent);
438 }
439
setOndragover(PassRefPtr<EventListener> eventListener)440 void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener)
441 {
442 correspondingElement()->setAttributeEventListener(eventNames().dragoverEvent, eventListener);
443 }
444
ondragleave() const445 EventListener* SVGElementInstance::ondragleave() const
446 {
447 return correspondingElement()->getAttributeEventListener(eventNames().dragleaveEvent);
448 }
449
setOndragleave(PassRefPtr<EventListener> eventListener)450 void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener)
451 {
452 correspondingElement()->setAttributeEventListener(eventNames().dragleaveEvent, eventListener);
453 }
454
ondrop() const455 EventListener* SVGElementInstance::ondrop() const
456 {
457 return correspondingElement()->getAttributeEventListener(eventNames().dropEvent);
458 }
459
setOndrop(PassRefPtr<EventListener> eventListener)460 void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener)
461 {
462 correspondingElement()->setAttributeEventListener(eventNames().dropEvent, eventListener);
463 }
464
ondragstart() const465 EventListener* SVGElementInstance::ondragstart() const
466 {
467 return correspondingElement()->getAttributeEventListener(eventNames().dragstartEvent);
468 }
469
setOndragstart(PassRefPtr<EventListener> eventListener)470 void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener)
471 {
472 correspondingElement()->setAttributeEventListener(eventNames().dragstartEvent, eventListener);
473 }
474
ondrag() const475 EventListener* SVGElementInstance::ondrag() const
476 {
477 return correspondingElement()->getAttributeEventListener(eventNames().dragEvent);
478 }
479
setOndrag(PassRefPtr<EventListener> eventListener)480 void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener)
481 {
482 correspondingElement()->setAttributeEventListener(eventNames().dragEvent, eventListener);
483 }
484
ondragend() const485 EventListener* SVGElementInstance::ondragend() const
486 {
487 return correspondingElement()->getAttributeEventListener(eventNames().dragendEvent);
488 }
489
setOndragend(PassRefPtr<EventListener> eventListener)490 void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener)
491 {
492 correspondingElement()->setAttributeEventListener(eventNames().dragendEvent, eventListener);
493 }
494
onreset() const495 EventListener* SVGElementInstance::onreset() const
496 {
497 return correspondingElement()->getAttributeEventListener(eventNames().resetEvent);
498 }
499
setOnreset(PassRefPtr<EventListener> eventListener)500 void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener)
501 {
502 correspondingElement()->setAttributeEventListener(eventNames().resetEvent, eventListener);
503 }
504
onresize() const505 EventListener* SVGElementInstance::onresize() const
506 {
507 return correspondingElement()->getAttributeEventListener(eventNames().resizeEvent);
508 }
509
setOnresize(PassRefPtr<EventListener> eventListener)510 void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener)
511 {
512 correspondingElement()->setAttributeEventListener(eventNames().resizeEvent, eventListener);
513 }
514
onscroll() const515 EventListener* SVGElementInstance::onscroll() const
516 {
517 return correspondingElement()->getAttributeEventListener(eventNames().scrollEvent);
518 }
519
setOnscroll(PassRefPtr<EventListener> eventListener)520 void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener)
521 {
522 correspondingElement()->setAttributeEventListener(eventNames().scrollEvent, eventListener);
523 }
524
onsearch() const525 EventListener* SVGElementInstance::onsearch() const
526 {
527 return correspondingElement()->getAttributeEventListener(eventNames().searchEvent);
528 }
529
setOnsearch(PassRefPtr<EventListener> eventListener)530 void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener)
531 {
532 correspondingElement()->setAttributeEventListener(eventNames().searchEvent, eventListener);
533 }
534
onselect() const535 EventListener* SVGElementInstance::onselect() const
536 {
537 return correspondingElement()->getAttributeEventListener(eventNames().selectEvent);
538 }
539
setOnselect(PassRefPtr<EventListener> eventListener)540 void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener)
541 {
542 correspondingElement()->setAttributeEventListener(eventNames().selectEvent, eventListener);
543 }
544
onselectstart() const545 EventListener* SVGElementInstance::onselectstart() const
546 {
547 return correspondingElement()->getAttributeEventListener(eventNames().selectstartEvent);
548 }
549
setOnselectstart(PassRefPtr<EventListener> eventListener)550 void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener)
551 {
552 correspondingElement()->setAttributeEventListener(eventNames().selectstartEvent, eventListener);
553 }
554
onsubmit() const555 EventListener* SVGElementInstance::onsubmit() const
556 {
557 return correspondingElement()->getAttributeEventListener(eventNames().submitEvent);
558 }
559
setOnsubmit(PassRefPtr<EventListener> eventListener)560 void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener)
561 {
562 correspondingElement()->setAttributeEventListener(eventNames().submitEvent, eventListener);
563 }
564
onunload() const565 EventListener* SVGElementInstance::onunload() const
566 {
567 return correspondingElement()->getAttributeEventListener(eventNames().unloadEvent);
568 }
569
setOnunload(PassRefPtr<EventListener> eventListener)570 void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener)
571 {
572 correspondingElement()->setAttributeEventListener(eventNames().unloadEvent, eventListener);
573 }
574
575 }
576
577 #endif // ENABLE(SVG)
578