1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * 3. Neither the name of Google Inc. nor the names of its contributors 15 * may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/dom/CustomElement.h" 33 34 #include "HTMLNames.h" 35 #include "MathMLNames.h" 36 #include "RuntimeEnabledFeatures.h" 37 #include "SVGNames.h" 38 #include "core/dom/CustomElementCallbackScheduler.h" 39 #include "core/dom/CustomElementUpgradeCandidateMap.h" 40 #include "core/dom/Element.h" 41 42 namespace WebCore { 43 44 Vector<AtomicString>& CustomElement::embedderCustomElementNames() 45 { 46 DEFINE_STATIC_LOCAL(Vector<AtomicString>, names, ()); 47 return names; 48 } 49 50 void CustomElement::addEmbedderCustomElementName(const AtomicString& name) 51 { 52 AtomicString lower = name.lower(); 53 if (isValidName(lower, EmbedderNames)) 54 return; 55 embedderCustomElementNames().append(lower); 56 } 57 58 static CustomElement::NameSet enabledNameSet() 59 { 60 return CustomElement::NameSet((RuntimeEnabledFeatures::customDOMElementsEnabled() ? CustomElement::StandardNames : 0) | (RuntimeEnabledFeatures::embedderCustomElementsEnabled() ? CustomElement::EmbedderNames : 0)); 61 } 62 63 bool CustomElement::isValidName(const AtomicString& name, NameSet validNames) 64 { 65 validNames = NameSet(validNames & enabledNameSet()); 66 67 if ((validNames & EmbedderNames) && notFound != embedderCustomElementNames().find(name)) 68 return Document::isValidName(name); 69 70 if ((validNames & StandardNames) && notFound != name.find('-')) { 71 DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ()); 72 if (reservedNames.isEmpty()) { 73 reservedNames.append(MathMLNames::annotation_xmlTag.localName()); 74 reservedNames.append(SVGNames::color_profileTag.localName()); 75 reservedNames.append(SVGNames::font_faceTag.localName()); 76 reservedNames.append(SVGNames::font_face_srcTag.localName()); 77 reservedNames.append(SVGNames::font_face_uriTag.localName()); 78 reservedNames.append(SVGNames::font_face_formatTag.localName()); 79 reservedNames.append(SVGNames::font_face_nameTag.localName()); 80 reservedNames.append(SVGNames::missing_glyphTag.localName()); 81 } 82 83 if (notFound == reservedNames.find(name)) 84 return Document::isValidName(name.string()); 85 } 86 87 return false; 88 } 89 90 void CustomElement::define(Element* element, PassRefPtr<CustomElementDefinition> passDefinition) 91 { 92 RefPtr<CustomElementDefinition> definition(passDefinition); 93 element->setCustomElementState(Element::Defined); 94 definitions().add(element, definition); 95 CustomElementCallbackScheduler::scheduleCreatedCallback(definition->callbacks(), element); 96 } 97 98 CustomElementDefinition* CustomElement::definitionFor(Element* element) 99 { 100 return definitions().get(element); 101 } 102 103 void CustomElement::attributeDidChange(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) 104 { 105 ASSERT(element->customElementState() == Element::Upgraded); 106 CustomElementCallbackScheduler::scheduleAttributeChangedCallback(definitions().get(element)->callbacks(), element, name, oldValue, newValue); 107 } 108 109 void CustomElement::didEnterDocument(Element* element, Document* document) 110 { 111 ASSERT(element->customElementState() == Element::Upgraded); 112 if (!document->defaultView()) 113 return; 114 CustomElementCallbackScheduler::scheduleEnteredDocumentCallback(definitions().get(element)->callbacks(), element); 115 } 116 117 void CustomElement::didLeaveDocument(Element* element, Document* document) 118 { 119 ASSERT(element->customElementState() == Element::Upgraded); 120 if (!document->defaultView()) 121 return; 122 CustomElementCallbackScheduler::scheduleLeftDocumentCallback(definitions().get(element)->callbacks(), element); 123 } 124 125 void CustomElement::wasDestroyed(Element* element) 126 { 127 switch (element->customElementState()) { 128 case Element::NotCustomElement: 129 ASSERT_NOT_REACHED(); 130 break; 131 132 case Element::UpgradeCandidate: 133 CustomElementUpgradeCandidateMap::elementWasDestroyed(element); 134 break; 135 136 case Element::Defined: 137 case Element::Upgraded: 138 definitions().remove(element); 139 break; 140 } 141 } 142 143 void CustomElement::DefinitionMap::add(Element* element, PassRefPtr<CustomElementDefinition> definition) 144 { 145 ASSERT(definition.get()); 146 DefinitionMap::ElementDefinitionHashMap::AddResult result = m_definitions.add(element, definition); 147 ASSERT(result.isNewEntry); 148 } 149 150 void CustomElement::DefinitionMap::remove(Element* element) 151 { 152 m_definitions.remove(element); 153 } 154 155 CustomElementDefinition* CustomElement::DefinitionMap::get(Element* element) 156 { 157 DefinitionMap::ElementDefinitionHashMap::const_iterator it = m_definitions.find(element); 158 ASSERT(it != m_definitions.end()); 159 return it->value.get(); 160 } 161 162 CustomElement::DefinitionMap& CustomElement::definitions() 163 { 164 DEFINE_STATIC_LOCAL(DefinitionMap, map, ()); 165 return map; 166 } 167 168 } // namespace WebCore 169