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