67bb8618ede383548b35b4b84474d44932d95f0e
[WebKit-https.git] / Source / WebCore / dom / ShadowRoot.cpp
1 /*
2  * Copyright (C) 2011 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Neither the name of Google Inc. nor the names of its
11  * contributors may be used to endorse or promote products derived from
12  * this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "ShadowRoot.h"
29
30 #include "ContentDistributor.h"
31 #include "DOMSelection.h"
32 #include "DOMWindow.h"
33 #include "Document.h"
34 #include "DocumentFragment.h"
35 #include "Element.h"
36 #include "ElementShadow.h"
37 #include "HTMLContentElement.h"
38 #include "HTMLNames.h"
39 #include "InsertionPoint.h"
40 #include "NodeRareData.h"
41 #include "SVGNames.h"
42 #include "StyleResolver.h"
43 #include "markup.h"
44
45 namespace WebCore {
46
47 ShadowRoot::ShadowRoot(Document* document)
48     : DocumentFragment(document, CreateShadowRoot)
49     , TreeScope(this)
50     , m_prev(0)
51     , m_next(0)
52     , m_applyAuthorStyles(false)
53     , m_resetStyleInheritance(false)
54     , m_insertionPointAssignedTo(0)
55 {
56     ASSERT(document);
57     
58     // Assume document as parent scope.
59     setParentTreeScope(document);
60     // Shadow tree scopes have the scope pointer point to themselves.
61     // This way, direct children will receive the correct scope pointer.
62     ensureRareData()->setTreeScope(this);
63 }
64
65 ShadowRoot::~ShadowRoot()
66 {
67     ASSERT(!m_prev);
68     ASSERT(!m_next);
69
70     // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
71     // as well as Node. See a comment on TreeScope.h for the reason.
72     if (hasRareData())
73         clearRareData();
74 }
75
76 static bool allowsAuthorShadowRoot(Element* element)
77 {
78     // FIXME: ValidationMessage recreates shadow root dynamically.
79     // https://bugs.webkit.org/show_bug.cgi?id=77937
80     // Especially, INPUT recreates shadow root dynamically.
81     // https://bugs.webkit.org/show_bug.cgi?id=77930
82     if (element->isFormControlElement())
83         return false;
84
85     // FIXME: We disable multiple shadow subtrees for SVG for while, because there will be problems to support it.
86     // https://bugs.webkit.org/show_bug.cgi?id=78205
87     // Especially SVG TREF recreates shadow root dynamically.
88     // https://bugs.webkit.org/show_bug.cgi?id=77938
89     if (element->isSVGElement())
90         return false;
91
92     return true;
93 }
94
95 PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ExceptionCode& ec)
96 {
97     return create(element, AuthorShadowRoot, ec);
98 }
99
100 PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ShadowRootType type, ExceptionCode& ec)
101 {
102     if (!element) {
103         ec = HIERARCHY_REQUEST_ERR;
104         return 0;
105     }
106
107     // Since some elements recreates shadow root dynamically, multiple shadow subtrees won't work well in that element.
108     // Until they are fixed, we disable adding author shadow root for them.
109     if (type == AuthorShadowRoot && !allowsAuthorShadowRoot(element)) {
110         ec = HIERARCHY_REQUEST_ERR;
111         return 0;
112     }
113
114     RefPtr<ShadowRoot> shadowRoot = adoptRef(new ShadowRoot(element->document()));
115 #ifndef NDEBUG
116     shadowRoot->m_type = type;
117 #endif
118
119     ec = 0;
120     element->ensureShadow()->addShadowRoot(element, shadowRoot, type, ec);
121     if (ec)
122         return 0;
123     ASSERT(element == shadowRoot->host());
124     ASSERT(element->shadow());
125     return shadowRoot.release();
126 }
127
128 String ShadowRoot::nodeName() const
129 {
130     return "#shadow-root";
131 }
132
133 PassRefPtr<Node> ShadowRoot::cloneNode(bool)
134 {
135     // ShadowRoot should not be arbitrarily cloned.
136     return 0;
137 }
138
139 String ShadowRoot::innerHTML() const
140 {
141     return createMarkup(this, ChildrenOnly);
142 }
143
144 void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
145 {
146     if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, ec))
147         replaceChildrenWithFragment(this, fragment.release(), ec);
148 }
149
150 bool ShadowRoot::childTypeAllowed(NodeType type) const
151 {
152     switch (type) {
153     case ELEMENT_NODE:
154     case PROCESSING_INSTRUCTION_NODE:
155     case COMMENT_NODE:
156     case TEXT_NODE:
157     case CDATA_SECTION_NODE:
158     case ENTITY_REFERENCE_NODE:
159         return true;
160     default:
161         return false;
162     }
163 }
164
165 ElementShadow* ShadowRoot::owner() const
166 {
167     if (host())
168         return host()->shadow();
169     return 0;
170 }
171
172 bool ShadowRoot::hasInsertionPoint() const
173 {
174     for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
175         if (isInsertionPoint(n))
176             return true;
177     }
178
179     return false;
180 }
181
182 bool ShadowRoot::applyAuthorStyles() const
183 {
184     return m_applyAuthorStyles;
185 }
186
187 void ShadowRoot::setApplyAuthorStyles(bool value)
188 {
189     if (m_applyAuthorStyles != value) {
190         m_applyAuthorStyles = value;
191         host()->setNeedsStyleRecalc();
192     }
193 }
194
195 bool ShadowRoot::resetStyleInheritance() const
196 {
197     return m_resetStyleInheritance;
198 }
199
200 void ShadowRoot::setResetStyleInheritance(bool value)
201 {
202     if (value != m_resetStyleInheritance) {
203         m_resetStyleInheritance = value;
204         if (attached() && owner())
205             owner()->recalcStyle(Force);
206     }
207 }
208
209 void ShadowRoot::attach()
210 {
211     StyleResolver* styleResolver = document()->styleResolver();
212     styleResolver->pushParentShadowRoot(this);
213     attachChildrenIfNeeded();
214     attachAsNode();
215     styleResolver->popParentShadowRoot(this);
216 }
217
218 void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
219 {
220     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
221     owner()->invalidateDistribution();
222 }
223
224 }