b586687c11a6d870fae94f8e74022ab5484afacf
[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, document)
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     // Shadow tree scopes have the scope pointer point to themselves.
59     // This way, direct children will receive the correct scope pointer.
60     setTreeScope(this);
61 }
62
63 ShadowRoot::~ShadowRoot()
64 {
65     ASSERT(!m_prev);
66     ASSERT(!m_next);
67
68     // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
69     // as well as Node. See a comment on TreeScope.h for the reason.
70     if (hasRareData())
71         clearRareData();
72 }
73
74 static bool allowsAuthorShadowRoot(Element* element)
75 {
76     // FIXME: ValidationMessage recreates shadow root dynamically.
77     // https://bugs.webkit.org/show_bug.cgi?id=77937
78     // Especially, INPUT recreates shadow root dynamically.
79     // https://bugs.webkit.org/show_bug.cgi?id=77930
80     if (element->isFormControlElement())
81         return false;
82
83     // FIXME: We disable multiple shadow subtrees for SVG for while, because there will be problems to support it.
84     // https://bugs.webkit.org/show_bug.cgi?id=78205
85     // Especially SVG TREF recreates shadow root dynamically.
86     // https://bugs.webkit.org/show_bug.cgi?id=77938
87     if (element->isSVGElement())
88         return false;
89
90     return true;
91 }
92
93 PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ExceptionCode& ec)
94 {
95     return create(element, AuthorShadowRoot, ec);
96 }
97
98 PassRefPtr<ShadowRoot> ShadowRoot::create(Element* element, ShadowRootType type, ExceptionCode& ec)
99 {
100     if (!element) {
101         ec = HIERARCHY_REQUEST_ERR;
102         return 0;
103     }
104
105     // Since some elements recreates shadow root dynamically, multiple shadow subtrees won't work well in that element.
106     // Until they are fixed, we disable adding author shadow root for them.
107     if (type == AuthorShadowRoot && !allowsAuthorShadowRoot(element)) {
108         ec = HIERARCHY_REQUEST_ERR;
109         return 0;
110     }
111
112     RefPtr<ShadowRoot> shadowRoot = adoptRef(new ShadowRoot(element->document()));
113 #ifndef NDEBUG
114     shadowRoot->m_type = type;
115 #endif
116
117     ec = 0;
118     element->ensureShadow()->addShadowRoot(element, shadowRoot, type, ec);
119     if (ec)
120         return 0;
121     ASSERT(element == shadowRoot->host());
122     ASSERT(element->shadow());
123     return shadowRoot.release();
124 }
125
126 String ShadowRoot::nodeName() const
127 {
128     return "#shadow-root";
129 }
130
131 PassRefPtr<Node> ShadowRoot::cloneNode(bool)
132 {
133     // ShadowRoot should not be arbitrarily cloned.
134     return 0;
135 }
136
137 String ShadowRoot::innerHTML() const
138 {
139     return createMarkup(this, ChildrenOnly);
140 }
141
142 void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
143 {
144     if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, ec))
145         replaceChildrenWithFragment(this, fragment.release(), ec);
146 }
147
148 bool ShadowRoot::childTypeAllowed(NodeType type) const
149 {
150     switch (type) {
151     case ELEMENT_NODE:
152     case PROCESSING_INSTRUCTION_NODE:
153     case COMMENT_NODE:
154     case TEXT_NODE:
155     case CDATA_SECTION_NODE:
156     case ENTITY_REFERENCE_NODE:
157         return true;
158     default:
159         return false;
160     }
161 }
162
163 ElementShadow* ShadowRoot::owner() const
164 {
165     if (host())
166         return host()->shadow();
167     return 0;
168 }
169
170 bool ShadowRoot::hasInsertionPoint() const
171 {
172     for (Node* n = firstChild(); n; n = n->traverseNextNode(this)) {
173         if (isInsertionPoint(n))
174             return true;
175     }
176
177     return false;
178 }
179
180 bool ShadowRoot::applyAuthorStyles() const
181 {
182     return m_applyAuthorStyles;
183 }
184
185 void ShadowRoot::setApplyAuthorStyles(bool value)
186 {
187     if (m_applyAuthorStyles != value) {
188         m_applyAuthorStyles = value;
189         host()->setNeedsStyleRecalc();
190     }
191 }
192
193 bool ShadowRoot::resetStyleInheritance() const
194 {
195     return m_resetStyleInheritance;
196 }
197
198 void ShadowRoot::setResetStyleInheritance(bool value)
199 {
200     if (value != m_resetStyleInheritance) {
201         m_resetStyleInheritance = value;
202         if (attached() && owner())
203             owner()->recalcStyle(Force);
204     }
205 }
206
207 void ShadowRoot::attach()
208 {
209     StyleResolver* styleResolver = document()->styleResolver();
210     styleResolver->pushParentShadowRoot(this);
211     attachChildrenIfNeeded();
212     attachAsNode();
213     styleResolver->popParentShadowRoot(this);
214 }
215
216 void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
217 {
218     ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
219     owner()->invalidateDistribution();
220 }
221
222 }