bool DOMPatchSupport::innerPatchNode(Digest* oldDigest, Digest* newDigest, ExceptionState& exceptionState) { if (oldDigest->m_sha1 == newDigest->m_sha1) return true; Node* oldNode = oldDigest->m_node; Node* newNode = newDigest->m_node; if (newNode->nodeType() != oldNode->nodeType() || newNode->nodeName() != oldNode->nodeName()) return m_domEditor->replaceChild(oldNode->parentNode(), newNode, oldNode, exceptionState); if (oldNode->nodeValue() != newNode->nodeValue()) { if (!m_domEditor->setNodeValue(oldNode, newNode->nodeValue(), exceptionState)) return false; } if (!oldNode->isElementNode()) return true; // Patch attributes Element* oldElement = toElement(oldNode); Element* newElement = toElement(newNode); if (oldDigest->m_attrsSHA1 != newDigest->m_attrsSHA1) { // FIXME: Create a function in Element for removing all properties. Take in account whether did/willModifyAttribute are important. if (oldElement->hasAttributesWithoutUpdate()) { while (oldElement->attributeCount()) { const Attribute& attribute = oldElement->attributeAt(0); if (!m_domEditor->removeAttribute(oldElement, attribute.localName(), exceptionState)) return false; } } // FIXME: Create a function in Element for copying properties. cloneDataFromElement() is close but not enough for this case. if (newElement->hasAttributesWithoutUpdate()) { AttributeCollection attributes = newElement->attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { if (!m_domEditor->setAttribute(oldElement, it->name().localName(), it->value(), exceptionState)) return false; } } } bool result = innerPatchChildren(oldElement, oldDigest->m_children, newDigest->m_children, exceptionState); m_unusedNodesMap.remove(newDigest->m_sha1); return result; }
PassOwnPtr<DOMPatchSupport::Digest> DOMPatchSupport::createDigest(Node* node, UnusedNodesMap* unusedNodesMap) { Digest* digest = new Digest(node); OwnPtr<blink::WebCryptoDigestor> digestor = createDigestor(HashAlgorithmSha1); DigestValue digestResult; Node::NodeType nodeType = node->nodeType(); digestor->consume(reinterpret_cast<const unsigned char*>(&nodeType), sizeof(nodeType)); addStringToDigestor(digestor.get(), node->nodeName()); addStringToDigestor(digestor.get(), node->nodeValue()); if (node->isElementNode()) { Element& element = toElement(*node); Node* child = element.firstChild(); while (child) { OwnPtr<Digest> childInfo = createDigest(child, unusedNodesMap); addStringToDigestor(digestor.get(), childInfo->m_sha1); child = child->nextSibling(); digest->m_children.append(childInfo.release()); } if (element.hasAttributesWithoutUpdate()) { OwnPtr<blink::WebCryptoDigestor> attrsDigestor = createDigestor(HashAlgorithmSha1); AttributeCollection attributes = element.attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { addStringToDigestor(attrsDigestor.get(), it->name().toString()); addStringToDigestor(attrsDigestor.get(), it->value().string()); } finishDigestor(attrsDigestor.get(), digestResult); digest->m_attrsSHA1 = base64Encode(reinterpret_cast<const char*>(digestResult.data()), 10); addStringToDigestor(digestor.get(), digest->m_attrsSHA1); digestResult.clear(); } } finishDigestor(digestor.get(), digestResult); digest->m_sha1 = base64Encode(reinterpret_cast<const char*>(digestResult.data()), 10); if (unusedNodesMap) unusedNodesMap->add(digest->m_sha1, digest); return adoptPtr(digest); }
void NodeSet::traversalSort() const { WillBeHeapHashSet<RawPtrWillBeMember<Node> > nodes; bool containsAttributeNodes = false; unsigned nodeCount = m_nodes.size(); ASSERT(nodeCount > 1); for (unsigned i = 0; i < nodeCount; ++i) { Node* node = m_nodes[i].get(); nodes.add(node); if (node->isAttributeNode()) containsAttributeNodes = true; } WillBeHeapVector<RefPtrWillBeMember<Node> > sortedNodes; sortedNodes.reserveInitialCapacity(nodeCount); for (Node* n = findRootNode(m_nodes.first().get()); n; n = NodeTraversal::next(*n)) { if (nodes.contains(n)) sortedNodes.append(n); if (!containsAttributeNodes || !n->isElementNode()) continue; Element* element = toElement(n); if (!element->hasAttributes()) continue; AttributeCollection attributes = element->attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { RefPtrWillBeRawPtr<Attr> attr = element->attrIfExists(it->name()); if (attr && nodes.contains(attr.get())) sortedNodes.append(attr); } } ASSERT(sortedNodes.size() == nodeCount); const_cast<WillBeHeapVector<RefPtrWillBeMember<Node> >&>(m_nodes).swap(sortedNodes); }
void WebPageSerializerImpl::openTagToString(Element* element, SerializeDomParam* param) { bool needSkip; StringBuilder result; // Do pre action for open tag. result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip)); if (needSkip) return; // Add open tag result.append('<'); result.append(element->nodeName().lower()); // Go through all attributes and serialize them. if (element->hasAttributes()) { AttributeCollection attributes = element->attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { result.append(' '); // Add attribute pair result.append(it->name().toString()); result.appendLiteral("=\""); if (!it->value().isEmpty()) { const String& attrValue = it->value(); // Check whether we need to replace some resource links // with local resource paths. const QualifiedName& attrName = it->name(); if (element->hasLegalLinkAttribute(attrName)) { // For links start with "javascript:", we do not change it. if (attrValue.startsWith("javascript:", false)) result.append(attrValue); else { // Get the absolute link WebLocalFrameImpl* subFrame = WebLocalFrameImpl::fromFrameOwnerElement(element); String completeURL = subFrame ? subFrame->frame()->document()->url() : param->document->completeURL(attrValue); // Check whether we have local files for those link. if (m_localLinks.contains(completeURL)) { if (!param->directoryName.isEmpty()) { result.appendLiteral("./"); result.append(param->directoryName); result.append('/'); } result.append(m_localLinks.get(completeURL)); } else result.append(completeURL); } } else { if (param->isHTMLDocument) result.append(m_htmlEntities.convertEntitiesInString(attrValue)); else result.append(m_xmlEntities.convertEntitiesInString(attrValue)); } } result.append('\"'); } } // Do post action for open tag. String addedContents = postActionAfterSerializeOpenTag(element, param); // Complete the open tag for element when it has child/children. if (element->hasChildren() || param->haveAddedContentsBeforeEnd) result.append('>'); // Append the added contents generate in post action of open tag. result.append(addedContents); // Save the result to data buffer. saveHTMLContentToBuffer(result.toString(), param); }
// 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 (HTMLParamElement* p = Traversal<HTMLParamElement>::firstChild(*this); p; p = Traversal<HTMLParamElement>::nextSibling(*p)) { 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 != kNotFound) 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. if (hasAttributes()) { AttributeCollection attributes = this->attributes(); AttributeCollection::const_iterator end = attributes.end(); for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { const AtomicString& name = it->name().localName(); if (!uniqueParamNames.contains(name.impl())) { paramNames.append(name.string()); paramValues.append(it->value().string()); } } } mapDataParamToSrc(¶mNames, ¶mValues); // 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()) { KURL completedURL = document().completeURL(urlParameter); bool useFallback; if (shouldUsePlugin(completedURL, serviceType, false, useFallback)) url = urlParameter; } }