1 /* 2 * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 4 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 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 #include "core/svg/SVGElementInstance.h" 25 26 #include "core/dom/ContainerNodeAlgorithms.h" 27 #include "core/dom/Event.h" 28 #include "core/dom/EventListener.h" 29 #include "core/dom/EventNames.h" 30 #include "core/svg/SVGElement.h" 31 #include "core/svg/SVGElementInstanceList.h" 32 #include "core/svg/SVGUseElement.h" 33 34 #include "wtf/RefCountedLeakCounter.h" 35 36 namespace WebCore { 37 38 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, instanceCounter, ("WebCoreSVGElementInstance")); 39 40 // EventTarget API 41 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), abort); 42 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), blur); 43 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), change); 44 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), click); 45 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), contextmenu); 46 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dblclick); 47 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), error); 48 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), focus); 49 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), input); 50 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), keydown); 51 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), keypress); 52 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), keyup); 53 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), load); 54 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mousedown); 55 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mouseenter); 56 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mouseleave); 57 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mousemove); 58 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mouseout); 59 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mouseover); 60 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mouseup); 61 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), mousewheel); 62 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), beforecut); 63 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), cut); 64 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), beforecopy); 65 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), copy); 66 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), beforepaste); 67 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), paste); 68 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dragenter); 69 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dragover); 70 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dragleave); 71 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), drop); 72 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dragstart); 73 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), drag); 74 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), dragend); 75 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), reset); 76 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), resize); 77 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), scroll); 78 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), search); 79 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), select); 80 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), selectstart); 81 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), submit); 82 DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(SVGElementInstance, correspondingElement(), unload); 83 84 PassRefPtr<SVGElementInstance> SVGElementInstance::create(SVGUseElement* correspondingUseElement, SVGUseElement* directUseElement, PassRefPtr<SVGElement> originalElement) 85 { 86 return adoptRef(new SVGElementInstance(correspondingUseElement, directUseElement, originalElement)); 87 } 88 89 SVGElementInstance::SVGElementInstance(SVGUseElement* correspondingUseElement, SVGUseElement* directUseElement, PassRefPtr<SVGElement> originalElement) 90 : m_parentInstance(0) 91 , m_correspondingUseElement(correspondingUseElement) 92 , m_directUseElement(directUseElement) 93 , m_element(originalElement) 94 , m_previousSibling(0) 95 , m_nextSibling(0) 96 , m_firstChild(0) 97 , m_lastChild(0) 98 { 99 ASSERT(m_correspondingUseElement); 100 ASSERT(m_element); 101 ScriptWrappable::init(this); 102 103 // Register as instance for passed element. 104 m_element->mapInstanceToElement(this); 105 106 #ifndef NDEBUG 107 instanceCounter.increment(); 108 #endif 109 } 110 111 SVGElementInstance::~SVGElementInstance() 112 { 113 // Call detach because we may be deleted directly if we are a child of a detached instance. 114 detach(); 115 116 #ifndef NDEBUG 117 instanceCounter.decrement(); 118 #endif 119 120 m_element = 0; 121 } 122 123 // It's important not to inline removedLastRef, because we don't want to inline the code to 124 // delete an SVGElementInstance at each deref call site. 125 void SVGElementInstance::removedLastRef() 126 { 127 #ifndef NDEBUG 128 m_deletionHasBegun = true; 129 #endif 130 delete this; 131 } 132 133 void SVGElementInstance::detach() 134 { 135 // Clear all pointers. When the node is detached from the shadow DOM it should be removed but, 136 // due to ref counting, it may not be. So clear everything to avoid dangling pointers. 137 138 for (SVGElementInstance* node = firstChild(); node; node = node->nextSibling()) 139 node->detach(); 140 141 // Deregister as instance for passed element, if we haven't already. 142 if (m_element->instancesForElement().contains(this)) 143 m_element->removeInstanceMapping(this); 144 // DO NOT clear ref to m_element because JavaScriptCore uses it for garbage collection 145 146 m_shadowTreeElement = 0; 147 148 m_directUseElement = 0; 149 m_correspondingUseElement = 0; 150 151 removeDetachedChildrenInContainer<SVGElementInstance, SVGElementInstance>(this); 152 } 153 154 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() 155 { 156 return SVGElementInstanceList::create(this); 157 } 158 159 void SVGElementInstance::setShadowTreeElement(SVGElement* element) 160 { 161 ASSERT(element); 162 m_shadowTreeElement = element; 163 } 164 165 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) 166 { 167 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); 168 } 169 170 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) 171 { 172 if (!element || !element->inDocument()) 173 return; 174 175 if (element->instanceUpdatesBlocked()) 176 return; 177 178 const HashSet<SVGElementInstance*>& set = element->instancesForElement(); 179 if (set.isEmpty()) 180 return; 181 182 // Mark all use elements referencing 'element' for rebuilding 183 const HashSet<SVGElementInstance*>::const_iterator end = set.end(); 184 for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) { 185 ASSERT((*it)->shadowTreeElement()); 186 ASSERT((*it)->shadowTreeElement()->correspondingElement()); 187 ASSERT((*it)->shadowTreeElement()->correspondingElement() == (*it)->correspondingElement()); 188 ASSERT((*it)->correspondingElement() == element); 189 (*it)->shadowTreeElement()->setCorrespondingElement(0); 190 191 if (SVGUseElement* element = (*it)->correspondingUseElement()) { 192 ASSERT(element->inDocument()); 193 element->invalidateShadowTree(); 194 } 195 } 196 197 element->document()->updateStyleIfNeeded(); 198 } 199 200 const AtomicString& SVGElementInstance::interfaceName() const 201 { 202 return eventNames().interfaceForSVGElementInstance; 203 } 204 205 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const 206 { 207 return m_element->document(); 208 } 209 210 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 211 { 212 return m_element->addEventListener(eventType, listener, useCapture); 213 } 214 215 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 216 { 217 return m_element->removeEventListener(eventType, listener, useCapture); 218 } 219 220 void SVGElementInstance::removeAllEventListeners() 221 { 222 m_element->removeAllEventListeners(); 223 } 224 225 Node* SVGElementInstance::toNode() 226 { 227 return shadowTreeElement(); 228 } 229 230 Document* SVGElementInstance::ownerDocument() const 231 { 232 return m_element ? m_element->ownerDocument() : 0; 233 } 234 235 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> event) 236 { 237 SVGElement* element = shadowTreeElement(); 238 if (!element) 239 return false; 240 241 return element->dispatchEvent(event); 242 } 243 244 EventTargetData* SVGElementInstance::eventTargetData() 245 { 246 // Since no event listeners are added to an SVGElementInstance, we don't have eventTargetData. 247 return 0; 248 } 249 250 EventTargetData* SVGElementInstance::ensureEventTargetData() 251 { 252 // EventTarget would use these methods if we were actually using its add/removeEventListener logic. 253 // As we're forwarding those calls to the correspondingElement(), no one should ever call this function. 254 ASSERT_NOT_REACHED(); 255 return 0; 256 } 257 258 SVGElementInstance::InstanceUpdateBlocker::InstanceUpdateBlocker(SVGElement* targetElement) 259 : m_targetElement(targetElement) 260 { 261 if (m_targetElement) 262 m_targetElement->setInstanceUpdatesBlocked(true); 263 } 264 265 SVGElementInstance::InstanceUpdateBlocker::~InstanceUpdateBlocker() 266 { 267 if (m_targetElement) 268 m_targetElement->setInstanceUpdatesBlocked(false); 269 } 270 271 } 272