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 "ElementTraversal.h"
31#include "InsertionPoint.h"
32#include "RenderElement.h"
33#include "RuntimeEnabledFeatures.h"
34#include "StyleResolver.h"
35#include "markup.h"
36
37namespace WebCore {
38
39struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope {
40    unsigned countersAndFlags[1];
41    ContentDistributor distributor;
42    void* host;
43};
44
45COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);
46
47enum ShadowRootUsageOriginType {
48    ShadowRootUsageOriginWeb = 0,
49    ShadowRootUsageOriginNotWeb,
50    ShadowRootUsageOriginMax
51};
52
53ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
54    : DocumentFragment(document, CreateShadowRoot)
55    , TreeScope(*this, document)
56    , m_resetStyleInheritance(false)
57    , m_type(type)
58    , m_hostElement(0)
59{
60}
61
62ShadowRoot::~ShadowRoot()
63{
64    // We cannot let ContainerNode destructor call willBeDeletedFrom()
65    // for this ShadowRoot instance because TreeScope destructor
66    // clears Node::m_treeScope thus ContainerNode is no longer able
67    // to access it Document reference after that.
68    willBeDeletedFrom(document());
69
70    // We must remove all of our children first before the TreeScope destructor
71    // runs so we don't go through TreeScopeAdopter for each child with a
72    // destructed tree scope in each descendant.
73    removeDetachedChildren();
74}
75
76PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
77{
78    ec = DATA_CLONE_ERR;
79    return 0;
80}
81
82String ShadowRoot::innerHTML() const
83{
84    return createMarkup(*this, ChildrenOnly);
85}
86
87void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec)
88{
89    if (isOrphan()) {
90        ec = INVALID_ACCESS_ERR;
91        return;
92    }
93
94    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, hostElement(), AllowScriptingContent, ec))
95        replaceChildrenWithFragment(*this, fragment.release(), ec);
96}
97
98bool ShadowRoot::childTypeAllowed(NodeType type) const
99{
100    switch (type) {
101    case ELEMENT_NODE:
102    case PROCESSING_INSTRUCTION_NODE:
103    case COMMENT_NODE:
104    case TEXT_NODE:
105    case CDATA_SECTION_NODE:
106    case ENTITY_REFERENCE_NODE:
107        return true;
108    default:
109        return false;
110    }
111}
112
113void ShadowRoot::setResetStyleInheritance(bool value)
114{
115    if (isOrphan())
116        return;
117
118    if (value != m_resetStyleInheritance) {
119        m_resetStyleInheritance = value;
120        if (hostElement())
121            setNeedsStyleRecalc();
122    }
123}
124
125void ShadowRoot::childrenChanged(const ChildChange& change)
126{
127    if (isOrphan())
128        return;
129
130    ContainerNode::childrenChanged(change);
131    invalidateDistribution();
132}
133
134void ShadowRoot::removeAllEventListeners()
135{
136    DocumentFragment::removeAllEventListeners();
137    for (Node* node = firstChild(); node; node = NodeTraversal::next(node))
138        node->removeAllEventListeners();
139}
140
141}
142