1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2009, 2010 Google Inc. All rights reserved. 4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Redistribution and use in source and binary forms, with or without 6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modification, are permitted provided that the following conditions 7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * are met: 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1. Redistributions of source code must retain the above copyright 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer. 10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright 11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer in the 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * documentation and/or other materials provided with the distribution. 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */ 26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h" 28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "MarkupAccumulator.h" 29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "CDATASection.h" 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "Comment.h" 32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "DocumentFragment.h" 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "DocumentType.h" 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "Editor.h" 35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "HTMLElement.h" 36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "HTMLNames.h" 37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "KURL.h" 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "ProcessingInstruction.h" 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "XMLNSNames.h" 402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h> 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore { 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochusing namespace HTMLNames; 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid appendCharactersReplacingEntities(Vector<UChar>& out, const UChar* content, size_t length, EntityMask entityMask) 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch DEFINE_STATIC_LOCAL(const String, ampReference, ("&")); 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch DEFINE_STATIC_LOCAL(const String, ltReference, ("<")); 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch DEFINE_STATIC_LOCAL(const String, gtReference, (">")); 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch DEFINE_STATIC_LOCAL(const String, quotReference, (""")); 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch DEFINE_STATIC_LOCAL(const String, nbspReference, (" ")); 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch static const EntityDescription entityMaps[] = { 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch { '&', ampReference, EntityAmp }, 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch { '<', ltReference, EntityLt }, 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch { '>', gtReference, EntityGt }, 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch { '"', quotReference, EntityQuot }, 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch { noBreakSpace, nbspReference, EntityNbsp }, 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch }; 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch size_t positionAfterLastEntity = 0; 634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang for (size_t i = 0; i < length; ++i) { 644576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang for (size_t m = 0; m < WTF_ARRAY_LENGTH(entityMaps); ++m) { 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (content[i] == entityMaps[m].entity && entityMaps[m].mask & entityMask) { 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append(content + positionAfterLastEntity, i - positionAfterLastEntity); 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, entityMaps[m].reference); 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch positionAfterLastEntity = i + 1; 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append(content + positionAfterLastEntity, length - positionAfterLastEntity); 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 76a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochMarkupAccumulator::MarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, const Range* range) 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch : m_nodes(nodes) 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_range(range) 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_shouldResolveURLs(shouldResolveURLs) 80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 83a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochMarkupAccumulator::~MarkupAccumulator() 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 87a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochString MarkupAccumulator::serializeNodes(Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly) 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch Vector<UChar> out; 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch serializeNodesWithNamespaces(node, nodeToSkip, childrenOnly, 0); 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.reserveInitialCapacity(length()); 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch concatenateMarkup(out); 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return String::adopt(out); 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::serializeNodesWithNamespaces(Node* node, Node* nodeToSkip, EChildrenOnly childrenOnly, const Namespaces* namespaces) 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node == nodeToSkip) 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch Namespaces namespaceHash; 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (namespaces) 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaceHash = *namespaces; 104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!childrenOnly) 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendStartTag(node, &namespaceHash); 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!(node->document()->isHTMLDocument() && elementCannotHaveEndTag(node))) { 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (Node* current = node->firstChild(); current; current = current->nextSibling()) 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch serializeNodesWithNamespaces(current, nodeToSkip, IncludeNode, &namespaceHash); 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!childrenOnly) 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendEndTag(node); 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendString(const String& string) 118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_succeedingMarkup.append(string); 120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendStartTag(Node* node, Namespaces* namespaces) 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch Vector<UChar> markup; 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendStartMarkup(markup, node, namespaces); 126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendString(String::adopt(markup)); 127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_nodes) 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_nodes->append(node); 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendEndTag(Node* node) 132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch Vector<UChar> markup; 134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendEndMarkup(markup, node); 135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendString(String::adopt(markup)); 136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochsize_t MarkupAccumulator::totalLength(const Vector<String>& strings) 139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch size_t length = 0; 141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (size_t i = 0; i < strings.size(); ++i) 142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length += strings[i].length(); 143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return length; 144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// FIXME: This is a very inefficient way of accumulating the markup. 147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// We're converting results of appendStartMarkup and appendEndMarkup from Vector<UChar> to String 148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// and then back to Vector<UChar> and again to String here. 149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::concatenateMarkup(Vector<UChar>& out) 150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (size_t i = 0; i < m_succeedingMarkup.size(); ++i) 152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, m_succeedingMarkup[i]); 153a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 154a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendAttributeValue(Vector<UChar>& result, const String& attribute, bool documentIsHTML) 156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendCharactersReplacingEntities(result, attribute.characters(), attribute.length(), 158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch documentIsHTML ? EntityMaskInHTMLAttributeValue : EntityMaskInAttributeValue); 159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString) 162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch UChar quoteChar = '\"'; 164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String strippedURLString = urlString.stripWhiteSpace(); 165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (protocolIsJavaScript(strippedURLString)) { 166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // minimal escaping for javascript urls 167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (strippedURLString.contains('"')) { 168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (strippedURLString.contains('\'')) 169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch strippedURLString.replace('\"', """); 170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else 171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch quoteChar = '\''; 172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(quoteChar); 174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, strippedURLString); 175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(quoteChar); 176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: This does not fully match other browsers. Firefox percent-escapes non-ASCII characters for innerHTML. 180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(quoteChar); 181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendAttributeValue(result, urlString, false); 182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(quoteChar); 183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendNodeValue(Vector<UChar>& out, const Node* node, const Range* range, EntityMask entityMask) 186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch String str = node->nodeValue(); 188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const UChar* characters = str.characters(); 189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch size_t length = str.length(); 190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (range) { 192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ExceptionCode ec; 193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node == range->endContainer(ec)) 194a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length = range->endOffset(ec); 195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node == range->startContainer(ec)) { 196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch size_t start = range->startOffset(ec); 197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch characters += start; 198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch length -= start; 199a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 200a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 201a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendCharactersReplacingEntities(out, characters, length, entityMask); 203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 204a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool MarkupAccumulator::shouldAddNamespaceElement(const Element* element) 206a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Don't add namespace attribute if it is already defined for this elem. 208a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const AtomicString& prefix = element->prefix(); 209a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AtomicString attr = !prefix.isEmpty() ? "xmlns:" + prefix : "xmlns"; 210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return !element->hasAttribute(attr); 211a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 212a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces) 214a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces.checkConsistency(); 216a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 217a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Don't add namespace attributes twice 218a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (attribute.name() == XMLNSNames::xmlnsAttr) { 219a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces.set(emptyAtom.impl(), attribute.value().impl()); 220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 222a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch QualifiedName xmlnsPrefixAttr(xmlnsAtom, attribute.localName(), XMLNSNames::xmlnsNamespaceURI); 224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (attribute.name() == xmlnsPrefixAttr) { 225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces.set(attribute.localName().impl(), attribute.value().impl()); 226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 229a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return true; 230a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 231a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 232a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendNamespace(Vector<UChar>& result, const AtomicString& prefix, const AtomicString& namespaceURI, Namespaces& namespaces) 233a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 234a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces.checkConsistency(); 235a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (namespaceURI.isEmpty()) 236a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 237a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 238a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Use emptyAtoms's impl() for both null and empty strings since the HashMap can't handle 0 as a key 239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AtomicStringImpl* pre = prefix.isEmpty() ? emptyAtom.impl() : prefix.impl(); 240a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AtomicStringImpl* foundNS = namespaces.get(pre); 241a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (foundNS != namespaceURI.impl()) { 242a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces.set(pre, namespaceURI.impl()); 243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(' '); 244a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, xmlnsAtom.string()); 245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!prefix.isEmpty()) { 246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append(':'); 247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, prefix); 248a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 249a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('='); 251a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('"'); 252a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendAttributeValue(result, namespaceURI, false); 253a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('"'); 254a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 255a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 256a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 257a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochEntityMask MarkupAccumulator::entityMaskForText(Text* text) const 258a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 259a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const QualifiedName* parentName = 0; 260a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (text->parentElement()) 261a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch parentName = &static_cast<Element*>(text->parentElement())->tagQName(); 262a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 263a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (parentName && (*parentName == scriptTag || *parentName == styleTag || *parentName == xmpTag)) 264a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return EntityMaskInCDATA; 265a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 266a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return text->document()->isHTMLDocument() ? EntityMaskInHTMLPCDATA : EntityMaskInPCDATA; 267a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 268a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 269a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendText(Vector<UChar>& out, Text* text) 270a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 271a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendNodeValue(out, text, m_range, entityMaskForText(text)); 272a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 273a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 274a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendComment(Vector<UChar>& out, const String& comment) 275a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 276a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->". 277a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "<!--"); 278a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, comment); 279a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "-->"); 280a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 281a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 282a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendDocumentType(Vector<UChar>& result, const DocumentType* n) 283a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 284a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (n->name().isEmpty()) 285a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 286a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 287a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, "<!DOCTYPE "); 288a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, n->name()); 289a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!n->publicId().isEmpty()) { 290a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, " PUBLIC \""); 291a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, n->publicId()); 292a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, "\""); 293a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!n->systemId().isEmpty()) { 294a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, " \""); 295a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, n->systemId()); 296a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, "\""); 297a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 298a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else if (!n->systemId().isEmpty()) { 299a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, " SYSTEM \""); 300a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, n->systemId()); 301a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, "\""); 302a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 303a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!n->internalSubset().isEmpty()) { 304a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, " ["); 305a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, n->internalSubset()); 306a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, "]"); 307a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 308a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, ">"); 309a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 310a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 311a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendProcessingInstruction(Vector<UChar>& out, const String& target, const String& data) 312a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 313a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>". 314a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "<?"); 315a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, target); 316a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, " "); 317a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, data); 318a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "?>"); 319a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 320a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 321a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendElement(Vector<UChar>& out, Element* element, Namespaces* namespaces) 322a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 323a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendOpenTag(out, element, namespaces); 324a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 325a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch NamedNodeMap* attributes = element->attributes(); 326a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned length = attributes->length(); 327a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned int i = 0; i < length; i++) 328a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendAttribute(out, element, *attributes->attributeItem(i), namespaces); 329a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 330a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendCloseTag(out, element); 331a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 332a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 333a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendOpenTag(Vector<UChar>& out, Element* element, Namespaces* namespaces) 334a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 335a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('<'); 336a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, element->nodeNamePreservingCase()); 337a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!element->document()->isHTMLDocument() && namespaces && shouldAddNamespaceElement(element)) 338a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendNamespace(out, element->prefix(), element->namespaceURI(), *namespaces); 339a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 340a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 341a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendCloseTag(Vector<UChar>& out, Element* element) 342a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 343a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (shouldSelfClose(element)) { 344a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (element->isHTMLElement()) 345a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append(' '); // XHTML 1.0 <-> HTML compatibility. 346a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('/'); 347a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 348a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('>'); 349a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 350a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 351a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendAttribute(Vector<UChar>& out, Element* element, const Attribute& attribute, Namespaces* namespaces) 352a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 353a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch bool documentIsHTML = element->document()->isHTMLDocument(); 354a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 355a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append(' '); 356a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 357a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (documentIsHTML) 358a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, attribute.name().localName()); 359a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else 360a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, attribute.name().toString()); 361a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 362a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('='); 363a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 364a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (element->isURLAttribute(const_cast<Attribute*>(&attribute))) { 365a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We don't want to complete file:/// URLs because it may contain sensitive information 366a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // about the user's system. 367a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (shouldResolveURLs() && !element->document()->url().isLocalFile()) 368a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendQuotedURLAttributeValue(out, element->document()->completeURL(attribute.value()).string()); 369a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else 370a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendQuotedURLAttributeValue(out, attribute.value()); 371a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else { 372a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('\"'); 373a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendAttributeValue(out, attribute.value(), documentIsHTML); 374a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch out.append('\"'); 375a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 376a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 377a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces)) 378a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendNamespace(out, attribute.prefix(), attribute.namespaceURI(), *namespaces); 379a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 380a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 381a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendCDATASection(Vector<UChar>& out, const String& section) 382a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 383a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>". 384a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "<![CDATA["); 385a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, section); 386a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(out, "]]>"); 387a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 388a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendStartMarkup(Vector<UChar>& result, const Node* node, Namespaces* namespaces) 390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (namespaces) 392a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch namespaces->checkConsistency(); 393a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 394a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch switch (node->nodeType()) { 395a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::TEXT_NODE: 396a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendText(result, static_cast<Text*>(const_cast<Node*>(node))); 397a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 398a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::COMMENT_NODE: 399a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendComment(result, static_cast<const Comment*>(node)->data()); 400a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 401a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::DOCUMENT_NODE: 402a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::DOCUMENT_FRAGMENT_NODE: 403a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 404a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::DOCUMENT_TYPE_NODE: 405a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendDocumentType(result, static_cast<const DocumentType*>(node)); 406a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 407a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::PROCESSING_INSTRUCTION_NODE: 408a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendProcessingInstruction(result, static_cast<const ProcessingInstruction*>(node)->target(), static_cast<const ProcessingInstruction*>(node)->data()); 409a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 410a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::ELEMENT_NODE: 411a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendElement(result, static_cast<Element*>(const_cast<Node*>(node)), namespaces); 412a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 413a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::CDATA_SECTION_NODE: 414a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch appendCDATASection(result, static_cast<const CDATASection*>(node)->data()); 415a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 416a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::ATTRIBUTE_NODE: 417a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::ENTITY_NODE: 418a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::ENTITY_REFERENCE_NODE: 419a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::NOTATION_NODE: 420a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch case Node::XPATH_NAMESPACE_NODE: 421a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT_NOT_REACHED(); 422a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 423a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 424a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 425a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 426a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// Rules of self-closure 427a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// 1. No elements in HTML documents use the self-closing syntax. 428a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// 2. Elements w/ children never self-close because they use a separate end tag. 429a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// 3. HTML elements which do not have a "forbidden" end tag will close with a separate end tag. 430a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// 4. Other elements self-close. 431a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool MarkupAccumulator::shouldSelfClose(const Node* node) 432a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 433a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node->document()->isHTMLDocument()) 434a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 435a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node->hasChildNodes()) 436a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 437a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (node->isHTMLElement() && !elementCannotHaveEndTag(node)) 438a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 439a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return true; 440a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 441a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 442a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool MarkupAccumulator::elementCannotHaveEndTag(const Node* node) 443a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 444a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!node->isHTMLElement()) 445a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 446a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 447a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: ieForbidsInsertHTML may not be the right function to call here 448a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // ieForbidsInsertHTML is used to disallow setting innerHTML/outerHTML 449a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // or createContextualFragment. It does not necessarily align with 450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // which elements should be serialized w/o end tags. 451a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return static_cast<const HTMLElement*>(node)->ieForbidsInsertHTML(); 452a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 453a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 454a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid MarkupAccumulator::appendEndMarkup(Vector<UChar>& result, const Node* node) 455a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 456a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!node->isElementNode() || shouldSelfClose(node) || (!node->hasChildNodes() && elementCannotHaveEndTag(node))) 457a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 458a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 459a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('<'); 460a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('/'); 461a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch append(result, static_cast<const Element*>(node)->nodeNamePreservingCase()); 462a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch result.append('>'); 463a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 464a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 465a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 466