blob: 4589e7e1c1c88d6f91b046b6df06e9bc0bbf1980 [file] [log] [blame]
Ben Murdoche69819b2013-07-17 14:56:49 +01001/*
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"
Ben Murdochdf957042013-08-06 11:01:27 +010036#include "bindings/v8/ExceptionState.h"
Ben Murdoch83750172013-07-24 10:36:59 +010037#include "core/dom/CustomElement.h"
Ben Murdoche69819b2013-07-17 14:56:49 +010038#include "core/dom/CustomElementDefinition.h"
Ben Murdoche69819b2013-07-17 14:56:49 +010039#include "core/dom/Element.h"
40#include "core/html/HTMLElement.h"
41#include "core/html/HTMLUnknownElement.h"
Torne (Richard Coles)f5e4ad52013-08-05 13:57:57 +010042#include "core/svg/SVGUnknownElement.h"
Ben Murdoch02772c62013-07-26 10:21:05 +010043#include "wtf/RefPtr.h"
Ben Murdoche69819b2013-07-17 14:56:49 +010044
45namespace WebCore {
46
Ben Murdochdf957042013-08-06 11:01:27 +010047void CustomElementRegistrationContext::registerElement(Document* document, CustomElementConstructorBuilder* constructorBuilder, const AtomicString& type, ExceptionState& es)
Ben Murdoche69819b2013-07-17 14:56:49 +010048{
Ben Murdochdf957042013-08-06 11:01:27 +010049 CustomElementDefinition* definition = m_registry.registerElement(document, constructorBuilder, type, es);
Ben Murdoche69819b2013-07-17 14:56:49 +010050
51 if (!definition)
52 return;
53
54 // Upgrade elements that were waiting for this definition.
55 const CustomElementUpgradeCandidateMap::ElementSet& upgradeCandidates = m_candidates.takeUpgradeCandidatesFor(definition->descriptor());
56 for (CustomElementUpgradeCandidateMap::ElementSet::const_iterator it = upgradeCandidates.begin(); it != upgradeCandidates.end(); ++it)
57 didResolveElement(definition, *it);
58}
59
Ben Murdoch02772c62013-07-26 10:21:05 +010060PassRefPtr<Element> CustomElementRegistrationContext::createCustomTagElement(Document* document, const QualifiedName& tagName)
Ben Murdoche69819b2013-07-17 14:56:49 +010061{
Ben Murdoch1fad5ca2013-08-07 11:05:11 +010062 ASSERT(CustomElement::isCustomTagName(tagName.localName()));
Ben Murdoche69819b2013-07-17 14:56:49 +010063
64 if (!document)
65 return 0;
66
67 RefPtr<Element> element;
68
69 if (HTMLNames::xhtmlNamespaceURI == tagName.namespaceURI()) {
70 element = HTMLElement::create(tagName, document);
71 } else if (SVGNames::svgNamespaceURI == tagName.namespaceURI()) {
Torne (Richard Coles)f5e4ad52013-08-05 13:57:57 +010072 element = SVGUnknownElement::create(tagName, document);
Ben Murdoche69819b2013-07-17 14:56:49 +010073 } else {
74 // XML elements are not custom elements, so return early.
75 return Element::create(tagName, document);
76 }
77
Ben Murdoch02772c62013-07-26 10:21:05 +010078 resolve(element.get(), nullAtom);
Ben Murdoch0019e4e2013-07-18 11:57:54 +010079 return element.release();
80}
Ben Murdoche69819b2013-07-17 14:56:49 +010081
Ben Murdoch02772c62013-07-26 10:21:05 +010082void CustomElementRegistrationContext::didGiveTypeExtension(Element* element, const AtomicString& type)
Ben Murdoch0019e4e2013-07-18 11:57:54 +010083{
Ben Murdoch02772c62013-07-26 10:21:05 +010084 resolve(element, type);
Ben Murdoch0019e4e2013-07-18 11:57:54 +010085}
86
Ben Murdoch02772c62013-07-26 10:21:05 +010087void CustomElementRegistrationContext::resolve(Element* element, const AtomicString& typeExtension)
Ben Murdoch0019e4e2013-07-18 11:57:54 +010088{
Ben Murdoch02772c62013-07-26 10:21:05 +010089 // If an element has a custom tag name it takes precedence over
90 // the "is" attribute (if any).
Ben Murdoch1fad5ca2013-08-07 11:05:11 +010091 const AtomicString& type = CustomElement::isCustomTagName(element->localName())
Ben Murdoch02772c62013-07-26 10:21:05 +010092 ? element->localName()
93 : typeExtension;
94 ASSERT(!type.isNull());
95
96 CustomElementDescriptor descriptor(type, element->namespaceURI(), element->localName());
Ben Murdoche69819b2013-07-17 14:56:49 +010097 CustomElementDefinition* definition = m_registry.find(descriptor);
98 if (definition)
Ben Murdoch0019e4e2013-07-18 11:57:54 +010099 didResolveElement(definition, element);
Ben Murdoche69819b2013-07-17 14:56:49 +0100100 else
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100101 didCreateUnresolvedElement(descriptor, element);
102}
Ben Murdoche69819b2013-07-17 14:56:49 +0100103
Ben Murdoch02772c62013-07-26 10:21:05 +0100104void CustomElementRegistrationContext::didResolveElement(CustomElementDefinition* definition, Element* element)
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100105{
Ben Murdoch83750172013-07-24 10:36:59 +0100106 CustomElement::define(element, definition);
Ben Murdoche69819b2013-07-17 14:56:49 +0100107}
108
Ben Murdoch02772c62013-07-26 10:21:05 +0100109void CustomElementRegistrationContext::didCreateUnresolvedElement(const CustomElementDescriptor& descriptor, Element* element)
Ben Murdoche69819b2013-07-17 14:56:49 +0100110{
111 m_candidates.add(descriptor, element);
112}
113
Ben Murdoch02772c62013-07-26 10:21:05 +0100114void CustomElementRegistrationContext::customElementWasDestroyed(Element* element)
Ben Murdoche69819b2013-07-17 14:56:49 +0100115{
Ben Murdoche69819b2013-07-17 14:56:49 +0100116 m_candidates.remove(element);
Ben Murdoche69819b2013-07-17 14:56:49 +0100117}
118
119PassRefPtr<CustomElementRegistrationContext> CustomElementRegistrationContext::create()
120{
Ben Murdoch02772c62013-07-26 10:21:05 +0100121 return adoptRef(new CustomElementRegistrationContext());
Ben Murdoche69819b2013-07-17 14:56:49 +0100122}
123
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100124void CustomElementRegistrationContext::setIsAttributeAndTypeExtension(Element* element, const AtomicString& type)
Ben Murdoche69819b2013-07-17 14:56:49 +0100125{
126 ASSERT(element);
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100127 ASSERT(!type.isEmpty());
128 element->setAttribute(HTMLNames::isAttr, type);
129 setTypeExtension(element, type);
130}
Ben Murdoche69819b2013-07-17 14:56:49 +0100131
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100132void CustomElementRegistrationContext::setTypeExtension(Element* element, const AtomicString& type)
133{
134 if (!element->isHTMLElement() && !element->isSVGElement())
135 return;
136
Ben Murdoch1fad5ca2013-08-07 11:05:11 +0100137 if (element->isCustomElement()) {
138 // This can happen if:
139 // 1. The element has a custom tag, which takes precedence over
140 // type extensions.
141 // 2. Undoing a command (eg ReplaceNodeWithSpan) recycles an
142 // element but tries to overwrite its attribute list.
143 return;
144 }
145
146 // Custom tags take precedence over type extensions
147 ASSERT(!CustomElement::isCustomTagName(element->localName()));
Ben Murdoch0019e4e2013-07-18 11:57:54 +0100148
Ben Murdoch02772c62013-07-26 10:21:05 +0100149 if (CustomElementRegistrationContext* context = element->document()->registrationContext())
150 context->didGiveTypeExtension(element, type);
Ben Murdoche69819b2013-07-17 14:56:49 +0100151}
152
153} // namespace WebCore