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 "ElementShadow.h" 32#include "HistogramSupport.h" 33#include "InsertionPoint.h" 34#include "RuntimeEnabledFeatures.h" 35#include "StyleResolver.h" 36#include "Text.h" 37#include "markup.h" 38 39namespace WebCore { 40 41struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope { 42 unsigned countersAndFlags[1]; 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(0, CreateShadowRoot) 55 , TreeScope(this, document) 56 , m_numberOfStyles(0) 57 , m_applyAuthorStyles(false) 58 , m_resetStyleInheritance(false) 59 , m_type(type) 60{ 61 ASSERT(document); 62} 63 64ShadowRoot::~ShadowRoot() 65{ 66 // We cannot let ContainerNode destructor call willBeDeletedFrom() 67 // for this ShadowRoot instance because TreeScope destructor 68 // clears Node::m_treeScope thus ContainerNode is no longer able 69 // to access it Document reference after that. 70 willBeDeletedFrom(documentInternal()); 71 72 // We must remove all of our children first before the TreeScope destructor 73 // runs so we don't go through TreeScopeAdopter for each child with a 74 // destructed tree scope in each descendant. 75 removeDetachedChildren(); 76 77 // We must call clearRareData() here since a ShadowRoot class inherits TreeScope 78 // as well as Node. See a comment on TreeScope.h for the reason. 79 if (hasRareData()) 80 clearRareData(); 81} 82 83void ShadowRoot::dispose() 84{ 85 removeDetachedChildren(); 86} 87 88PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec) 89{ 90 ec = DATA_CLONE_ERR; 91 return 0; 92} 93 94String ShadowRoot::innerHTML() const 95{ 96 return createMarkup(this, ChildrenOnly); 97} 98 99void ShadowRoot::setInnerHTML(const String& markup, ExceptionCode& ec) 100{ 101 if (isOrphan()) { 102 ec = INVALID_ACCESS_ERR; 103 return; 104 } 105 106 if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, ec)) 107 replaceChildrenWithFragment(this, fragment.release(), ec); 108} 109 110bool ShadowRoot::childTypeAllowed(NodeType type) const 111{ 112 switch (type) { 113 case ELEMENT_NODE: 114 case PROCESSING_INSTRUCTION_NODE: 115 case COMMENT_NODE: 116 case TEXT_NODE: 117 case CDATA_SECTION_NODE: 118 case ENTITY_REFERENCE_NODE: 119 return true; 120 default: 121 return false; 122 } 123} 124 125void ShadowRoot::recalcStyle(StyleChange change) 126{ 127 // ShadowRoot doesn't support custom callbacks. 128 ASSERT(!hasCustomStyleCallbacks()); 129 130 StyleResolver* styleResolver = document()->ensureStyleResolver(); 131 styleResolver->pushParentShadowRoot(this); 132 133 for (Node* child = firstChild(); child; child = child->nextSibling()) { 134 if (child->isElementNode()) 135 toElement(child)->recalcStyle(change); 136 else if (child->isTextNode()) 137 toText(child)->recalcTextStyle(change); 138 } 139 140 styleResolver->popParentShadowRoot(this); 141 clearNeedsStyleRecalc(); 142 clearChildNeedsStyleRecalc(); 143} 144 145void ShadowRoot::setApplyAuthorStyles(bool value) 146{ 147 if (isOrphan()) 148 return; 149 150 if (m_applyAuthorStyles != value) { 151 m_applyAuthorStyles = value; 152 host()->setNeedsStyleRecalc(); 153 } 154} 155 156void ShadowRoot::setResetStyleInheritance(bool value) 157{ 158 if (isOrphan()) 159 return; 160 161 if (value != m_resetStyleInheritance) { 162 m_resetStyleInheritance = value; 163 if (attached() && owner()) 164 owner()->recalcStyle(Force); 165 } 166} 167 168void ShadowRoot::attach(const AttachContext& context) 169{ 170 StyleResolver* styleResolver = document()->ensureStyleResolver(); 171 styleResolver->pushParentShadowRoot(this); 172 DocumentFragment::attach(context); 173 styleResolver->popParentShadowRoot(this); 174} 175 176void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 177{ 178 if (isOrphan()) 179 return; 180 181 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 182 owner()->invalidateDistribution(); 183} 184 185void ShadowRoot::registerScopedHTMLStyleChild() 186{ 187 ++m_numberOfStyles; 188 setHasScopedHTMLStyleChild(true); 189} 190 191void ShadowRoot::unregisterScopedHTMLStyleChild() 192{ 193 ASSERT(hasScopedHTMLStyleChild() && m_numberOfStyles > 0); 194 --m_numberOfStyles; 195 setHasScopedHTMLStyleChild(m_numberOfStyles > 0); 196} 197 198} 199