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

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: Tweaks. 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 if (!element)
175 return 0;
Hajime Morrita 2013/07/11 06:41:15 Nit: Do we need this check?
176
177 element->setIsCustomElement();
178
179 const CustomElementDescriptor& descriptor = describe(element.get());
180 CustomElementDefinition* definition = m_registry.find(descriptor);
181 if (definition)
182 didResolveElement(definition, element.get());
183 else
184 didCreateUnresolvedElement(descriptor, element.get());
185
186 return element.release();
187 }
188
189 void ActiveRegistrationContext::didCreateUnresolvedElement(const CustomElementDe scriptor& descriptor, Element* element)
190 {
191 m_candidates.add(descriptor, element);
192 }
193
194 void ActiveRegistrationContext::didResolveElement(CustomElementDefinition* defin ition, Element* element) const
195 {
196 CustomElementCallbackDispatcher::instance().enqueueCreatedCallback(definitio n->callbacks(), element);
197 }
198
199 void ActiveRegistrationContext::didGiveTypeExtension(Element* element, const Ato micString& type)
200 {
201 if (!element->isHTMLElement() && !element->isSVGElement())
202 return;
203 if (element->isCustomElement())
204 return; // A custom tag, which takes precedence over type extensions
205 element->setIsCustomElement();
206 m_elementTypeMap.add(element, type);
207 const CustomElementDescriptor& descriptor = describe(element);
208 CustomElementDefinition* definition = m_registry.find(descriptor);
209 if (definition)
210 didResolveElement(definition, element);
211 else
212 didCreateUnresolvedElement(descriptor, element);
213 }
214
215 void ActiveRegistrationContext::customElementAttributeDidChange(Element* element , const AtomicString& name, const AtomicString& oldValue, const AtomicString& ne wValue)
216 {
217 ASSERT(element->isUpgradedCustomElement());
218 CustomElementDefinition* definition = definitionFor(element);
219 CustomElementCallbackDispatcher::instance().enqueueAttributeChangedCallback( definition->callbacks(), element, name, oldValue, newValue);
220 }
221
222 void ActiveRegistrationContext::customElementDidEnterDocument(Element* element)
223 {
224 ASSERT(element->isUpgradedCustomElement());
225 CustomElementDefinition* definition = definitionFor(element);
226 CustomElementCallbackDispatcher::instance().enqueueEnteredDocumentCallback(d efinition->callbacks(), element);
227 }
228
229 void ActiveRegistrationContext::customElementDidLeaveDocument(Element* element)
230 {
231 ASSERT(element->isUpgradedCustomElement());
232 CustomElementDefinition* definition = definitionFor(element);
233 CustomElementCallbackDispatcher::instance().enqueueLeftDocumentCallback(defi nition->callbacks(), element);
234 }
235
236 void ActiveRegistrationContext::customElementIsBeingDestroyed(Element* element)
237 {
238 ASSERT(element->isCustomElement());
239 m_candidates.remove(element);
240 m_elementTypeMap.remove(element);
241 }
242
243 PassRefPtr<CustomElementRegistrationContext> CustomElementRegistrationContext::c reate()
244 {
245 return adoptRef(new ActiveRegistrationContext());
246 }
247
248 bool CustomElementRegistrationContext::isValidTypeName(const AtomicString& name)
249 {
250 if (notFound == name.find('-'))
251 return false;
252
253 // FIXME: Add annotation-xml.
254 DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ());
255 if (reservedNames.isEmpty()) {
256 reservedNames.append(SVGNames::color_profileTag.localName());
257 reservedNames.append(SVGNames::font_faceTag.localName());
258 reservedNames.append(SVGNames::font_face_srcTag.localName());
259 reservedNames.append(SVGNames::font_face_uriTag.localName());
260 reservedNames.append(SVGNames::font_face_formatTag.localName());
261 reservedNames.append(SVGNames::font_face_nameTag.localName());
262 reservedNames.append(SVGNames::missing_glyphTag.localName());
263 }
264
265 if (notFound != reservedNames.find(name))
266 return false;
267
268 return Document::isValidName(name.string());
269 }
270
271 bool CustomElementRegistrationContext::isCustomTagName(const AtomicString& local Name)
272 {
273 return isValidTypeName(localName);
274 }
275
276 void CustomElementRegistrationContext::setTypeExtension(Element* element, const AtomicString& type)
277 {
278 ASSERT(element);
279 if (!type.isEmpty())
280 element->setAttribute(HTMLNames::isAttr, type);
281
282 didGiveTypeExtension(element, type);
283 }
284
285 } // 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