コード例 #1
0
ファイル: htmlediting.cpp プロジェクト: paul99/third_party
bool areIdenticalElements(const Node* first, const Node* second)
{
    // check that tag name and all attribute names and values are identical

    if (!first->isElementNode() || !second->isElementNode())
        return false;

    if (!toElement(first)->tagQName().matches(toElement(second)->tagQName()))
        return false;

    NamedNodeMap* firstMap = toElement(first)->attributes();
    NamedNodeMap* secondMap = toElement(second)->attributes();
    unsigned firstLength = firstMap->length();

    if (firstLength != secondMap->length())
        return false;

    for (unsigned i = 0; i < firstLength; i++) {
        Attribute* attribute = firstMap->attributeItem(i);
        Attribute* secondAttribute = secondMap->getAttributeItem(attribute->name());
        if (!secondAttribute || attribute->value() != secondAttribute->value())
            return false;
    }

    return true;
}
コード例 #2
0
static String imageToMarkup(const String& url, Element* element)
{
    StringBuilder markup;
    markup.append("<img src=\"");
    markup.append(url);
    markup.append("\"");
    // Copy over attributes.  If we are dragging an image, we expect things like
    // the id to be copied as well.
    NamedNodeMap* attrs = element->attributes();
    unsigned length = attrs->length();
    for (unsigned i = 0; i < length; ++i) {
        Attribute* attr = attrs->attributeItem(i);
        if (attr->localName() == "src")
            continue;
        markup.append(" ");
        markup.append(attr->localName());
        markup.append("=\"");
        String escapedAttr = attr->value();
        escapedAttr.replace("\"", "&quot;");
        markup.append(escapedAttr);
        markup.append("\"");
    }

    markup.append("/>");
    return markup.toString();
}
コード例 #3
0
void MarkupAccumulator::appendElement(StringBuilder& out, Element* element, Namespaces* namespaces)
{
    appendOpenTag(out, element, namespaces);

    NamedNodeMap* attributes = element->attributes();
    unsigned length = attributes->length();
    for (unsigned int i = 0; i < length; i++)
        appendAttribute(out, element, *attributes->attributeItem(i), namespaces);

    appendCloseTag(out, element);
}
コード例 #4
0
void DatasetDOMStringMap::getNames(Vector<String>& names)
{
    NamedNodeMap* attributeMap = m_element->attributes(true);
    if (attributeMap) {
        unsigned length = attributeMap->length();
        for (unsigned i = 0; i < length; i++) {
            Attribute* attribute = attributeMap->attributeItem(i);
            if (isValidAttributeName(attribute->localName()))
                names.append(convertAttributeNameToPropertyName(attribute->localName()));
        }
    }
}
コード例 #5
0
void HTMLEmbedElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues)
{
    NamedNodeMap* attributes = this->attributes(true);
    if (!attributes)
        return;

    for (unsigned i = 0; i < attributes->length(); ++i) {
        Attribute* it = attributes->attributeItem(i);
        paramNames.append(it->localName().string());
        paramValues.append(it->value().string());
    }
}
コード例 #6
0
bool DatasetDOMStringMap::contains(const String& name)
{
    NamedNodeMap* attributeMap = m_element->attributes(true);
    if (attributeMap) {
        unsigned length = attributeMap->length();
        for (unsigned i = 0; i < length; i++) {
            Attribute* attribute = attributeMap->attributeItem(i);
            if (propertyNameMatchesAttributeName(name, attribute->localName()))
                return true;
        }
    }
    return false;
}
コード例 #7
0
void StyledMarkupAccumulator::appendElement(StringBuilder& out, Element* element, bool addDisplayInline, RangeFullySelectsNode rangeFullySelectsNode)
{
    const bool documentIsHTML = element->document()->isHTMLDocument();
    appendOpenTag(out, element, 0);

    NamedNodeMap* attributes = element->attributes();
    const unsigned length = attributes->length();
    const bool shouldAnnotateOrForceInline = element->isHTMLElement() && (shouldAnnotate() || addDisplayInline);
    const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element);
    for (unsigned int i = 0; i < length; i++) {
        Attribute* attribute = attributes->attributeItem(i);
        // We'll handle the style attribute separately, below.
        if (attribute->name() == styleAttr && shouldOverrideStyleAttr)
            continue;
        appendAttribute(out, element, *attribute, 0);
    }

    if (shouldOverrideStyleAttr) {
        RefPtr<EditingStyle> newInlineStyle;

        if (shouldApplyWrappingStyle(element)) {
            newInlineStyle = m_wrappingStyle->copy();
            newInlineStyle->removePropertiesInElementDefaultStyle(element);
            newInlineStyle->removeStyleConflictingWithStyleOfNode(element);
        } else
            newInlineStyle = EditingStyle::create();

        if (element->isStyledElement() && static_cast<StyledElement*>(element)->inlineStyleDecl())
            newInlineStyle->overrideWithStyle(static_cast<StyledElement*>(element)->inlineStyleDecl());

        if (shouldAnnotateOrForceInline) {
            if (shouldAnnotate())
                newInlineStyle->mergeStyleFromRulesForSerialization(toHTMLElement(element));

            if (addDisplayInline)
                newInlineStyle->forceInline();

            // If the node is not fully selected by the range, then we don't want to keep styles that affect its relationship to the nodes around it
            // only the ones that affect it and the nodes within it.
            if (rangeFullySelectsNode == DoesNotFullySelectNode && newInlineStyle->style())
                newInlineStyle->style()->removeProperty(CSSPropertyFloat);
        }

        if (!newInlineStyle->isEmpty()) {
            DEFINE_STATIC_LOCAL(const String, stylePrefix, (" style=\""));
            out.append(stylePrefix);
            appendAttributeValue(out, newInlineStyle->style()->cssText(), documentIsHTML);
            out.append('\"');
        }
    }
コード例 #8
0
PassRefPtr<InspectorObject> InspectorCSSAgent::buildObjectForAttributeStyles(Element* element)
{
    RefPtr<InspectorObject> styleAttributes = InspectorObject::create();
    NamedNodeMap* attributes = element->attributes();
    for (unsigned i = 0; attributes && i < attributes->length(); ++i) {
        Attribute* attribute = attributes->attributeItem(i);
        if (attribute->style()) {
            String attributeName = attribute->localName();
            RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), attribute->style(), 0);
            styleAttributes->setObject(attributeName.utf8().data(), inspectorStyle->buildObjectForStyle());
        }
    }

    return styleAttributes;
}
コード例 #9
0
// FIXME: This function should not deal with url or serviceType!
void HTMLObjectElement::parametersForPlugin(Vector<String>& paramNames, Vector<String>& paramValues, String& url, String& serviceType)
{
    HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;
    String urlParameter;
    
    // Scan the PARAM children and store their name/value pairs.
    // Get the URL and type from the params if we don't already have them.
    for (Node* child = firstChild(); child; child = child->nextSibling()) {
        if (!child->hasTagName(paramTag))
            continue;

        HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
        String name = p->name();
        if (name.isEmpty())
            continue;

        uniqueParamNames.add(name.impl());
        paramNames.append(p->name());
        paramValues.append(p->value());

        // FIXME: url adjustment does not belong in this function.
        if (url.isEmpty() && urlParameter.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
            urlParameter = stripLeadingAndTrailingHTMLSpaces(p->value());
        // FIXME: serviceType calculation does not belong in this function.
        if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
            serviceType = p->value();
            size_t pos = serviceType.find(";");
            if (pos != notFound)
                serviceType = serviceType.left(pos);
        }
    }
    
    // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
    // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
    // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
    // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
    // else our Java plugin will misinterpret it. [4004531]
    String codebase;
    if (MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
        codebase = "codebase";
        uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
    }
    
    // Turn the attributes of the <object> element into arrays, but don't override <param> values.
    NamedNodeMap* attributes = this->attributes(true);
    if (attributes) {
        for (unsigned i = 0; i < attributes->length(); ++i) {
            Attribute* it = attributes->attributeItem(i);
            const AtomicString& name = it->name().localName();
            if (!uniqueParamNames.contains(name.impl())) {
                paramNames.append(name.string());
                paramValues.append(it->value().string());
            }
        }
    }
    
    mapDataParamToSrc(&paramNames, &paramValues);
    
    // HTML5 says that an object resource's URL is specified by the object's data
    // attribute, not by a param element. However, for compatibility, allow the
    // resource's URL to be given by a param named "src", "movie", "code" or "url"
    // if we know that resource points to a plug-in.
    if (url.isEmpty() && !urlParameter.isEmpty()) {
        SubframeLoader* loader = document()->frame()->loader()->subframeLoader();
        if (loader->resourceWillUsePlugin(urlParameter, serviceType, shouldPreferPlugInsForImages()))
            url = urlParameter;
    }
}
コード例 #10
0
// Result nodes are ordered in axis order. Node test (including merged predicates) is applied.
void Step::nodesInAxis(Node* context, NodeSet& nodes) const
{
    ASSERT(nodes.isEmpty());
    switch (m_axis) {
        case ChildAxis:
            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
                return;

            for (Node* n = context->firstChild(); n; n = n->nextSibling())
                if (nodeMatches(n, ChildAxis, m_nodeTest))
                    nodes.append(n);
            return;
        case DescendantAxis:
            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
                return;

            for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
                if (nodeMatches(n, DescendantAxis, m_nodeTest))
                    nodes.append(n);
            return;
        case ParentAxis:
            if (context->isAttributeNode()) {
                Element* n = static_cast<Attr*>(context)->ownerElement();
                if (nodeMatches(n, ParentAxis, m_nodeTest))
                    nodes.append(n);
            } else {
                ContainerNode* n = context->parentNode();
                if (n && nodeMatches(n, ParentAxis, m_nodeTest))
                    nodes.append(n);
            }
            return;
        case AncestorAxis: {
            Node* n = context;
            if (context->isAttributeNode()) {
                n = static_cast<Attr*>(context)->ownerElement();
                if (nodeMatches(n, AncestorAxis, m_nodeTest))
                    nodes.append(n);
            }
            for (n = n->parentNode(); n; n = n->parentNode())
                if (nodeMatches(n, AncestorAxis, m_nodeTest))
                    nodes.append(n);
            nodes.markSorted(false);
            return;
        }
        case FollowingSiblingAxis:
            if (context->nodeType() == Node::ATTRIBUTE_NODE ||
                 context->nodeType() == Node::XPATH_NAMESPACE_NODE) 
                return;
            
            for (Node* n = context->nextSibling(); n; n = n->nextSibling())
                if (nodeMatches(n, FollowingSiblingAxis, m_nodeTest))
                    nodes.append(n);
            return;
        case PrecedingSiblingAxis:
            if (context->nodeType() == Node::ATTRIBUTE_NODE ||
                 context->nodeType() == Node::XPATH_NAMESPACE_NODE)
                return;
            
            for (Node* n = context->previousSibling(); n; n = n->previousSibling())
                if (nodeMatches(n, PrecedingSiblingAxis, m_nodeTest))
                    nodes.append(n);

            nodes.markSorted(false);
            return;
        case FollowingAxis:
            if (context->isAttributeNode()) {
                Node* p = static_cast<Attr*>(context)->ownerElement();
                while ((p = p->traverseNextNode()))
                    if (nodeMatches(p, FollowingAxis, m_nodeTest))
                        nodes.append(p);
            } else {
                for (Node* p = context; !isRootDomNode(p); p = p->parentNode()) {
                    for (Node* n = p->nextSibling(); n; n = n->nextSibling()) {
                        if (nodeMatches(n, FollowingAxis, m_nodeTest))
                            nodes.append(n);
                        for (Node* c = n->firstChild(); c; c = c->traverseNextNode(n))
                            if (nodeMatches(c, FollowingAxis, m_nodeTest))
                                nodes.append(c);
                    }
                }
            }
            return;
        case PrecedingAxis: {
            if (context->isAttributeNode())
                context = static_cast<Attr*>(context)->ownerElement();

            Node* n = context;
            while (Node* parent = n->parent()) {
                for (n = n->traversePreviousNode(); n != parent; n = n->traversePreviousNode())
                    if (nodeMatches(n, PrecedingAxis, m_nodeTest))
                        nodes.append(n);
                n = parent;
            }
            nodes.markSorted(false);
            return;
        }
        case AttributeAxis: {
            if (context->nodeType() != Node::ELEMENT_NODE)
                return;

            // Avoid lazily creating attribute nodes for attributes that we do not need anyway.
            if (m_nodeTest.kind() == NodeTest::NameTest && m_nodeTest.data() != starAtom) {
                RefPtr<Node> n = static_cast<Element*>(context)->getAttributeNodeNS(m_nodeTest.namespaceURI(), m_nodeTest.data());
                if (n && n->namespaceURI() != XMLNSNames::xmlnsNamespaceURI) { // In XPath land, namespace nodes are not accessible on the attribute axis.
                    if (nodeMatches(n.get(), AttributeAxis, m_nodeTest)) // Still need to check merged predicates.
                        nodes.append(n.release());
                }
                return;
            }
            
            NamedNodeMap* attrs = context->attributes();
            if (!attrs)
                return;

            for (unsigned i = 0; i < attrs->length(); ++i) {
                RefPtr<Attr> attr = attrs->attributeItem(i)->createAttrIfNeeded(static_cast<Element*>(context));
                if (nodeMatches(attr.get(), AttributeAxis, m_nodeTest))
                    nodes.append(attr.release());
            }
            return;
        }
        case NamespaceAxis:
            // XPath namespace nodes are not implemented yet.
            return;
        case SelfAxis:
            if (nodeMatches(context, SelfAxis, m_nodeTest))
                nodes.append(context);
            return;
        case DescendantOrSelfAxis:
            if (nodeMatches(context, DescendantOrSelfAxis, m_nodeTest))
                nodes.append(context);
            if (context->isAttributeNode()) // In XPath model, attribute nodes do not have children.
                return;

            for (Node* n = context->firstChild(); n; n = n->traverseNextNode(context))
            if (nodeMatches(n, DescendantOrSelfAxis, m_nodeTest))
                nodes.append(n);
            return;
        case AncestorOrSelfAxis: {
            if (nodeMatches(context, AncestorOrSelfAxis, m_nodeTest))
                nodes.append(context);
            Node* n = context;
            if (context->isAttributeNode()) {
                n = static_cast<Attr*>(context)->ownerElement();
                if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
                    nodes.append(n);
            }
            for (n = n->parentNode(); n; n = n->parentNode())
                if (nodeMatches(n, AncestorOrSelfAxis, m_nodeTest))
                    nodes.append(n);

            nodes.markSorted(false);
            return;
        }
    }
    ASSERT_NOT_REACHED();
}
コード例 #11
0
void RenderEmbeddedObject::updateWidget(bool onlyCreateNonNetscapePlugins)
{
    if (!m_replacementText.isNull() || !node()) // Check the node in case destroy() has been called.
        return;

    String url;
    String serviceType;
    Vector<String> paramNames;
    Vector<String> paramValues;
    Frame* frame = frameView()->frame();

    // The calls to SubframeLoader::requestObject within this function can result in a plug-in being initialized.
    // This can run cause arbitrary JavaScript to run and may result in this RenderObject being detached from
    // the render tree and destroyed, causing a crash like <rdar://problem/6954546>.  By extending our lifetime
    // artifically to ensure that we remain alive for the duration of plug-in initialization.
    RenderWidgetProtector protector(this);

    if (node()->hasTagName(objectTag)) {
        HTMLObjectElement* objectElement = static_cast<HTMLObjectElement*>(node());

        objectElement->setNeedWidgetUpdate(false);
        if (!objectElement->isFinishedParsingChildren())
          return;

        // Check for a child EMBED tag.
        HTMLEmbedElement* embed = 0;
        for (Node* child = objectElement->firstChild(); child; ) {
            if (child->hasTagName(embedTag)) {
                embed = static_cast<HTMLEmbedElement*>(child);
                break;
            }
            
            if (child->hasTagName(objectTag))
                child = child->nextSibling(); // Don't descend into nested OBJECT tags
            else
                child = child->traverseNextNode(objectElement); // Otherwise descend (EMBEDs may be inside COMMENT tags)
        }

        // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
        HTMLElement* embedOrObject;
        if (embed) {
            embedOrObject = embed;
            url = embed->url();
            serviceType = embed->serviceType();
        } else
            embedOrObject = objectElement;

        // If there was no URL or type defined in EMBED, try the OBJECT tag.
        if (url.isEmpty())
            url = objectElement->url();
        if (serviceType.isEmpty())
            serviceType = objectElement->serviceType();

        HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;

        // Scan the PARAM children.
        // Get the URL and type from the params if we don't already have them.
        // Get the attributes from the params if there is no EMBED tag.
        Node* child = objectElement->firstChild();
        while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
            if (child->hasTagName(paramTag)) {
                HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
                String name = p->name();
                if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
                    url = p->value();
                if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
                    serviceType = p->value();
                    int pos = serviceType.find(";");
                    if (pos != -1)
                        serviceType = serviceType.left(pos);
                }
                if (!embed && !name.isEmpty()) {
                    uniqueParamNames.add(name.impl());
                    paramNames.append(p->name());
                    paramValues.append(p->value());
                }
            }
            child = child->nextSibling();
        }

        // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
        // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
        // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
        // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
        // else our Java plugin will misinterpret it. [4004531]
        String codebase;
        if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
            codebase = "codebase";
            uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
        }
        
        // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
        NamedNodeMap* attributes = embedOrObject->attributes();
        if (attributes) {
            for (unsigned i = 0; i < attributes->length(); ++i) {
                Attribute* it = attributes->attributeItem(i);
                const AtomicString& name = it->name().localName();
                if (embed || !uniqueParamNames.contains(name.impl())) {
                    paramNames.append(name.string());
                    paramValues.append(it->value().string());
                }
            }
        }

        mapDataParamToSrc(&paramNames, &paramValues);

        // If we still don't have a type, try to map from a specific CLASSID to a type.
        if (serviceType.isEmpty())
            serviceType = serviceTypeForClassId(objectElement->classId());

        if (!isURLAllowed(document(), url))
            return;

        // Find out if we support fallback content.
        m_hasFallbackContent = false;
        for (Node* child = objectElement->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
            if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag))  // Discount <embed> and <param>
                || (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace()))
                m_hasFallbackContent = true;
        }

        if (onlyCreateNonNetscapePlugins) {
            KURL completedURL;
            if (!url.isEmpty())
                completedURL = frame->loader()->completeURL(url);

            if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
                return;
        }

        bool beforeLoadAllowedLoad = objectElement->dispatchBeforeLoadEvent(url);
        
        // beforeload events can modify the DOM, potentially causing
        // RenderWidget::destroy() to be called.  Ensure we haven't been
        // destroyed before continuing.
        if (!node())
            return;
        
        bool success = beforeLoadAllowedLoad && frame->loader()->subframeLoader()->requestObject(this, url, objectElement->getAttribute(nameAttr), serviceType, paramNames, paramValues);
    
        if (!success && m_hasFallbackContent)
            objectElement->renderFallbackContent();

    } else if (node()->hasTagName(embedTag)) {
        HTMLEmbedElement* embedElement = static_cast<HTMLEmbedElement*>(node());
        embedElement->setNeedWidgetUpdate(false);
        url = embedElement->url();
        serviceType = embedElement->serviceType();

        if (url.isEmpty() && serviceType.isEmpty())
            return;
        if (!isURLAllowed(document(), url))
            return;

        // add all attributes set on the embed object
        NamedNodeMap* attributes = embedElement->attributes();
        if (attributes) {
            for (unsigned i = 0; i < attributes->length(); ++i) {
                Attribute* it = attributes->attributeItem(i);
                paramNames.append(it->name().localName().string());
                paramValues.append(it->value().string());
            }
        }

        if (onlyCreateNonNetscapePlugins) {
            KURL completedURL;
            if (!url.isEmpty())
                completedURL = frame->loader()->completeURL(url);

            if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
                return;
        }

        if (embedElement->dispatchBeforeLoadEvent(url))
            frame->loader()->subframeLoader()->requestObject(this, url, embedElement->getAttribute(nameAttr), serviceType, paramNames, paramValues);
    }
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)        
    else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) {
        HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node());
        KURL kurl;

        mediaElement->getPluginProxyParams(kurl, paramNames, paramValues);
        mediaElement->setNeedWidgetUpdate(false);
        frame->loader()->subframeLoader()->loadMediaPlayerProxyPlugin(node(), kurl, paramNames, paramValues);
    }
#endif
}