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/custom/CustomElement.h" 33 34 #include "HTMLNames.h" 35 #include "MathMLNames.h" 36 #include "RuntimeEnabledFeatures.h" 37 #include "SVGNames.h" 38 #include "core/dom/Element.h" 39 #include "core/dom/custom/CustomElementCallbackScheduler.h" 40 #include "core/dom/custom/CustomElementObserver.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::customElementsEnabled() ? 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) && kNotFound != embedderCustomElementNames().find(name)) 68 return Document::isValidName(name); 69 70 if ((validNames & StandardNames) && kNotFound != name.find('-')) { 71 DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ()); 72 if (reservedNames.isEmpty()) { 73 reservedNames.append(MathMLNames::annotation_xmlTag.localName()); 74 // In principle, "color-profile" should exist in the SVGNames 75 // namespace, but we don't implement the color-profile element. 76 reservedNames.append("color-profile"); 77 reservedNames.append(SVGNames::font_faceTag.localName()); 78 reservedNames.append(SVGNames::font_face_srcTag.localName()); 79 reservedNames.append(SVGNames::font_face_uriTag.localName()); 80 reservedNames.append(SVGNames::font_face_formatTag.localName()); 81 reservedNames.append(SVGNames::font_face_nameTag.localName()); 82 reservedNames.append(SVGNames::missing_glyphTag.localName()); 83 } 84 85 if (kNotFound == reservedNames.find(name)) 86 return Document::isValidName(name.string()); 87 } 88 89 return false; 90 } 91 92 void CustomElement::define(Element* element, PassRefPtr<CustomElementDefinition> passDefinition) 93 { 94 RefPtr<CustomElementDefinition> definition(passDefinition); 95 96 switch (element->customElementState()) { 97 case Element::NotCustomElement: 98 case Element::Upgraded: 99 ASSERT_NOT_REACHED(); 100 break; 101 102 case Element::WaitingForUpgrade: 103 definitions().add(element, definition); 104 CustomElementCallbackScheduler::scheduleCreatedCallback(definition->callbacks(), element); 105 break; 106 } 107 } 108 109 CustomElementDefinition* CustomElement::definitionFor(Element* element) 110 { 111 CustomElementDefinition* definition = definitions().get(element); 112 ASSERT(definition); 113 return definition; 114 } 115 116 void CustomElement::attributeDidChange(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) 117 { 118 ASSERT(element->customElementState() == Element::Upgraded); 119 CustomElementCallbackScheduler::scheduleAttributeChangedCallback(definitionFor(element)->callbacks(), element, name, oldValue, newValue); 120 } 121 122 void CustomElement::didEnterDocument(Element* element, const Document& document) 123 { 124 ASSERT(element->customElementState() == Element::Upgraded); 125 if (!document.domWindow()) 126 return; 127 CustomElementCallbackScheduler::scheduleAttachedCallback(definitionFor(element)->callbacks(), element); 128 } 129 130 void CustomElement::didLeaveDocument(Element* element, const Document& document) 131 { 132 ASSERT(element->customElementState() == Element::Upgraded); 133 if (!document.domWindow()) 134 return; 135 CustomElementCallbackScheduler::scheduleDetachedCallback(definitionFor(element)->callbacks(), element); 136 } 137 138 void CustomElement::wasDestroyed(Element* element) 139 { 140 switch (element->customElementState()) { 141 case Element::NotCustomElement: 142 ASSERT_NOT_REACHED(); 143 break; 144 145 case Element::WaitingForUpgrade: 146 case Element::Upgraded: 147 definitions().remove(element); 148 CustomElementObserver::notifyElementWasDestroyed(element); 149 break; 150 } 151 } 152 153 void CustomElement::DefinitionMap::add(Element* element, PassRefPtr<CustomElementDefinition> definition) 154 { 155 ASSERT(definition.get()); 156 DefinitionMap::ElementDefinitionHashMap::AddResult result = m_definitions.add(element, definition); 157 ASSERT_UNUSED(result, result.isNewEntry); 158 } 159 160 CustomElement::DefinitionMap& CustomElement::definitions() 161 { 162 DEFINE_STATIC_LOCAL(DefinitionMap, map, ()); 163 return map; 164 } 165 166 } // namespace WebCore 167