15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009, 2010 Google Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/MarkupAccumulator.h" 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 305d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h" 315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XLinkNames.h" 325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XMLNSNames.h" 335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/XMLNames.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/CDATASection.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Comment.h" 365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/dom/Document.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/DocumentFragment.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/DocumentType.h" 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/ProcessingInstruction.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/Editor.h" 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLElement.h" 4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLTemplateElement.h" 4351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/KURL.h" 44521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/unicode/CharacterNames.h" 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 46c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames; 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)struct EntityDescription { 5109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) UChar entity; 5209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const CString& reference; 5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EntityMask mask; 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}; 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)template <typename CharType> 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static inline void appendCharactersReplacingEntitiesInternal(StringBuilder& result, CharType* text, unsigned length, const EntityDescription entityMaps[], unsigned entityMapsCount, EntityMask entityMask) 5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 5909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) unsigned positionAfterLastEntity = 0; 6009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (unsigned i = 0; i < length; ++i) { 6109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (unsigned entityIndex = 0; entityIndex < entityMapsCount; ++entityIndex) { 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (text[i] == entityMaps[entityIndex].entity && entityMaps[entityIndex].mask & entityMask) { 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(text + positionAfterLastEntity, i - positionAfterLastEntity); 6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const CString& replacement = entityMaps[entityIndex].reference; 6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(replacement.data(), replacement.length()); 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) positionAfterLastEntity = i + 1; 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) break; 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 7009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(text + positionAfterLastEntity, length - positionAfterLastEntity); 7209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 7309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendCharactersReplacingEntities(StringBuilder& result, const String& source, unsigned offset, unsigned length, EntityMask entityMask) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 7609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(const CString, ampReference, ("&")); 7709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(const CString, ltReference, ("<")); 7809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(const CString, gtReference, (">")); 7909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(const CString, quotReference, (""")); 8009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) DEFINE_STATIC_LOCAL(const CString, nbspReference, (" ")); 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) static const EntityDescription entityMaps[] = { 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { '&', ampReference, EntityAmp }, 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { '<', ltReference, EntityLt }, 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { '>', gtReference, EntityGt }, 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { '"', quotReference, EntityQuot }, 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { noBreakSpace, nbspReference, EntityNbsp }, 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!(offset + length)) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(offset + length <= source.length()); 9409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (source.is8Bit()) 9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendCharactersReplacingEntitiesInternal(result, source.characters8() + offset, length, entityMaps, WTF_ARRAY_LENGTH(entityMaps), entityMask); 9609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) else 9709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendCharactersReplacingEntitiesInternal(result, source.characters16() + offset, length, entityMaps, WTF_ARRAY_LENGTH(entityMaps), entityMask); 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 100f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)MarkupAccumulator::MarkupAccumulator(WillBeHeapVector<RawPtrWillBeMember<Node> >* nodes, EAbsoluteURLs resolveUrlsMethod, const Range* range, SerializationType serializationType) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_nodes(nodes) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_range(range) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_resolveURLsMethod(resolveUrlsMethod) 104d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) , m_serializationType(serializationType) 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)MarkupAccumulator::~MarkupAccumulator() 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)String MarkupAccumulator::serializeNodes(Node& targetNode, EChildrenOnly childrenOnly, Vector<QualifiedName>* tagNamesToSkip) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) Namespaces* namespaces = 0; 115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) Namespaces namespaceHash; 116d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!serializeAsHTMLDocument(targetNode)) { 117d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Add pre-bound namespaces for XML fragments. 1186f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch namespaceHash.set(xmlAtom, XMLNames::xmlNamespaceURI); 119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) namespaces = &namespaceHash; 120d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) serializeNodesWithNamespaces(targetNode, childrenOnly, namespaces, tagNamesToSkip); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_markup.toString(); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 12609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::serializeNodesWithNamespaces(Node& targetNode, EChildrenOnly childrenOnly, const Namespaces* namespaces, Vector<QualifiedName>* tagNamesToSkip) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (tagNamesToSkip && targetNode.isElementNode()) { 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t i = 0; i < tagNamesToSkip->size(); ++i) { 130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (toElement(targetNode).hasTagName(tagNamesToSkip->at(i))) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Namespaces namespaceHash; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (namespaces) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) namespaceHash = *namespaces; 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!childrenOnly) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendStartTag(targetNode, &namespaceHash); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!(serializeAsHTMLDocument(targetNode) && elementCannotHaveEndTag(targetNode))) { 143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) Node* current = isHTMLTemplateElement(targetNode) ? toHTMLTemplateElement(targetNode).content()->firstChild() : targetNode.firstChild(); 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) for ( ; current; current = current->nextSibling()) 14509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) serializeNodesWithNamespaces(*current, IncludeNode, &namespaceHash, tagNamesToSkip); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!childrenOnly && targetNode.isElementNode()) 149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) appendEndTag(toElement(targetNode)); 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)String MarkupAccumulator::resolveURLIfNeeded(const Element& element, const String& urlString) const 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (m_resolveURLsMethod) { 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case ResolveAllURLs: 15609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return element.document().completeURL(urlString).string(); 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case ResolveNonLocalURLs: 15909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!element.document().url().isLocalFile()) 16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return element.document().completeURL(urlString).string(); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case DoNotResolveURLs: 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return urlString; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendString(const String& string) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_markup.append(string); 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendStartTag(Node& node, Namespaces* namespaces) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendStartMarkup(m_markup, node, namespaces); 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_nodes) 17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) m_nodes->append(&node); 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MarkupAccumulator::appendEndTag(const Element& element) 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) appendEndMarkup(m_markup, element); 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)size_t MarkupAccumulator::totalLength(const Vector<String>& strings) 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) size_t length = 0; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (size_t i = 0; i < strings.size(); ++i) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) length += strings[i].length(); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return length; 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::concatenateMarkup(StringBuilder& result) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(m_markup); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendAttributeValue(StringBuilder& result, const String& attribute, bool documentIsHTML) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendCharactersReplacingEntities(result, attribute, 0, attribute.length(), 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeValue); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendCustomAttributes(StringBuilder&, const Element&, Namespaces*) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendQuotedURLAttributeValue(StringBuilder& result, const Element& element, const Attribute& attribute) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 21109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(element.isURLAttribute(attribute)); 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const String resolvedURLString = resolveURLIfNeeded(element, attribute.value()); 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) UChar quoteChar = '"'; 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String strippedURLString = resolvedURLString.stripWhiteSpace(); 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (protocolIsJavaScript(strippedURLString)) { 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // minimal escaping for javascript urls 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (strippedURLString.contains('"')) { 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (strippedURLString.contains('\'')) 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) strippedURLString.replaceWithLiteral('"', """); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) quoteChar = '\''; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(quoteChar); 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(strippedURLString); 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(quoteChar); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML. 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(quoteChar); 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendAttributeValue(result, resolvedURLString, false); 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(quoteChar); 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 235d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool MarkupAccumulator::shouldAddNamespaceElement(const Element& element, Namespaces& namespaces) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Don't add namespace attribute if it is already defined for this elem. 23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const AtomicString& prefix = element.prefix(); 239d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (prefix.isEmpty()) { 240d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (element.hasAttribute(xmlnsAtom)) { 2416f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch namespaces.set(emptyAtom, element.namespaceURI()); 242d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return false; 243d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 244d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return true; 245d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2476f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch return !element.hasAttribute(WTF::xmlnsWithColon + prefix); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2506f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochbool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, const Element& element) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch // xmlns and xmlns:prefix attributes should be handled by another branch in appendAttribute. 2536f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch ASSERT(attribute.namespaceURI() != XMLNSNames::xmlnsNamespaceURI); 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2556f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch // Attributes are in the null namespace by default. 2566f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (!attribute.namespaceURI()) 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2596f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch // Attributes without a prefix will need one generated for them, and an xmlns attribute for that prefix. 2606f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (!attribute.prefix()) 2616f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch return true; 2626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch 2636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch return !element.hasAttribute(WTF::xmlnsWithColon + attribute.prefix()); 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendNamespace(StringBuilder& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces) 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (namespaceURI.isEmpty()) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2716f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch const AtomicString& lookupKey = (!prefix) ? emptyAtom : prefix; 2726f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch AtomicString foundURI = namespaces.get(lookupKey); 2736f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (foundURI != namespaceURI) { 2746f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch namespaces.set(lookupKey, namespaceURI); 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(' '); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(xmlnsAtom.string()); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!prefix.isEmpty()) { 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(':'); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(prefix); 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.appendLiteral("=\""); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendAttributeValue(result, namespaceURI, false); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 290d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!serializeAsHTMLDocument(text)) 29151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return EntityMaskInPCDATA; 29251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const QualifiedName* parentName = 0; 29409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (text.parentElement()) 29509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) parentName = &(text.parentElement())->tagQName(); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag)) 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return EntityMaskInCDATA; 29951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) return EntityMaskInHTMLPCDATA; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 30209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendText(StringBuilder& result, Text& text) 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 30409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const String& str = text.data(); 30509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) unsigned length = str.length(); 30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) unsigned start = 0; 30709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 30809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (m_range) { 30909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (text == m_range->endContainer()) 31009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) length = m_range->endOffset(); 31109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (text == m_range->startContainer()) { 31209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) start = m_range->startOffset(); 31309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) length -= start; 31409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 31509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 31609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendCharactersReplacingEntities(result, str, start, length, entityMaskForText(text)); 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendComment(StringBuilder& result, const String& comment) 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->". 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("<!--"); 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(comment); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("-->"); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 32709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendXMLDeclaration(StringBuilder& result, const Document& document) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 32909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!document.hasXMLDeclaration()) 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("<?xml version=\""); 33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(document.xmlVersion()); 33409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) const String& encoding = document.xmlEncoding(); 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!encoding.isEmpty()) { 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("\" encoding=\""); 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(encoding); 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 33909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (document.xmlStandaloneStatus() != Document::StandaloneUnspecified) { 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("\" standalone=\""); 34109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (document.xmlStandalone()) 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("yes"); 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("no"); 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("\"?>"); 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendDocumentType(StringBuilder& result, const DocumentType& n) 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 35209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (n.name().isEmpty()) 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("<!DOCTYPE "); 35609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(n.name()); 35709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!n.publicId().isEmpty()) { 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral(" PUBLIC \""); 35909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(n.publicId()); 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 36109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!n.systemId().isEmpty()) { 36209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.appendLiteral(" \""); 36309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(n.systemId()); 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 36609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else if (!n.systemId().isEmpty()) { 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral(" SYSTEM \""); 36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.append(n.systemId()); 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('>'); 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendProcessingInstruction(StringBuilder& result, const String& target, const String& data) 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>". 37709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.appendLiteral("<?"); 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(target); 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(' '); 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(data); 38109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.appendLiteral("?>"); 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendElement(StringBuilder& result, Element& element, Namespaces* namespaces) 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendOpenTag(result, element, namespaces); 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 388c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) AttributeCollection attributes = element.attributes(); 389e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) AttributeCollection::iterator end = attributes.end(); 390e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) 391c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) appendAttribute(result, element, *it, namespaces); 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Give an opportunity to subclasses to add their own attributes. 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendCustomAttributes(result, element, namespaces); 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendCloseTag(result, element); 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 39909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendOpenTag(StringBuilder& result, const Element& element, Namespaces* namespaces) 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('<'); 402c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) result.append(element.tagQName().toString()); 403d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (!serializeAsHTMLDocument(element) && namespaces && shouldAddNamespaceElement(element, *namespaces)) 40409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendNamespace(result, element.prefix(), element.namespaceURI(), *namespaces); 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendCloseTag(StringBuilder& result, const Element& element) 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (shouldSelfClose(element)) { 41009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (element.isHTMLElement()) 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(' '); // XHTML 1.0 <-> HTML compatibility. 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('/'); 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('>'); 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline bool attributeIsInSerializedNamespace(const Attribute& attribute) 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return attribute.namespaceURI() == XMLNames::xmlNamespaceURI 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) || attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI; 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces) 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 426d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) bool documentIsHTML = serializeAsHTMLDocument(element); 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 428d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) QualifiedName prefixedName = attribute.name(); 429d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { 4306f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch result.append(' '); 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(attribute.name().localName()); 432d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else { 433c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { 4346f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (!attribute.prefix() && attribute.localName() != xmlnsAtom) 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) prefixedName.setPrefix(xmlnsAtom); 4366f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch if (namespaces) { // Account for the namespace attribute we're about to append. 4376f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch const AtomicString& lookupKey = (!attribute.prefix()) ? emptyAtom : attribute.localName(); 4386f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch namespaces->set(lookupKey, attribute.value()); 4396f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch } 440c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { 441c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!attribute.prefix()) 442c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) prefixedName.setPrefix(xmlAtom); 443c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } else { 444c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { 445c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!attribute.prefix()) 446c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) prefixedName.setPrefix(xlinkAtom); 447c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 448c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) 449c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (namespaces && shouldAddNamespaceAttribute(attribute, element)) { 450c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!prefixedName.prefix()) { 451c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // This behavior is in process of being standardized. See crbug.com/248044 and https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208 452c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) String prefixPrefix("ns", 2); 453c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for (unsigned i = attribute.namespaceURI().impl()->existingHash(); ; ++i) { 454c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) AtomicString newPrefix(String(prefixPrefix + String::number(i))); 455c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) AtomicString foundURI = namespaces->get(newPrefix); 456c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (foundURI == attribute.namespaceURI() || foundURI == nullAtom) { 457c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // We already generated a prefix for this namespace. 458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) prefixedName.setPrefix(newPrefix); 459c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) break; 460c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) } 4616f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch } 4626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch } 463c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) ASSERT(prefixedName.prefix()); 464c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) appendNamespace(result, prefixedName.prefix(), attribute.namespaceURI(), *namespaces); 4656f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch } 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4676f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch result.append(' '); 4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(prefixedName.toString()); 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('='); 4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 473d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (element.isURLAttribute(attribute)) { 4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendQuotedURLAttributeValue(result, element, attribute); 475d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else { 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendAttributeValue(result, attribute.value(), documentIsHTML); 4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('"'); 4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MarkupAccumulator::appendCDATASection(StringBuilder& result, const String& section) 4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>". 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("<![CDATA["); 4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append(section); 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.appendLiteral("]]>"); 4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 49009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void MarkupAccumulator::appendStartMarkup(StringBuilder& result, Node& node, Namespaces* namespaces) 4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 49209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) switch (node.nodeType()) { 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::TEXT_NODE: 49409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendText(result, toText(node)); 4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::COMMENT_NODE: 49709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendComment(result, toComment(node).data()); 4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::DOCUMENT_NODE: 500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) appendXMLDeclaration(result, toDocument(node)); 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::DOCUMENT_FRAGMENT_NODE: 5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::DOCUMENT_TYPE_NODE: 5058abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) appendDocumentType(result, toDocumentType(node)); 5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::PROCESSING_INSTRUCTION_NODE: 50809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendProcessingInstruction(result, toProcessingInstruction(node).target(), toProcessingInstruction(node).data()); 5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::ELEMENT_NODE: 51109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendElement(result, toElement(node), namespaces); 5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::CDATA_SECTION_NODE: 51409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) appendCDATASection(result, toCDATASection(node).data()); 5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case Node::ATTRIBUTE_NODE: 5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT_NOT_REACHED(); 5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Rules of self-closure 5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 1. No elements in HTML documents use the self-closing syntax. 5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 2. Elements w/ children never self-close because they use a separate end tag. 5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag. 5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 4. Other elements self-close. 527c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool MarkupAccumulator::shouldSelfClose(const Element& element) 5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 529c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (serializeAsHTMLDocument(element)) 5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 531c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (element.hasChildren()) 5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 533c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (element.isHTMLElement() && !elementCannotHaveEndTag(element)) 5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 53809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)bool MarkupAccumulator::elementCannotHaveEndTag(const Node& node) 5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 54009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (!node.isHTMLElement()) 5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: ieForbidsInsertHTML may not be the right function to call here 5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // ieForbidsInsertHTML is used to disallow setting innerHTML/outerHTML 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // or createContextualFragment. It does not necessarily align with 5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // which elements should be serialized w/o end tags. 54709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return toHTMLElement(node).ieForbidsInsertHTML(); 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 550c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void MarkupAccumulator::appendEndMarkup(StringBuilder& result, const Element& element) 5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 552c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (shouldSelfClose(element) || (!element.hasChildren() && elementCannotHaveEndTag(element))) 5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.appendLiteral("</"); 556c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) result.append(element.tagQName().toString()); 5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result.append('>'); 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 560d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)bool MarkupAccumulator::serializeAsHTMLDocument(const Node& node) const 561d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 562d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (m_serializationType == ForcedXML) 563d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return false; 564d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return node.document().isHTMLDocument(); 565d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 566d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 568