Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / shadow / ShadowRoot.cpp
index 95865b8..d346a20 100644 (file)
 #include "config.h"
 #include "core/dom/shadow/ShadowRoot.h"
 
-#include "bindings/v8/ExceptionMessages.h"
-#include "bindings/v8/ExceptionState.h"
+#include "bindings/core/v8/ExceptionState.h"
 #include "core/css/StyleSheetList.h"
 #include "core/css/resolver/StyleResolver.h"
+#include "core/css/resolver/StyleResolverParentScope.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/StyleEngine.h"
 #include "core/dom/Text.h"
-#include "core/dom/WhitespaceChildList.h"
 #include "core/dom/shadow/ElementShadow.h"
 #include "core/dom/shadow/InsertionPoint.h"
 #include "core/dom/shadow/ShadowRootRareData.h"
 #include "core/editing/markup.h"
+#include "core/html/HTMLShadowElement.h"
 #include "public/platform/Platform.h"
 
-namespace WebCore {
+namespace blink {
 
 struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> {
     void* pointers[3];
@@ -50,42 +50,28 @@ struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope, public
 
 COMPILE_ASSERT(sizeof(ShadowRoot) == sizeof(SameSizeAsShadowRoot), shadowroot_should_stay_small);
 
-enum ShadowRootUsageOriginType {
-    ShadowRootUsageOriginWeb = 0,
-    ShadowRootUsageOriginNotWeb,
-    ShadowRootUsageOriginMax
-};
-
-ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
+ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
     : DocumentFragment(0, CreateShadowRoot)
-    , TreeScope(this, document)
-    , m_prev(0)
-    , m_next(0)
+    , TreeScope(*this, document)
+    , m_prev(nullptr)
+    , m_next(nullptr)
     , m_numberOfStyles(0)
-    , m_applyAuthorStyles(false)
-    , m_resetStyleInheritance(false)
     , m_type(type)
     , m_registeredWithParentShadowRoot(false)
-    , m_childInsertionPointsIsValid(false)
+    , m_descendantInsertionPointsIsValid(false)
 {
-    ASSERT(document);
-    ScriptWrappable::init(this);
-
-    if (type == ShadowRoot::AuthorShadowRoot) {
-        ShadowRootUsageOriginType usageType = document->url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
-        WebKit::Platform::current()->histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
-    }
 }
 
 ShadowRoot::~ShadowRoot()
 {
+#if !ENABLE(OILPAN)
     ASSERT(!m_prev);
     ASSERT(!m_next);
 
     if (m_shadowRootRareData && m_shadowRootRareData->styleSheets())
         m_shadowRootRareData->styleSheets()->detachFromDocument();
 
-    documentInternal()->styleEngine()->didRemoveShadowRoot(this);
+    document().styleEngine()->didRemoveShadowRoot(this);
 
     // We cannot let ContainerNode destructor call willBeDeletedFromDocument()
     // for this ShadowRoot instance because TreeScope destructor
@@ -102,14 +88,17 @@ ShadowRoot::~ShadowRoot()
     // as well as Node. See a comment on TreeScope.h for the reason.
     if (hasRareData())
         clearRareData();
+#endif
 }
 
+#if !ENABLE(OILPAN)
 void ShadowRoot::dispose()
 {
     removeDetachedChildren();
 }
+#endif
 
-ShadowRoot* ShadowRoot::bindingsOlderShadowRoot() const
+ShadowRoot* ShadowRoot::olderShadowRootForBindings() const
 {
     ShadowRoot* older = olderShadowRoot();
     while (older && !older->shouldExposeToBindings())
@@ -118,19 +107,10 @@ ShadowRoot* ShadowRoot::bindingsOlderShadowRoot() const
     return older;
 }
 
-bool ShadowRoot::isOldestAuthorShadowRoot() const
+PassRefPtrWillBeRawPtr<Node> ShadowRoot::cloneNode(bool, ExceptionState& exceptionState)
 {
-    if (type() != AuthorShadowRoot)
-        return false;
-    if (ShadowRoot* older = olderShadowRoot())
-        return older->type() == UserAgentShadowRoot;
-    return true;
-}
-
-PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionState& es)
-{
-    es.throwDOMException(DataCloneError, ExceptionMessages::failedToExecute("cloneNode", "ShadowRoot", "ShadowRoot nodes are not clonable."));
-    return 0;
+    exceptionState.throwDOMException(DataCloneError, "ShadowRoot nodes are not clonable.");
+    return nullptr;
 }
 
 String ShadowRoot::innerHTML() const
@@ -138,29 +118,15 @@ String ShadowRoot::innerHTML() const
     return createMarkup(this, ChildrenOnly);
 }
 
-void ShadowRoot::setInnerHTML(const String& markup, ExceptionState& es)
+void ShadowRoot::setInnerHTML(const String& markup, ExceptionState& exceptionState)
 {
     if (isOrphan()) {
-        es.throwDOMException(InvalidAccessError, ExceptionMessages::failedToExecute("setInnerHTML", "ShadowRoot", "The ShadowRoot does not have a host."));
+        exceptionState.throwDOMException(InvalidAccessError, "The ShadowRoot does not have a host.");
         return;
     }
 
-    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, "innerHTML", es))
-        replaceChildrenWithFragment(this, fragment.release(), es);
-}
-
-bool ShadowRoot::childTypeAllowed(NodeType type) const
-{
-    switch (type) {
-    case ELEMENT_NODE:
-    case PROCESSING_INSTRUCTION_NODE:
-    case COMMENT_NODE:
-    case TEXT_NODE:
-    case CDATA_SECTION_NODE:
-        return true;
-    default:
-        return false;
-    }
+    if (RefPtrWillBeRawPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, "innerHTML", exceptionState))
+        replaceChildrenWithFragment(this, fragment.release(), exceptionState);
 }
 
 void ShadowRoot::recalcStyle(StyleRecalcChange change)
@@ -168,92 +134,22 @@ void ShadowRoot::recalcStyle(StyleRecalcChange change)
     // ShadowRoot doesn't support custom callbacks.
     ASSERT(!hasCustomStyleCallbacks());
 
-    StyleResolver* styleResolver = document().styleResolver();
-    styleResolver->pushParentShadowRoot(*this);
+    StyleResolverParentScope parentScope(*this);
 
-    // When we're set to lazyAttach we'll have a SubtreeStyleChange and we'll need
-    // to promote the change to a Force for all our descendants so they get a
-    // recalc and will attach.
     if (styleChangeType() >= SubtreeStyleChange)
         change = Force;
 
-    // FIXME: This doesn't handle :hover + div properly like Element::recalcStyle does.
-    WhitespaceChildList whitespaceChildList(change);
-    for (Node* child = lastChild(); child; child = child->previousSibling()) {
-        if (child->isTextNode()) {
-            Text* textChild = toText(child);
-            if (textChild->containsOnlyWhitespace())
-                whitespaceChildList.append(textChild);
-            else
-                textChild->recalcTextStyle(change);
-        } else if (child->isElementNode() && shouldRecalcStyle(change, child)) {
-            toElement(child)->recalcStyle(change);
-        }
-    }
-
-    whitespaceChildList.recalcStyle();
-
-    styleResolver->popParentShadowRoot(*this);
+    // There's no style to update so just calling recalcStyle means we're updated.
     clearNeedsStyleRecalc();
-    clearChildNeedsStyleRecalc();
-    setAttached();
-}
-
-bool ShadowRoot::isActive() const
-{
-    for (ShadowRoot* shadowRoot = youngerShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot())
-        if (!shadowRoot->containsShadowElements())
-            return false;
-    return true;
-}
-
-void ShadowRoot::setApplyAuthorStyles(bool value)
-{
-    if (isOrphan())
-        return;
 
-    if (m_applyAuthorStyles == value)
-        return;
-
-    m_applyAuthorStyles = value;
-    if (!isActive())
-        return;
-
-    ASSERT(host());
-    ASSERT(host()->shadow());
-    if (host()->shadow()->didAffectApplyAuthorStyles())
-        host()->setNeedsStyleRecalc();
-
-    // Since styles in shadow trees can select shadow hosts, set shadow host's needs-recalc flag true.
-    // FIXME: host->setNeedsStyleRecalc() should take care of all elements in its shadow tree.
-    // However, when host's recalcStyle is skipped (i.e. host's parent has no renderer),
-    // no recalc style is invoked for any elements in its shadow tree.
-    // This problem occurs when using getComputedStyle() API.
-    // So currently host and shadow root's needsStyleRecalc flags are set to be true.
-    setNeedsStyleRecalc();
-}
-
-void ShadowRoot::setResetStyleInheritance(bool value)
-{
-    if (isOrphan())
-        return;
-
-    if (value == m_resetStyleInheritance)
-        return;
-
-    m_resetStyleInheritance = value;
-    if (!isActive())
-        return;
-
-    setNeedsStyleRecalc();
+    recalcChildStyle(change);
+    clearChildNeedsStyleRecalc();
 }
 
 void ShadowRoot::attach(const AttachContext& context)
 {
-    StyleResolver* styleResolver = document().styleResolver();
-    styleResolver->pushParentShadowRoot(*this);
+    StyleResolverParentScope parentScope(*this);
     DocumentFragment::attach(context);
-    styleResolver->popParentShadowRoot(*this);
 }
 
 Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode* insertionPoint)
@@ -291,9 +187,13 @@ void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
     DocumentFragment::removedFrom(insertionPoint);
 }
 
-void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
+void ShadowRoot::childrenChanged(const ChildrenChange& change)
 {
-    ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+    ContainerNode::childrenChanged(change);
+
+    if (change.isChildElementChange())
+        checkForSiblingStyleChanges(change.type == ElementRemoved ? SiblingElementRemoved : SiblingElementInserted, change.siblingBeforeChange, change.siblingAfterChange);
+
     if (InsertionPoint* point = shadowInsertionPointOfYoungerShadowRoot()) {
         if (ShadowRoot* root = point->containingShadowRoot())
             root->owner()->setNeedsDistributionRecalc();
@@ -303,14 +203,12 @@ void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node*
 void ShadowRoot::registerScopedHTMLStyleChild()
 {
     ++m_numberOfStyles;
-    setHasScopedHTMLStyleChild(true);
 }
 
 void ShadowRoot::unregisterScopedHTMLStyleChild()
 {
-    ASSERT(hasScopedHTMLStyleChild() && m_numberOfStyles > 0);
+    ASSERT(m_numberOfStyles > 0);
     --m_numberOfStyles;
-    setHasScopedHTMLStyleChild(m_numberOfStyles > 0);
 }
 
 ShadowRootRareData* ShadowRoot::ensureShadowRootRareData()
@@ -318,7 +216,7 @@ ShadowRootRareData* ShadowRoot::ensureShadowRootRareData()
     if (m_shadowRootRareData)
         return m_shadowRootRareData.get();
 
-    m_shadowRootRareData = adoptPtr(new ShadowRootRareData);
+    m_shadowRootRareData = adoptPtrWillBeNoop(new ShadowRootRareData);
     return m_shadowRootRareData.get();
 }
 
@@ -347,7 +245,7 @@ HTMLShadowElement* ShadowRoot::shadowInsertionPointOfYoungerShadowRoot() const
     return m_shadowRootRareData ? m_shadowRootRareData->shadowInsertionPointOfYoungerShadowRoot() : 0;
 }
 
-void ShadowRoot::setShadowInsertionPointOfYoungerShadowRoot(PassRefPtr<HTMLShadowElement> shadowInsertionPoint)
+void ShadowRoot::setShadowInsertionPointOfYoungerShadowRoot(PassRefPtrWillBeRawPtr<HTMLShadowElement> shadowInsertionPoint)
 {
     if (!m_shadowRootRareData && !shadowInsertionPoint)
         return;
@@ -357,13 +255,13 @@ void ShadowRoot::setShadowInsertionPointOfYoungerShadowRoot(PassRefPtr<HTMLShado
 void ShadowRoot::didAddInsertionPoint(InsertionPoint* insertionPoint)
 {
     ensureShadowRootRareData()->didAddInsertionPoint(insertionPoint);
-    invalidateChildInsertionPoints();
+    invalidateDescendantInsertionPoints();
 }
 
 void ShadowRoot::didRemoveInsertionPoint(InsertionPoint* insertionPoint)
 {
     m_shadowRootRareData->didRemoveInsertionPoint(insertionPoint);
-    invalidateChildInsertionPoints();
+    invalidateDescendantInsertionPoints();
 }
 
 void ShadowRoot::addChildShadowRoot()
@@ -384,29 +282,26 @@ unsigned ShadowRoot::childShadowRootCount() const
     return m_shadowRootRareData ? m_shadowRootRareData->childShadowRootCount() : 0;
 }
 
-void ShadowRoot::invalidateChildInsertionPoints()
+void ShadowRoot::invalidateDescendantInsertionPoints()
 {
-    m_childInsertionPointsIsValid = false;
+    m_descendantInsertionPointsIsValid = false;
     m_shadowRootRareData->clearDescendantInsertionPoints();
 }
 
-const Vector<RefPtr<InsertionPoint> >& ShadowRoot::descendantInsertionPoints()
+const WillBeHeapVector<RefPtrWillBeMember<InsertionPoint> >& ShadowRoot::descendantInsertionPoints()
 {
-    DEFINE_STATIC_LOCAL(const Vector<RefPtr<InsertionPoint> >, emptyList, ());
-
-    if (m_shadowRootRareData && m_childInsertionPointsIsValid)
+    DEFINE_STATIC_LOCAL(WillBePersistentHeapVector<RefPtrWillBeMember<InsertionPoint> >, emptyList, ());
+    if (m_shadowRootRareData && m_descendantInsertionPointsIsValid)
         return m_shadowRootRareData->descendantInsertionPoints();
 
-    m_childInsertionPointsIsValid = true;
+    m_descendantInsertionPointsIsValid = true;
 
     if (!containsInsertionPoints())
         return emptyList;
 
-    Vector<RefPtr<InsertionPoint> > insertionPoints;
-    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this)) {
-        if (element->isInsertionPoint())
-            insertionPoints.append(toInsertionPoint(element));
-    }
+    WillBeHeapVector<RefPtrWillBeMember<InsertionPoint> > insertionPoints;
+    for (InsertionPoint& insertionPoint : Traversal<InsertionPoint>::descendantsOf(*this))
+        insertionPoints.append(&insertionPoint);
 
     ensureShadowRootRareData()->setDescendantInsertionPoints(insertionPoints);
 
@@ -421,4 +316,13 @@ StyleSheetList* ShadowRoot::styleSheets()
     return m_shadowRootRareData->styleSheets();
 }
 
+void ShadowRoot::trace(Visitor* visitor)
+{
+    visitor->trace(m_prev);
+    visitor->trace(m_next);
+    visitor->trace(m_shadowRootRareData);
+    TreeScope::trace(visitor);
+    DocumentFragment::trace(visitor);
+}
+
 }