Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Side by Side Diff: Source/core/dom/CustomElementRegistrationContext.cpp

Issue 18332025: Split CustomElementRegistry into a registration context and a registry. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Synced to tip. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/CustomElementRegistrationContext.h"
33
34 #include "HTMLNames.h"
35 #include "SVGNames.h"
36 #include "core/dom/CustomElementCallbackDispatcher.h"
37 #include "core/dom/CustomElementDefinition.h"
38 #include "core/dom/CustomElementRegistry.h"
39 #include "core/dom/CustomElementUpgradeCandidateMap.h"
40 #include "core/dom/Element.h"
41 #include "core/html/HTMLElement.h"
42 #include "core/html/HTMLUnknownElement.h"
43 #include "core/svg/SVGElement.h"
44
45 namespace WebCore {
46
47 // The null registration context is used by documents that do not
48 // process custom elements. All of its operations are no-ops.
49 class NullRegistrationContext : public CustomElementRegistrationContext {
50 public:
51 NullRegistrationContext() { }
52 virtual ~NullRegistrationContext() { }
53
54 virtual CustomElementDescriptor describe(Element*) const OVERRIDE { return C ustomElementDescriptor(); }
55
56 virtual void registerElement(Document*, CustomElementConstructorBuilder*, co nst AtomicString&, ExceptionCode& ec) OVERRIDE { ec = NotSupportedError; }
57
58 virtual PassRefPtr<Element> createCustomTagElement(Document*, const Qualifie dName&) OVERRIDE;
59 virtual void didGiveTypeExtension(Element*, const AtomicString&) OVERRIDE { }
60
61 virtual void customElementAttributeDidChange(Element*, const AtomicString&, const AtomicString&, const AtomicString&) OVERRIDE { }
62 virtual void customElementDidEnterDocument(Element*) OVERRIDE { }
63 virtual void customElementDidLeaveDocument(Element*) OVERRIDE { }
64 virtual void customElementIsBeingDestroyed(Element*) OVERRIDE { }
65 };
66
67 PassRefPtr<Element> NullRegistrationContext::createCustomTagElement(Document* do cument, const QualifiedName& tagName)
68 {
69 ASSERT(isCustomTagName(tagName.localName()));
70
71 if (!document)
72 return 0;
73
74 if (HTMLNames::xhtmlNamespaceURI == tagName.namespaceURI())
75 return HTMLUnknownElement::create(tagName, document);
76 if (SVGNames::svgNamespaceURI == tagName.namespaceURI())
77 return SVGElement::create(tagName, document);
78 return Element::create(tagName, document);
79 }
80
81 PassRefPtr<CustomElementRegistrationContext> CustomElementRegistrationContext::n ullRegistrationContext()
82 {
83 DEFINE_STATIC_LOCAL(RefPtr<NullRegistrationContext>, instance, ());
84 if (!instance)
85 instance = adoptRef(new NullRegistrationContext());
86 return instance.get();
87 }
88
89 // An active registration context is used by documents that are
90 // processing custom elements.
91 class ActiveRegistrationContext : public CustomElementRegistrationContext {
92 public:
93 ActiveRegistrationContext() { }
94 virtual ~ActiveRegistrationContext() { }
95
96 virtual CustomElementDescriptor describe(Element*) const OVERRIDE;
97
98 virtual void registerElement(Document*, CustomElementConstructorBuilder*, co nst AtomicString& type, ExceptionCode&) OVERRIDE;
99
100 virtual PassRefPtr<Element> createCustomTagElement(Document*, const Qualifie dName&) OVERRIDE;
101 virtual void didGiveTypeExtension(Element*, const AtomicString&) OVERRIDE;
102
103 virtual void customElementAttributeDidChange(Element*, const AtomicString&, const AtomicString&, const AtomicString&) OVERRIDE;
104 virtual void customElementDidEnterDocument(Element*) OVERRIDE;
105 virtual void customElementDidLeaveDocument(Element*) OVERRIDE;
106 virtual void customElementIsBeingDestroyed(Element*) OVERRIDE;
107
108 private:
109 CustomElementDefinition* definitionFor(Element*) const;
110
111 void didCreateUnresolvedElement(const CustomElementDescriptor&, Element*);
112 void didResolveElement(CustomElementDefinition*, Element*) const;
113
114 CustomElementRegistry m_registry;
115
116 // Element creation
117 typedef HashMap<Element*, AtomicString> ElementTypeMap;
118 ElementTypeMap m_elementTypeMap; // Creation-time "is" attribute value.
119 CustomElementUpgradeCandidateMap m_candidates;
120 };
121
122 CustomElementDescriptor ActiveRegistrationContext::describe(Element* element) co nst
123 {
124 ASSERT(element->isCustomElement());
125
126 // If an element has a custom tag name it takes precedence over
127 // the "is" attribute (if any).
128 const AtomicString& type = isCustomTagName(element->localName())
129 ? element->localName()
130 : m_elementTypeMap.get(element);
131
132 ASSERT(!type.isNull()); // Element must be in this registry
133 return CustomElementDescriptor(type, element->namespaceURI(), element->local Name());
134 }
135
136 void ActiveRegistrationContext::registerElement(Document* document, CustomElemen tConstructorBuilder* constructorBuilder, const AtomicString& type, ExceptionCode & ec)
137 {
138 CustomElementDefinition* definition = m_registry.registerElement(document, c onstructorBuilder, type, ec);
139
140 if (!definition)
141 return;
142
143 // Upgrade elements that were waiting for this definition.
144 const CustomElementUpgradeCandidateMap::ElementSet& upgradeCandidates = m_ca ndidates.takeUpgradeCandidatesFor(definition->descriptor());
145 for (CustomElementUpgradeCandidateMap::ElementSet::const_iterator it = upgra deCandidates.begin(); it != upgradeCandidates.end(); ++it)
146 didResolveElement(definition, *it);
147 }
148
149 CustomElementDefinition* ActiveRegistrationContext::definitionFor(Element* eleme nt) const
150 {
151 ASSERT(element->document()->registrationContext() == this);
152 const CustomElementDescriptor& descriptor = describe(element);
153 return m_registry.find(descriptor);
154 }
155
156 PassRefPtr<Element> ActiveRegistrationContext::createCustomTagElement(Document* document, const QualifiedName& tagName)
157 {
158 ASSERT(isCustomTagName(tagName.localName()));
159
160 if (!document)
161 return 0;
162
163 RefPtr<Element> element;
164
165 if (HTMLNames::xhtmlNamespaceURI == tagName.namespaceURI()) {
166 element = HTMLElement::create(tagName, document);
167 } else if (SVGNames::svgNamespaceURI == tagName.namespaceURI()) {
168 element = SVGElement::create(tagName, document);
169 } else {
170 // XML elements are not custom elements, so return early.
171 return Element::create(tagName, document);
172 }
173
174 element->setIsCustomElement();
175
176 const CustomElementDescriptor& descriptor = describe(element.get());
177 CustomElementDefinition* definition = m_registry.find(descriptor);
178 if (definition)
179 didResolveElement(definition, element.get());
180 else
181 didCreateUnresolvedElement(descriptor, element.get());
182
183 return element.release();
184 }
185
186 void ActiveRegistrationContext::didCreateUnresolvedElement(const CustomElementDe scriptor& descriptor, Element* element)
187 {
188 m_candidates.add(descriptor, element);
189 }
190
191 void ActiveRegistrationContext::didResolveElement(CustomElementDefinition* defin ition, Element* element) const
192 {
193 CustomElementCallbackDispatcher::instance().enqueueCreatedCallback(definitio n->callbacks(), element);
194 }
195
196 void ActiveRegistrationContext::didGiveTypeExtension(Element* element, const Ato micString& type)
197 {
198 if (!element->isHTMLElement() && !element->isSVGElement())
199 return;
200 if (element->isCustomElement())
201 return; // A custom tag, which takes precedence over type extensions
202 element->setIsCustomElement();
203 m_elementTypeMap.add(element, type);
204 const CustomElementDescriptor& descriptor = describe(element);
205 CustomElementDefinition* definition = m_registry.find(descriptor);
206 if (definition)
207 didResolveElement(definition, element);
208 else
209 didCreateUnresolvedElement(descriptor, element);
210 }
211
212 void ActiveRegistrationContext::customElementAttributeDidChange(Element* element , const AtomicString& name, const AtomicString& oldValue, const AtomicString& ne wValue)
213 {
214 ASSERT(element->isUpgradedCustomElement());
215 CustomElementDefinition* definition = definitionFor(element);
216 CustomElementCallbackDispatcher::instance().enqueueAttributeChangedCallback( definition->callbacks(), element, name, oldValue, newValue);
217 }
218
219 void ActiveRegistrationContext::customElementDidEnterDocument(Element* element)
220 {
221 ASSERT(element->isUpgradedCustomElement());
222 CustomElementDefinition* definition = definitionFor(element);
223 CustomElementCallbackDispatcher::instance().enqueueEnteredDocumentCallback(d efinition->callbacks(), element);
224 }
225
226 void ActiveRegistrationContext::customElementDidLeaveDocument(Element* element)
227 {
228 ASSERT(element->isUpgradedCustomElement());
229 CustomElementDefinition* definition = definitionFor(element);
230 CustomElementCallbackDispatcher::instance().enqueueLeftDocumentCallback(defi nition->callbacks(), element);
231 }
232
233 void ActiveRegistrationContext::customElementIsBeingDestroyed(Element* element)
234 {
235 ASSERT(element->isCustomElement());
236 m_candidates.remove(element);
237 m_elementTypeMap.remove(element);
238 }
239
240 PassRefPtr<CustomElementRegistrationContext> CustomElementRegistrationContext::c reate()
241 {
242 return adoptRef(new ActiveRegistrationContext());
243 }
244
245 bool CustomElementRegistrationContext::isValidTypeName(const AtomicString& name)
246 {
247 if (notFound == name.find('-'))
248 return false;
249
250 // FIXME: Add annotation-xml.
251 DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ());
252 if (reservedNames.isEmpty()) {
253 reservedNames.append(SVGNames::color_profileTag.localName());
254 reservedNames.append(SVGNames::font_faceTag.localName());
255 reservedNames.append(SVGNames::font_face_srcTag.localName());
256 reservedNames.append(SVGNames::font_face_uriTag.localName());
257 reservedNames.append(SVGNames::font_face_formatTag.localName());
258 reservedNames.append(SVGNames::font_face_nameTag.localName());
259 reservedNames.append(SVGNames::missing_glyphTag.localName());
260 }
261
262 if (notFound != reservedNames.find(name))
263 return false;
264
265 return Document::isValidName(name.string());
266 }
267
268 bool CustomElementRegistrationContext::isCustomTagName(const AtomicString& local Name)
269 {
270 return isValidTypeName(localName);
271 }
272
273 void CustomElementRegistrationContext::setTypeExtension(Element* element, const AtomicString& type)
274 {
275 ASSERT(element);
276 if (!type.isEmpty())
277 element->setAttribute(HTMLNames::isAttr, type);
278
279 didGiveTypeExtension(element, type);
280 }
281
282 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/dom/CustomElementRegistrationContext.h ('k') | Source/core/dom/CustomElementRegistry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698