void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
{
    ASSERT(!m_targetElementInstance);
    ASSERT(!m_needsShadowTreeRecreation);

    // <use> creates a "user agent" shadow root. Do not build the shadow/instance tree for <use>
    // elements living in a user agent shadow tree because they will get expanded in a second
    // pass -- see expandUseElementsInShadowTree().
    if (inUseShadowTree())
        return;

    // Do not allow self-referencing.
    // 'target' may be null, if it's a non SVG namespaced element.
    if (!target || target == this || isDisallowedElement(target))
        return;

    // Set up root SVG element in shadow tree.
    RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren();
    m_targetElementInstance = toSVGElement(newChild.get());
    ShadowRoot* shadowTreeRootElement = userAgentShadowRoot();
    shadowTreeRootElement->appendChild(newChild.release());

    // Clone the target subtree into the shadow tree, not handling <use> and <symbol> yet.

    // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!
    // Non-appearing <use> content is easier to debug, then half-appearing content.
    if (!buildShadowTree(target, m_targetElementInstance.get(), false)) {
        clearShadowTree();
        return;
    }

    if (instanceTreeIsLoading(m_targetElementInstance.get()))
        return;

    // Assure shadow tree building was successfull
    ASSERT(m_targetElementInstance);
    ASSERT(m_targetElementInstance->correspondingUseElement() == this);
    ASSERT(m_targetElementInstance->correspondingElement() == target);

    // Expand all <use> elements in the shadow tree.
    // Expand means: replace the actual <use> element by what it references.
    if (!expandUseElementsInShadowTree(m_targetElementInstance.get())) {
        clearShadowTree();
        return;
    }

    // Expand all <symbol> elements in the shadow tree.
    // Expand means: replace the actual <symbol> element by the <svg> element.
    expandSymbolElementsInShadowTree(toSVGElement(shadowTreeRootElement->firstChild()));

    m_targetElementInstance = toSVGElement(shadowTreeRootElement->firstChild());
    transferUseWidthAndHeightIfNeeded(*this, m_targetElementInstance.get(), *m_targetElementInstance->correspondingElement());

    ASSERT(m_targetElementInstance->parentNode() == shadowTreeRootElement);

    // Update relative length information.
    updateRelativeLengthsInformation();
}
Exemple #2
0
void SVGTRefElement::updateReferencedText()
{
    String textContent;
    if (Element* target = SVGURIReference::targetElementFromIRIString(href(), document()))
        textContent = target->textContent();

    ASSERT(shadow());
    ShadowRoot* root = shadow()->oldestShadowRoot();
    if (!root->firstChild())
        root->appendChild(SVGShadowText::create(document(), textContent), ASSERT_NO_EXCEPTION);
    else
        root->firstChild()->setTextContent(textContent, ASSERT_NO_EXCEPTION);
}
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);
    }
}
Exemple #4
0
void ShadowTree::recalcShadowTreeStyle(Node::StyleChange change)
{
    ShadowRoot* youngest = youngestShadowRoot();
    if (!youngest)
        return;

    if (needsReattachHostChildrenAndShadow())
        reattachHostChildrenAndShadow();
    else {
        StyleResolver* styleResolver = youngest->document()->styleResolver();

        styleResolver->pushParentShadowRoot(youngest);
        for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) {
            if (n->isElementNode())
                static_cast<Element*>(n)->recalcStyle(change);
            else if (n->isTextNode())
                toText(n)->recalcTextStyle(change);
        }
        styleResolver->popParentShadowRoot(youngest);
    }

    clearNeedsReattachHostChildrenAndShadow();
    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        root->clearNeedsStyleRecalc();
        root->clearChildNeedsStyleRecalc();
    }
}
static inline void getDecorationRootAndDecoratedRoot(HTMLInputElement* input, ShadowRoot*& decorationRoot, ShadowRoot*& decoratedRoot)
{
    ShadowRoot* existingRoot = input->youngestShadowRoot();
    ShadowRoot* newRoot = 0;
    while (existingRoot->childNodeCount() == 1 && existingRoot->firstChild()->hasTagName(shadowTag)) {
        newRoot = existingRoot;
        existingRoot = existingRoot->olderShadowRoot();
        ASSERT(existingRoot);
    }
    if (newRoot)
        newRoot->removeChild(newRoot->firstChild());
    else
        newRoot = ShadowRoot::create(input, ShadowRoot::UserAgentShadowRoot, ASSERT_NO_EXCEPTION).get();
    decorationRoot = newRoot;
    decoratedRoot = existingRoot;
}
SliderThumbElement* sliderThumbElementOf(Node* node)
{
    ASSERT(node);
    ShadowRoot* shadow = node->toInputElement()->shadowTree()->oldestShadowRoot();
    ASSERT(shadow);
    Node* thumb = shadow->firstChild()->firstChild()->firstChild();
    ASSERT(thumb);
    return toSliderThumbElement(thumb);
}
void HTMLPlugInImageElement::updateSnapshotInfo()
{
    ShadowRoot* root = userAgentShadowRoot();
    if (!root)
        return;

    Element* shadowContainer = toElement(root->firstChild());
    shadowContainer->setAttribute(classAttr, classNameForShadowRoot(this, m_isPrimarySnapshottedPlugIn));
}
HTMLElement* sliderTrackElementOf(Node* node)
{
    RELEASE_ASSERT(node->hasTagName(inputTag));
    ShadowRoot* shadow = toHTMLInputElement(node)->userAgentShadowRoot();
    ASSERT(shadow);
    Node* track = shadow->firstChild()->firstChild();
    ASSERT(track);
    return toHTMLElement(track);
}
Exemple #9
0
TrackLimiterElement* trackLimiterElementOf(Node* node)
{
    ASSERT(node);
    ShadowRoot* shadow = node->toInputElement()->shadowRoot();
    ASSERT(shadow);
    Node* limiter = shadow->firstChild()->lastChild();
    ASSERT(limiter);
    return static_cast<TrackLimiterElement*>(limiter);
}
Exemple #10
0
HTMLElement* sliderTrackElementOf(Node* node)
{
    ASSERT(node);
    ShadowRoot* shadow = node->toInputElement()->userAgentShadowRoot();
    ASSERT(shadow);
    Node* track = shadow->firstChild()->firstChild();
    ASSERT(track);
    return toHTMLElement(track);
}
Exemple #11
0
static inline void getDecorationRootAndDecoratedRoot(HTMLInputElement* input, ShadowRoot*& decorationRoot, ShadowRoot*& decoratedRoot)
{
    ShadowRoot* existingRoot = input->youngestShadowRoot();
    ShadowRoot* newRoot = 0;
    while (existingRoot->childNodeCount() == 1 && existingRoot->firstChild()->hasTagName(shadowTag)) {
        newRoot = existingRoot;
        existingRoot = existingRoot->olderShadowRoot();
        ASSERT(existingRoot);
    }
    if (newRoot)
        newRoot->removeChild(newRoot->firstChild());
    else {
        // FIXME: This interacts really badly with author shadow roots because now
        // we can interleave user agent and author shadow roots on the element meaning
        // input.shadowRoot may be inaccessible if the browser has decided to decorate
        // the input.
        newRoot = input->ensureShadow()->addShadowRoot(input, ShadowRoot::UserAgentShadowRoot);
    }
    decorationRoot = newRoot;
    decoratedRoot = existingRoot;
}
Exemple #12
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));
}
Exemple #13
0
void HTMLImageElement::destroyImageControls()
{
    ShadowRoot* shadowRoot = userAgentShadowRoot();
    if (!shadowRoot)
        return;

    if (Node* node = shadowRoot->firstChild()) {
        ASSERT_WITH_SECURITY_IMPLICATION(node->isImageControlsRootElement());
        shadowRoot->removeChild(*node);
    }

    auto* renderObject = renderer();
    if (!renderObject)
        return;

    downcast<RenderImage>(*renderObject).setHasShadowControls(false);
}
void TextFieldDecorationElement::decorate(HTMLInputElement* input, bool visible)
{
    ASSERT(input);
    ShadowRoot* existingRoot;
    ShadowRoot* decorationRoot;
    getDecorationRootAndDecoratedRoot(input, decorationRoot, existingRoot);
    ASSERT(decorationRoot);
    ASSERT(existingRoot);
    RefPtr<HTMLDivElement> box = HTMLDivElement::create(input->document());
    decorationRoot->appendChild(box);
    box->setInlineStyleProperty(CSSPropertyDisplay, CSSValueWebkitBox);
    box->setInlineStyleProperty(CSSPropertyWebkitBoxAlign, CSSValueCenter);
    ASSERT(existingRoot->childNodeCount() == 1);
    toHTMLElement(existingRoot->firstChild())->setInlineStyleProperty(CSSPropertyWebkitBoxFlex, 1.0, CSSPrimitiveValue::CSS_NUMBER);
    box->appendChild(HTMLShadowElement::create(HTMLNames::shadowTag, input->document()));

    setInlineStyleProperty(CSSPropertyDisplay, visible ? CSSValueBlock : CSSValueNone);
    box->appendChild(this);
}
bool RuleFeatureSet::invalidateStyleForClassChangeOnChildren(Element* element, Vector<AtomicString>& invalidationClasses, bool foundInvalidationSet)
{
    bool someChildrenNeedStyleRecalc = false;
    for (ShadowRoot* root = element->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
        for (Node* child = root->firstChild(); child; child = child->nextSibling()) {
            if (child->isElementNode()) {
                Element* childElement = toElement(child);
                bool childRecalced = invalidateStyleForClassChange(childElement, invalidationClasses, foundInvalidationSet);
                someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
            }
        }
    }
    for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
        if (child->isElementNode()) {
            Element* childElement = toElement(child);
            bool childRecalced = invalidateStyleForClassChange(childElement, invalidationClasses, foundInvalidationSet);
            someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced;
        }
    }
    return someChildrenNeedStyleRecalc;
}
Exemple #16
0
HTMLElement* ColorInputType::shadowColorSwatch() const
{
    ShadowRoot* shadow = element().userAgentShadowRoot();
    return shadow ? downcast<HTMLElement>(shadow->firstChild()->firstChild()) : nullptr;
}
Exemple #17
0
HTMLSelectElement* HTMLKeygenElement::shadowSelect() const
{
    ShadowRoot* shadow = shadowRoot();
    ASSERT(shadow);
    return shadow ? static_cast<HTMLSelectElement*>(shadow->firstChild()) : 0;
}
HTMLElement* ColorInputType::shadowColorSwatch() const
{
    ShadowRoot* shadow = element()->userAgentShadowRoot();
    return shadow ? toHTMLElement(shadow->firstChild()->firstChild()) : 0;
}
Exemple #19
0
HTMLSelectElement* HTMLKeygenElement::shadowSelect() const
{
    ShadowRoot* root = userAgentShadowRoot();
    return root ? toHTMLSelectElement(root->firstChild()) : 0;
}
Exemple #20
0
void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
{
    ASSERT(!m_targetElementInstance);

    // Do not build the shadow/instance tree for <use> elements living in a shadow tree.
    // The will be expanded soon anyway - see expandUseElementsInShadowTree().
    if (isInShadowTree())
        return;

    // Do not allow self-referencing.
    // 'target' may be null, if it's a non SVG namespaced element.
    if (!target || target == this)
        return;

    // Why a seperated instance/shadow tree? SVG demands it:
    // The instance tree is accesable from JavaScript, and has to
    // expose a 1:1 copy of the referenced tree, whereas internally we need
    // to alter the tree for correct "use-on-symbol", "use-on-svg" support.

    // Build instance tree. Create root SVGElementInstance object for the first sub-tree node.
    //
    // Spec: If the 'use' element references a simple graphics element such as a 'rect', then there is only a
    // single SVGElementInstance object, and the correspondingElement attribute on this SVGElementInstance object
    // is the SVGRectElement that corresponds to the referenced 'rect' element.
    m_targetElementInstance = SVGElementInstance::create(this, this, target);

    // Eventually enter recursion to build SVGElementInstance objects for the sub-tree children
    bool foundProblem = false;
    buildInstanceTree(target, m_targetElementInstance.get(), foundProblem, false);

    if (instanceTreeIsLoading(m_targetElementInstance.get()))
        return;

    // SVG specification does not say a word about <use> & cycles. My view on this is: just ignore it!
    // Non-appearing <use> content is easier to debug, then half-appearing content.
    if (foundProblem) {
        clearResourceReferences();
        return;
    }

    // Assure instance tree building was successfull
    ASSERT(m_targetElementInstance);
    ASSERT(!m_targetElementInstance->shadowTreeElement());
    ASSERT(m_targetElementInstance->correspondingUseElement() == this);
    ASSERT(m_targetElementInstance->directUseElement() == this);
    ASSERT(m_targetElementInstance->correspondingElement() == target);

    ShadowRoot* shadowTreeRootElement = shadowRoot();
    ASSERT(shadowTreeRootElement);

    // Build shadow tree from instance tree
    // This also handles the special cases: <use> on <symbol>, <use> on <svg>.
    buildShadowTree(target, m_targetElementInstance.get());

    // Expand all <use> elements in the shadow tree.
    // Expand means: replace the actual <use> element by what it references.
    expandUseElementsInShadowTree(shadowTreeRootElement);

    // Expand all <symbol> elements in the shadow tree.
    // Expand means: replace the actual <symbol> element by the <svg> element.
    expandSymbolElementsInShadowTree(shadowTreeRootElement);

    // Now that the shadow tree is completly expanded, we can associate
    // shadow tree elements <-> instances in the instance tree.
    associateInstancesWithShadowTreeElements(shadowTreeRootElement->firstChild(), m_targetElementInstance.get());

    // If no shadow tree element is present, this means that the reference root
    // element was removed, as it is disallowed (ie. <use> on <foreignObject>)
    // Do NOT leave an inconsistent instance tree around, instead destruct it.
    if (!m_targetElementInstance->shadowTreeElement()) {
        clearResourceReferences();
        return;
    }

    ASSERT(m_targetElementInstance->shadowTreeElement()->parentNode() == shadowTreeRootElement);

    // Transfer event listeners assigned to the referenced element to our shadow tree elements.
    transferEventListenersToShadowTree(m_targetElementInstance.get());

    // Update relative length information.
    updateRelativeLengthsInformation();

    // Eventually dump instance tree
#ifdef DUMP_INSTANCE_TREE
    String text;
    unsigned int depth = 0;

    dumpInstanceTree(depth, text, m_targetElementInstance.get());
    fprintf(stderr, "\nDumping <use> instance tree:\n%s\n", text.latin1().data());
#endif

    // Eventually dump shadow tree
#ifdef DUMP_SHADOW_TREE
    RefPtr<XMLSerializer> serializer = XMLSerializer::create();
    String markup = serializer->serializeToString(shadowTreeRootElement, ASSERT_NO_EXCEPTION);
    fprintf(stderr, "Dumping <use> shadow tree markup:\n%s\n", markup.latin1().data());
#endif
}