예제 #1
0
inline Node* ComposedTreeWalker::traverseParentOrHost(const Node* node) const
{
    Node* parent = node->parentNode();
    if (!parent)
        return 0;
    if (!parent->isShadowRoot())
        return parent;
    ShadowRoot* shadowRoot = toShadowRoot(parent);
    ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot());
    if (!shadowRoot->isYoungest())
        return 0;
    return shadowRoot->host();
}
예제 #2
0
Node::InsertionNotificationRequest HTMLContentElement::insertedInto(ContainerNode* insertionPoint)
{
    InsertionPoint::insertedInto(insertionPoint);

    if (insertionPoint->inDocument() && isActive()) {
        ShadowRoot* root = shadowRoot();
        root->registerContentElement();
        root->owner()->setShouldCollectSelectFeatureSet();
        m_registeredWithShadowRoot = true;
    }

    return InsertionDone;
}
예제 #3
0
// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree,
// nextTraversingShadowTree to the best place, e.g. NodeTraversal.
static ShadowRoot* authorShadowRootOf(const ContainerNode& node)
{
    if (!node.isElementNode() || !isShadowHost(&node))
        return nullptr;

    ElementShadow* shadow = toElement(node).shadow();
    ASSERT(shadow);
    for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) {
        if (shadowRoot->type() == ShadowRootType::OpenByDefault || shadowRoot->type() == ShadowRootType::Open)
            return shadowRoot;
    }
    return nullptr;
}
예제 #4
0
void TreeScope::setNeedsStyleRecalcForViewportUnits() {
  for (Element* element = ElementTraversal::firstWithin(rootNode()); element;
       element = ElementTraversal::nextIncludingPseudo(*element)) {
    for (ShadowRoot* root = element->youngestShadowRoot(); root;
         root = root->olderShadowRoot())
      root->setNeedsStyleRecalcForViewportUnits();
    const ComputedStyle* style = element->computedStyle();
    if (style && style->hasViewportUnits())
      element->setNeedsStyleRecalc(LocalStyleChange,
                                   StyleChangeReasonForTracing::create(
                                       StyleChangeReason::ViewportUnits));
  }
}
예제 #5
0
void SVGTRefElement::updateReferencedText()
{
    String textContent;
    if (Element* target = SVGURIReference::targetElementFromIRIString(href(), document()))
        textContent = target->textContent();

    ASSERT(hasShadowRoot());
    ShadowRoot* root = shadowTree()->oldestShadowRoot();
    if (!root->firstChild())
        root->appendChild(SVGShadowText::create(document(), textContent), ASSERT_NO_EXCEPTION);
    else
        root->firstChild()->setTextContent(textContent, ASSERT_NO_EXCEPTION);
}
예제 #6
0
void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
{
    if (insertionPoint->inDocument() && m_registeredWithParentShadowRoot) {
        ShadowRoot* root = host()->containingShadowRoot();
        if (!root)
            root = insertionPoint->containingShadowRoot();
        if (root)
            root->removeChildShadowRoot();
        m_registeredWithParentShadowRoot = false;
    }

    DocumentFragment::removedFrom(insertionPoint);
}
ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& node)
{
    ContainerNode* parent = node.parentNode();
    if (!parent)
        return nullptr;
    if (!parent->isShadowRoot())
        return parent;
    ShadowRoot* shadowRoot = toShadowRoot(parent);
    ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot());
    if (!shadowRoot->isYoungest())
        return nullptr;
    return shadowRoot->host();
}
예제 #8
0
void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
{
    ShadowRoot* root = host()->containingShadowRoot();
    if (!root)
        root = insertionPoint->containingShadowRoot();
    if (root)
        root->removeChildShadowRoot();

    if (inActiveDocument())
        document().styleEngine()->removeTreeScope(*this);

    DocumentFragment::removedFrom(insertionPoint);
}
예제 #9
0
void ShadowTree::attach()
{
    // Children of m_selector is populated lazily in
    // ensureSelector(), and here we just ensure that it is in clean state.
    ASSERT(!selector().hasPopulated());

    selector().willSelect();
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        if (!root->attached())
            root->attach();
    }
    selector().didSelect();
}
예제 #10
0
Node* ComposedTreeWalker::traverseBackToYoungerShadowRoot(const Node* node, TraversalDirection direction)
{
    ASSERT(node);
    if (node->parentNode() && node->parentNode()->isShadowRoot()) {
        ShadowRoot* parentShadowRoot = toShadowRoot(node->parentNode());
        if (!parentShadowRoot->isYoungest()) {
            HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadowInsertionPointOfYoungerShadowRoot();
            ASSERT(assignedInsertionPoint);
            return traverseSiblingInCurrentTree(assignedInsertionPoint, direction);
        }
    }
    return 0;
}
Node* ComposedShadowTreeWalker::traverseBackToYoungerShadowRoot(const Node* node, TraversalDirection direction)
{
    ASSERT(node);
    if (node->parentNode() && node->parentNode()->isShadowRoot()) {
        ShadowRoot* parentShadowRoot = toShadowRoot(node->parentNode());
        if (!parentShadowRoot->isYoungest()) {
            InsertionPoint* assignedInsertionPoint = ScopeContentDistribution::assignedTo(parentShadowRoot);
            ASSERT(assignedInsertionPoint);
            return traverseSiblingInCurrentTree(assignedInsertionPoint, direction);
        }
    }
    return 0;
}
예제 #12
0
ShadowRoot* HTMLShadowElement::olderShadowRoot()
{
    ShadowRoot* containingRoot = containingShadowRoot();
    if (!containingRoot)
        return 0;

    ContentDistributor::ensureDistribution(containingRoot);

    ShadowRoot* older = containingRoot->olderShadowRoot();
    if (!older || older->type() != ShadowRoot::AuthorShadowRoot || ScopeContentDistribution::assignedTo(older) != this)
        return 0;

    return older;
}
예제 #13
0
static bool shouldBypassMainWorldCSP(Element* element)
{
    // Main world CSP is bypassed within an isolated world.
    LocalFrame* frame = element->document().frame();
    if (frame && frame->script().shouldBypassMainWorldCSP())
        return true;

    // Main world CSP is bypassed for style elements in user agent shadow DOM.
    ShadowRoot* root = element->containingShadowRoot();
    if (root && root->type() == ShadowRootType::UserAgent)
        return true;

    return false;
}
예제 #14
0
static void attachShadowRoot(ShadowRoot& shadowRoot)
{
    if (shadowRoot.attached())
        return;
    StyleResolver& styleResolver = shadowRoot.document().ensureStyleResolver();
    styleResolver.pushParentShadowRoot(&shadowRoot);

    attachChildren(shadowRoot);

    styleResolver.popParentShadowRoot(&shadowRoot);

    shadowRoot.clearNeedsStyleRecalc();
    shadowRoot.setAttached(true);
}
예제 #15
0
TEST(TreeScopeTest, CommonAncestorOfInclusiveTrees) {
  //  document
  //     |      : Common ancestor is document.
  // shadowRoot

  Document* document = Document::create();
  Element* html = document->createElement("html", StringOrDictionary());
  document->appendChild(html);
  ShadowRoot* shadowRoot =
      html->createShadowRootInternal(ShadowRootType::V0, ASSERT_NO_EXCEPTION);

  EXPECT_EQ(document, document->commonAncestorTreeScope(*shadowRoot));
  EXPECT_EQ(document, shadowRoot->commonAncestorTreeScope(*document));
}
예제 #16
0
void ShadowRoot::removedFrom(ContainerNode* insertionPoint)
{
    if (insertionPoint->inDocument() && m_registeredWithParentShadowRoot) {
        ShadowRoot* root = host()->containingShadowRoot();
        if (!root)
            root = insertionPoint->containingShadowRoot();

        if (root && root->scopeDistribution())
            root->scopeDistribution()->unregisterElementShadow();
        m_registeredWithParentShadowRoot = false;
    }

    DocumentFragment::removedFrom(insertionPoint);
}
예제 #17
0
// Test case for
//  - childAt
//  - countChildren
//  - hasChildren
//  - index
//  - isDescendantOf
TEST_F(FlatTreeTraversalTest, childAt) {
  const char* mainHTML =
      "<div id='m0'>"
      "<span id='m00'>m00</span>"
      "<span id='m01'>m01</span>"
      "</div>";
  const char* shadowHTML =
      "<a id='s00'>s00</a>"
      "<content select='#m01'></content>"
      "<a id='s02'>s02</a>"
      "<a id='s03'><content select='#m00'></content></a>"
      "<a id='s04'>s04</a>";
  setupSampleHTML(mainHTML, shadowHTML, 0);

  Element* body = document().body();
  Element* m0 = body->querySelector("#m0");
  Element* m00 = m0->querySelector("#m00");
  Element* m01 = m0->querySelector("#m01");

  Element* shadowHost = m0;
  ShadowRoot* shadowRoot = shadowHost->openShadowRoot();
  Element* s00 = shadowRoot->querySelector("#s00");
  Element* s02 = shadowRoot->querySelector("#s02");
  Element* s03 = shadowRoot->querySelector("#s03");
  Element* s04 = shadowRoot->querySelector("#s04");

  const unsigned numberOfChildNodes = 5;
  Node* expectedChildNodes[5] = {s00, m01, s02, s03, s04};

  ASSERT_EQ(numberOfChildNodes, FlatTreeTraversal::countChildren(*shadowHost));
  EXPECT_TRUE(FlatTreeTraversal::hasChildren(*shadowHost));

  for (unsigned index = 0; index < numberOfChildNodes; ++index) {
    Node* child = FlatTreeTraversal::childAt(*shadowHost, index);
    EXPECT_EQ(expectedChildNodes[index], child)
        << "FlatTreeTraversal::childAt(*shadowHost, " << index << ")";
    EXPECT_EQ(index, FlatTreeTraversal::index(*child))
        << "FlatTreeTraversal::index(FlatTreeTraversal(*shadowHost, " << index
        << "))";
    EXPECT_TRUE(FlatTreeTraversal::isDescendantOf(*child, *shadowHost))
        << "FlatTreeTraversal::isDescendantOf(*FlatTreeTraversal(*shadowHost, "
        << index << "), *shadowHost)";
  }
  EXPECT_EQ(nullptr,
            FlatTreeTraversal::childAt(*shadowHost, numberOfChildNodes + 1))
      << "Out of bounds childAt() returns nullptr.";

  // Distribute node |m00| is child of node in shadow tree |s03|.
  EXPECT_EQ(m00, FlatTreeTraversal::childAt(*s03, 0));
}
예제 #18
0
void ElementShadow::collectSelectFeatureSetFrom(ShadowRoot& root)
{
    if (!root.containsShadowRoots() && !root.containsContentElements())
        return;

    for (Element& element : ElementTraversal::descendantsOf(root)) {
        if (ElementShadow* shadow = element.shadow())
            m_selectFeatures.add(shadow->ensureSelectFeatureSet());
        if (!isHTMLContentElement(element))
            continue;
        const CSSSelectorList& list = toHTMLContentElement(element).selectorList();
        m_selectFeatures.collectFeaturesFromSelectorList(list);
    }
}
예제 #19
0
TEST_F(FlatTreeTraversalTest, previousPostOrder) {
  const char* mainHTML =
      "<div id='m0'>m0</div>"
      "<div id='m1'>"
      "<span id='m10'>m10</span>"
      "<span id='m11'>m11</span>"
      "</div>"
      "<div id='m2'>m2</div>";
  const char* shadowHTML =
      "<content select='#m11'></content>"
      "<a id='s11'>s11</a>"
      "<a id='s12'>"
      "<b id='s120'>s120</b>"
      "<content select='#m10'></content>"
      "</a>";
  setupSampleHTML(mainHTML, shadowHTML, 1);

  Element* body = document().body();
  Element* m0 = body->querySelector("#m0");
  Element* m1 = body->querySelector("#m1");
  Element* m2 = body->querySelector("#m2");

  Element* m10 = body->querySelector("#m10");
  Element* m11 = body->querySelector("#m11");

  ShadowRoot* shadowRoot = m1->openShadowRoot();
  Element* s11 = shadowRoot->querySelector("#s11");
  Element* s12 = shadowRoot->querySelector("#s12");
  Element* s120 = shadowRoot->querySelector("#s120");

  EXPECT_EQ(*m0->firstChild(), FlatTreeTraversal::previousPostOrder(*m0));
  EXPECT_EQ(*s12, FlatTreeTraversal::previousPostOrder(*m1));
  EXPECT_EQ(*m10->firstChild(), FlatTreeTraversal::previousPostOrder(*m10));
  EXPECT_EQ(*s120, FlatTreeTraversal::previousPostOrder(*m10->firstChild()));
  EXPECT_EQ(*s120,
            FlatTreeTraversal::previousPostOrder(*m10->firstChild(), s12));
  EXPECT_EQ(*m11->firstChild(), FlatTreeTraversal::previousPostOrder(*m11));
  EXPECT_EQ(*m0, FlatTreeTraversal::previousPostOrder(*m11->firstChild()));
  EXPECT_EQ(nullptr,
            FlatTreeTraversal::previousPostOrder(*m11->firstChild(), m11));
  EXPECT_EQ(*m2->firstChild(), FlatTreeTraversal::previousPostOrder(*m2));

  EXPECT_EQ(*s11->firstChild(), FlatTreeTraversal::previousPostOrder(*s11));
  EXPECT_EQ(*m10, FlatTreeTraversal::previousPostOrder(*s12));
  EXPECT_EQ(*s120->firstChild(), FlatTreeTraversal::previousPostOrder(*s120));
  EXPECT_EQ(*s11, FlatTreeTraversal::previousPostOrder(*s120->firstChild()));
  EXPECT_EQ(nullptr,
            FlatTreeTraversal::previousPostOrder(*s120->firstChild(), s12));
}
예제 #20
0
void TreeScopeAdopter::moveTreeToNewScope(Node& root) const
{
    ASSERT(needsScopeChange());

#if !ENABLE(OILPAN)
    m_oldScope.guardRef();
#endif

    // If an element is moved from a document and then eventually back again the collection cache for
    // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
    // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
    // we ensure that the collection cache will be invalidated as needed when the element is moved back.
    Document& oldDocument = m_oldScope.document();
    Document& newDocument = m_newScope.document();
    bool willMoveToNewDocument = oldDocument != newDocument;
    if (willMoveToNewDocument)
        oldDocument.incDOMTreeVersion();

    for (Node* node = &root; node; node = NodeTraversal::next(*node, &root)) {
        updateTreeScope(*node);

        if (willMoveToNewDocument)
            moveNodeToNewDocument(*node, oldDocument, newDocument);
        else if (node->hasRareData()) {
            NodeRareData* rareData = node->rareData();
            if (rareData->nodeLists())
                rareData->nodeLists()->adoptTreeScope();
        }

        if (!node->isElementNode())
            continue;

        if (node->hasSyntheticAttrChildNodes()) {
            WillBeHeapVector<RefPtrWillBeMember<Attr> >& attrs = *toElement(node)->attrNodeList();
            for (unsigned i = 0; i < attrs.size(); ++i)
                moveTreeToNewScope(*attrs[i]);
        }

        for (ShadowRoot* shadow = node->youngestShadowRoot(); shadow; shadow = shadow->olderShadowRoot()) {
            shadow->setParentTreeScope(m_newScope);
            if (willMoveToNewDocument)
                moveTreeToNewDocument(*shadow, oldDocument, newDocument);
        }
    }

#if !ENABLE(OILPAN)
    m_oldScope.guardDeref();
#endif
}
예제 #21
0
void TreeScopeAdopter::moveTreeToNewScope(Node& root) const
{
    ASSERT(needsScopeChange());

#if !ENABLE(OILPAN)
    oldScope().guardRef();
#endif

    // If an element is moved from a document and then eventually back again the collection cache for
    // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
    // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
    // we ensure that the collection cache will be invalidated as needed when the element is moved back.
    Document& oldDocument = oldScope().document();
    Document& newDocument = newScope().document();
    bool willMoveToNewDocument = oldDocument != newDocument;
    if (willMoveToNewDocument)
        oldDocument.incDOMTreeVersion();

    for (Node& node : NodeTraversal::inclusiveDescendantsOf(root)) {
        updateTreeScope(node);

        if (willMoveToNewDocument) {
            moveNodeToNewDocument(node, oldDocument, newDocument);
        } else if (node.hasRareData()) {
            NodeRareData* rareData = node.rareData();
            if (rareData->nodeLists())
                rareData->nodeLists()->adoptTreeScope();
        }

        if (!node.isElementNode())
            continue;
        Element& element = toElement(node);

        if (WillBeHeapVector<RefPtrWillBeMember<Attr>>* attrs = element.attrNodeList()) {
            for (const auto& attr : *attrs)
                moveTreeToNewScope(*attr);
        }

        for (ShadowRoot* shadow = element.youngestShadowRoot(); shadow; shadow = shadow->olderShadowRoot()) {
            shadow->setParentTreeScope(newScope());
            if (willMoveToNewDocument)
                moveTreeToNewDocument(*shadow, oldDocument, newDocument);
        }
    }

#if !ENABLE(OILPAN)
    oldScope().guardDeref();
#endif
}
예제 #22
0
void SVGTRefElement::updateReferencedText(Element* target)
{
    String textContent;
    if (target)
        textContent = target->textContent();

    ASSERT(shadowRoot());
    ShadowRoot* root = shadowRoot();
    if (!root->firstChild())
        root->appendChild(Text::create(document(), textContent), ASSERT_NO_EXCEPTION);
    else {
        ASSERT(root->firstChild()->isTextNode());
        root->firstChild()->setTextContent(textContent, ASSERT_NO_EXCEPTION);
    }
}
예제 #23
0
void HTMLPlugInImageElement::checkSnapshotStatus()
{
    if (!renderer()->isSnapshottedPlugIn()) {
        if (displayState() == Playing)
            checkSizeChangeForSnapshotting();
        return;
    }

    ShadowRoot* root = userAgentShadowRoot();
    if (!root)
        return;

    Element* shadowContainer = toElement(root->firstChild());
    shadowContainer->setAttribute(classAttr, classNameForShadowRoot(this));
}
예제 #24
0
void HTMLSlotElement::enqueueSlotChangeEvent() {
  if (!m_slotchangeEventEnqueued) {
    Microtask::enqueueMicrotask(WTF::bind(
        &HTMLSlotElement::dispatchSlotChangeEvent, wrapPersistent(this)));
    m_slotchangeEventEnqueued = true;
  }

  ShadowRoot* root = containingShadowRoot();
  DCHECK(root);
  DCHECK(root->isV1());
  root->owner()->setNeedsDistributionRecalc();
  // Check slotchange recursively since this slotchange may cause another
  // slotchange.
  checkSlotChange();
}
예제 #25
0
void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot& root) {
  DEFINE_STATIC_LOCAL(AtomicString, labelPadding, ("0 2px 1px 2px"));
  DEFINE_STATIC_LOCAL(AtomicString, labelMinHeight, ("1.2em"));
  HTMLDivElement* label = HTMLDivElement::create(document());
  label->setAttribute(roleAttr, AtomicString("group"));
  label->setAttribute(aria_labelAttr, AtomicString());
  label->setInlineStyleProperty(CSSPropertyPadding, labelPadding);
  label->setInlineStyleProperty(CSSPropertyMinHeight, labelMinHeight);
  label->setIdAttribute(ShadowElementNames::optGroupLabel());
  root.appendChild(label);

  HTMLContentElement* content = HTMLContentElement::create(document());
  content->setAttribute(selectAttr, "option,hr");
  root.appendChild(content);
}
예제 #26
0
void HTMLContentElement::removedFrom(ContainerNode* insertionPoint)
{
    if (insertionPoint->inDocument() && m_registeredWithShadowRoot) {
        ShadowRoot* root = shadowRoot();
        if (!root)
            root = insertionPoint->shadowRoot();
        if (root)
            root->unregisterContentElement();
        m_registeredWithShadowRoot = false;

        if (ElementShadow* elementShadow = root ? root->owner() : 0)
            elementShadow->setShouldCollectSelectFeatureSet();
    }
    InsertionPoint::removedFrom(insertionPoint);
}
예제 #27
0
void ContentDistributor::ensureDistribution(ShadowRoot* shadowRoot)
{
    ASSERT(shadowRoot);

    Vector<ShadowRoot*, 8> shadowRoots;
    for (Element* current = shadowRoot->hostElement(); current; current = current->shadowHost()) {
        ShadowRoot* currentRoot = current->shadowRoot();
        if (!currentRoot->distributor().needsDistribution())
            break;
        shadowRoots.append(currentRoot);
    }

    for (size_t i = shadowRoots.size(); i > 0; --i)
        shadowRoots[i - 1]->distributor().distribute(shadowRoots[i - 1]->hostElement());
}
예제 #28
0
nsresult
HTMLContentElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify)
{
  nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
                                              aValue, aNotify);
  NS_ENSURE_SUCCESS(rv, rv);

  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::select) {
    // Select attribute was updated, the insertion point may match different
    // elements.
    nsIDocument* doc = OwnerDoc();
    nsCSSParser parser(doc->CSSLoader());

    mValidSelector = true;
    mSelectorList = nullptr;

    nsresult rv = parser.ParseSelectorString(aValue,
                                             doc->GetDocumentURI(),
                                             // Bug 11240
                                             0, // XXX get the line number!
                                             getter_Transfers(mSelectorList));

    // We don't want to return an exception if parsing failed because
    // the spec does not define it as an exception case.
    if (NS_SUCCEEDED(rv)) {
      // Ensure that all the selectors are valid
      nsCSSSelectorList* selectors = mSelectorList;
      while (selectors) {
        if (!IsValidContentSelectors(selectors->mSelectors)) {
          // If we have an invalid selector, we can not match anything.
          mValidSelector = false;
          mSelectorList = nullptr;
          break;
        }
        selectors = selectors->mNext;
      }
    }

    ShadowRoot* containingShadow = GetContainingShadow();
    if (containingShadow) {
      containingShadow->DistributeAllNodes();
    }
  }

  return NS_OK;
}
예제 #29
0
void HTMLMarqueeElement::didAddUserAgentShadowRoot(ShadowRoot& shadowRoot) {
    Element* style = HTMLStyleElement::create(document(), false);
    style->setTextContent(
        ":host { display: inline-block; overflow: hidden;"
        "text-align: initial; white-space: nowrap; }"
        ":host([direction=\"up\"]), :host([direction=\"down\"]) { overflow: "
        "initial; overflow-y: hidden; white-space: initial; }"
        ":host > div { will-change: transform; }");
    shadowRoot.appendChild(style);

    Element* mover = HTMLDivElement::create(document());
    shadowRoot.appendChild(mover);

    mover->appendChild(HTMLContentElement::create(document()));
    m_mover = mover;
}
예제 #30
0
파일: InputType.cpp 프로젝트: dog-god/iptv
void InputType::destroyShadowSubtree()
{
    ShadowRoot* root = element()->userAgentShadowRoot();
    if (!root)
        return;

    root->removeAllChildren();

    // It's ok to clear contents of all other ShadowRoots because they must have
    // been created by TextFieldDecorationElement, and we don't allow adding
    // AuthorShadowRoot to HTMLInputElement.
    while ((root = root->youngerShadowRoot())) {
        root->removeAllChildren();
        root->appendChild(HTMLShadowElement::create(shadowTag, element()->document()));
    }
}