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

Side by Side Diff: Source/core/dom/CustomElementRegistry.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
« no previous file with comments | « Source/core/dom/CustomElementRegistry.h ('k') | Source/core/dom/Document.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 16 matching lines...) Expand all
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/dom/CustomElementRegistry.h" 32 #include "core/dom/CustomElementRegistry.h"
33 33
34 #include "HTMLNames.h" 34 #include "HTMLNames.h"
35 #include "SVGNames.h" 35 #include "SVGNames.h"
36 #include "bindings/v8/CustomElementConstructorBuilder.h" 36 #include "bindings/v8/CustomElementConstructorBuilder.h"
37 #include "core/dom/CustomElementCallbackDispatcher.h"
38 #include "core/dom/CustomElementDefinition.h" 37 #include "core/dom/CustomElementDefinition.h"
39 #include "core/dom/Document.h" 38 #include "core/dom/CustomElementRegistrationContext.h"
40 #include "core/dom/DocumentLifecycleObserver.h" 39 #include "core/dom/DocumentLifecycleObserver.h"
41 #include "core/dom/Element.h"
42 #include "core/html/HTMLElement.h"
43 #include "core/svg/SVGElement.h"
44 #include "wtf/Vector.h"
45 40
46 namespace WebCore { 41 namespace WebCore {
47 42
48 void setTypeExtension(Element* element, const AtomicString& typeExtension)
49 {
50 ASSERT(element);
51 if (!typeExtension.isEmpty())
52 element->setAttribute(HTMLNames::isAttr, typeExtension);
53 }
54
55 static inline bool nameIncludesHyphen(const AtomicString& name)
56 {
57 size_t hyphenPosition = name.find('-');
58 return (hyphenPosition != notFound);
59 }
60
61 bool CustomElementRegistry::isValidTypeName(const AtomicString& name)
62 {
63 if (!nameIncludesHyphen(name))
64 return false;
65
66 DEFINE_STATIC_LOCAL(Vector<AtomicString>, reservedNames, ());
67 if (reservedNames.isEmpty()) {
68 reservedNames.append(SVGNames::color_profileTag.localName());
69 reservedNames.append(SVGNames::font_faceTag.localName());
70 reservedNames.append(SVGNames::font_face_srcTag.localName());
71 reservedNames.append(SVGNames::font_face_uriTag.localName());
72 reservedNames.append(SVGNames::font_face_formatTag.localName());
73 reservedNames.append(SVGNames::font_face_nameTag.localName());
74 reservedNames.append(SVGNames::missing_glyphTag.localName());
75 }
76
77 if (notFound != reservedNames.find(name))
78 return false;
79
80 return Document::isValidName(name.string());
81 }
82
83 CustomElementDescriptor CustomElementRegistry::describe(Element* element) const
84 {
85 ASSERT(element->isCustomElement());
86
87 // If an element has a custom tag name it takes precedence over
88 // the "is" attribute (if any).
89 const AtomicString& type = isCustomTagName(element->localName())
90 ? element->localName()
91 : m_elementTypeMap.get(element);
92
93 ASSERT(!type.isNull()); // Element must be in this registry
94 return CustomElementDescriptor(type, element->namespaceURI(), element->local Name());
95 }
96
97 class RegistrationContextObserver : public DocumentLifecycleObserver { 43 class RegistrationContextObserver : public DocumentLifecycleObserver {
98 public: 44 public:
99 explicit RegistrationContextObserver(Document* document) 45 explicit RegistrationContextObserver(Document* document)
100 : DocumentLifecycleObserver(document) 46 : DocumentLifecycleObserver(document)
101 , m_wentAway(!document) 47 , m_wentAway(!document)
102 { 48 {
103 } 49 }
104 50
105 bool registrationContextWentAway() { return m_wentAway; } 51 bool registrationContextWentAway() { return m_wentAway; }
106 52
107 private: 53 private:
108 virtual void documentWasDisposed() OVERRIDE { m_wentAway = true; } 54 virtual void documentWasDisposed() OVERRIDE { m_wentAway = true; }
109 55
110 bool m_wentAway; 56 bool m_wentAway;
111 }; 57 };
112 58
113 void CustomElementRegistry::registerElement(Document* document, CustomElementCon structorBuilder* constructorBuilder, const AtomicString& userSuppliedName, Excep tionCode& ec) 59 CustomElementDefinition* CustomElementRegistry::registerElement(Document* docume nt, CustomElementConstructorBuilder* constructorBuilder, const AtomicString& use rSuppliedName, ExceptionCode& ec)
114 { 60 {
115 RefPtr<CustomElementRegistry> protect(this);
116
117 // FIXME: In every instance except one it is the 61 // FIXME: In every instance except one it is the
118 // CustomElementConstructorBuilder that observes document 62 // CustomElementConstructorBuilder that observes document
119 // destruction during registration. This responsibility should be 63 // destruction during registration. This responsibility should be
120 // consolidated in one place. 64 // consolidated in one place.
121 RegistrationContextObserver observer(document); 65 RegistrationContextObserver observer(document);
122 66
123 if (!constructorBuilder->isFeatureAllowed()) 67 if (!constructorBuilder->isFeatureAllowed())
124 return; 68 return 0;
125 69
126 AtomicString type = userSuppliedName.lower(); 70 AtomicString type = userSuppliedName.lower();
127 if (!isValidTypeName(type)) { 71 if (!CustomElementRegistrationContext::isValidTypeName(type)) {
128 ec = InvalidCharacterError; 72 ec = InvalidCharacterError;
129 return; 73 return 0;
130 } 74 }
131 75
132 if (!constructorBuilder->validateOptions()) { 76 if (!constructorBuilder->validateOptions()) {
133 ec = InvalidStateError; 77 ec = InvalidStateError;
134 return; 78 return 0;
135 } 79 }
136 80
137 QualifiedName tagName = nullQName(); 81 QualifiedName tagName = nullQName();
138 if (!constructorBuilder->findTagName(type, tagName)) { 82 if (!constructorBuilder->findTagName(type, tagName)) {
139 ec = NamespaceError; 83 ec = NamespaceError;
140 return; 84 return 0;
141 } 85 }
142 ASSERT(tagName.namespaceURI() == HTMLNames::xhtmlNamespaceURI || tagName.nam espaceURI() == SVGNames::svgNamespaceURI); 86 ASSERT(tagName.namespaceURI() == HTMLNames::xhtmlNamespaceURI || tagName.nam espaceURI() == SVGNames::svgNamespaceURI);
143 87
144 if (m_registeredTypeNames.contains(type)) { 88 if (m_registeredTypeNames.contains(type)) {
145 ec = InvalidStateError; 89 ec = InvalidStateError;
146 return; 90 return 0;
147 } 91 }
148 92
149 ASSERT(!observer.registrationContextWentAway()); 93 ASSERT(!observer.registrationContextWentAway());
150 94
151 RefPtr<CustomElementLifecycleCallbacks> lifecycleCallbacks = constructorBuil der->createCallbacks(document); 95 RefPtr<CustomElementLifecycleCallbacks> lifecycleCallbacks = constructorBuil der->createCallbacks(document);
152 96
153 // Consulting the constructor builder could execute script and 97 // Consulting the constructor builder could execute script and
154 // kill the document. 98 // kill the document.
155 if (observer.registrationContextWentAway()) { 99 if (observer.registrationContextWentAway()) {
156 ec = InvalidStateError; 100 ec = InvalidStateError;
157 return; 101 return 0;
158 } 102 }
159 103
160 const CustomElementDescriptor descriptor(type, tagName.namespaceURI(), tagNa me.localName()); 104 const CustomElementDescriptor descriptor(type, tagName.namespaceURI(), tagNa me.localName());
161 RefPtr<CustomElementDefinition> definition = CustomElementDefinition::create (descriptor, lifecycleCallbacks); 105 RefPtr<CustomElementDefinition> definition = CustomElementDefinition::create (descriptor, lifecycleCallbacks);
162 106
163 if (!constructorBuilder->createConstructor(document, definition.get())) { 107 if (!constructorBuilder->createConstructor(document, definition.get())) {
164 ec = NotSupportedError; 108 ec = NotSupportedError;
165 return; 109 return 0;
166 } 110 }
167 111
168 m_definitions.add(descriptor, definition); 112 m_definitions.add(descriptor, definition);
169 m_registeredTypeNames.add(descriptor.type()); 113 m_registeredTypeNames.add(descriptor.type());
170 114
171 if (!constructorBuilder->didRegisterDefinition(definition.get())) { 115 if (!constructorBuilder->didRegisterDefinition(definition.get())) {
172 ec = NotSupportedError; 116 ec = NotSupportedError;
173 return; 117 return 0;
174 } 118 }
175 119
176 // Upgrade elements that were waiting for this definition. 120 return definition.get();
177 const CustomElementUpgradeCandidateMap::ElementSet& upgradeCandidates = m_ca ndidates.takeUpgradeCandidatesFor(descriptor);
178 for (CustomElementUpgradeCandidateMap::ElementSet::const_iterator it = upgra deCandidates.begin(); it != upgradeCandidates.end(); ++it)
179 didResolveElement(definition.get(), *it);
180 }
181
182 CustomElementDefinition* CustomElementRegistry::findFor(Element* element) const
183 {
184 ASSERT(element->document()->registry() == this);
185
186 const CustomElementDescriptor& descriptor = describe(element);
187 return find(descriptor);
188 } 121 }
189 122
190 CustomElementDefinition* CustomElementRegistry::find(const CustomElementDescript or& descriptor) const 123 CustomElementDefinition* CustomElementRegistry::find(const CustomElementDescript or& descriptor) const
191 { 124 {
192 return m_definitions.get(descriptor); 125 return m_definitions.get(descriptor);
193 } 126 }
194 127
195 PassRefPtr<Element> CustomElementRegistry::createCustomTagElement(Document* docu ment, const QualifiedName& tagName) 128 } // namespace WebCore
196 {
197 if (!document)
198 return 0;
199
200 ASSERT(isCustomTagName(tagName.localName()));
201
202 RefPtr<Element> element;
203
204 if (HTMLNames::xhtmlNamespaceURI == tagName.namespaceURI())
205 element = HTMLElement::create(tagName, document);
206 else if (SVGNames::svgNamespaceURI == tagName.namespaceURI())
207 element = SVGElement::create(tagName, document);
208 else
209 return Element::create(tagName, document);
210
211 element->setIsCustomElement();
212
213 const CustomElementDescriptor& descriptor = describe(element.get());
214 CustomElementDefinition* definition = find(descriptor);
215 if (definition)
216 didResolveElement(definition, element.get());
217 else
218 didCreateUnresolvedElement(descriptor, element.get());
219
220 return element.release();
221 }
222
223 void CustomElementRegistry::didGiveTypeExtension(Element* element, const AtomicS tring& type)
224 {
225 if (!element->isHTMLElement() && !element->isSVGElement())
226 return;
227 if (element->isCustomElement())
228 return; // A custom tag, which takes precedence over type extensions
229 element->setIsCustomElement();
230 m_elementTypeMap.add(element, type);
231 const CustomElementDescriptor& descriptor = describe(element);
232 CustomElementDefinition* definition = find(descriptor);
233 if (definition)
234 didResolveElement(definition, element);
235 else
236 didCreateUnresolvedElement(descriptor, element);
237 }
238
239 void CustomElementRegistry::didResolveElement(CustomElementDefinition* definitio n, Element* element) const
240 {
241 CustomElementCallbackDispatcher::instance().enqueueCreatedCallback(definitio n->callbacks(), element);
242 }
243
244 void CustomElementRegistry::didCreateUnresolvedElement(const CustomElementDescri ptor& descriptor, Element* element)
245 {
246 m_candidates.add(descriptor, element);
247 }
248
249 void CustomElementRegistry::customElementWasDestroyed(Element* element)
250 {
251 ASSERT(element->isCustomElement());
252 m_candidates.remove(element);
253 m_elementTypeMap.remove(element);
254 }
255
256 }
OLDNEW
« no previous file with comments | « Source/core/dom/CustomElementRegistry.h ('k') | Source/core/dom/Document.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698