• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
embedderCustomElementNames()44 Vector<AtomicString>& CustomElement::embedderCustomElementNames()
45 {
46     DEFINE_STATIC_LOCAL(Vector<AtomicString>, names, ());
47     return names;
48 }
49 
addEmbedderCustomElementName(const AtomicString & name)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 
enabledNameSet()58 static CustomElement::NameSet enabledNameSet()
59 {
60     return CustomElement::NameSet((RuntimeEnabledFeatures::customElementsEnabled() ? CustomElement::StandardNames : 0) | (RuntimeEnabledFeatures::embedderCustomElementsEnabled() ? CustomElement::EmbedderNames : 0));
61 }
62 
isValidName(const AtomicString & name,NameSet validNames)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 
define(Element * element,PassRefPtr<CustomElementDefinition> passDefinition)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 
definitionFor(Element * element)109 CustomElementDefinition* CustomElement::definitionFor(Element* element)
110 {
111     CustomElementDefinition* definition = definitions().get(element);
112     ASSERT(definition);
113     return definition;
114 }
115 
attributeDidChange(Element * element,const AtomicString & name,const AtomicString & oldValue,const AtomicString & newValue)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 
didEnterDocument(Element * element,const Document & document)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 
didLeaveDocument(Element * element,const Document & document)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 
wasDestroyed(Element * element)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 
add(Element * element,PassRefPtr<CustomElementDefinition> definition)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 
definitions()160 CustomElement::DefinitionMap& CustomElement::definitions()
161 {
162     DEFINE_STATIC_LOCAL(DefinitionMap, map, ());
163     return map;
164 }
165 
166 } // namespace WebCore
167