Node.appendChild(null) / replaceChild(null, null) / removeChild(null) / insertBefore...
[WebKit-https.git] / Source / WebCore / editing / markup.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved.
4  * Copyright (C) 2011 Igalia S.L.
5  * Copyright (C) 2011 Motorola Mobility. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "config.h"
30 #include "markup.h"
31
32 #include "CDATASection.h"
33 #include "CSSPrimitiveValue.h"
34 #include "CSSPropertyNames.h"
35 #include "CSSValue.h"
36 #include "CSSValueKeywords.h"
37 #include "ChildListMutationScope.h"
38 #include "DocumentFragment.h"
39 #include "DocumentType.h"
40 #include "Editor.h"
41 #include "ElementIterator.h"
42 #include "ExceptionCode.h"
43 #include "ExceptionCodePlaceholder.h"
44 #include "File.h"
45 #include "Frame.h"
46 #include "HTMLAttachmentElement.h"
47 #include "HTMLBodyElement.h"
48 #include "HTMLDivElement.h"
49 #include "HTMLElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLTableElement.h"
52 #include "HTMLTextAreaElement.h"
53 #include "HTMLTextFormControlElement.h"
54 #include "URL.h"
55 #include "MarkupAccumulator.h"
56 #include "NodeList.h"
57 #include "Range.h"
58 #include "RenderBlock.h"
59 #include "Settings.h"
60 #include "StyleProperties.h"
61 #include "TextIterator.h"
62 #include "TypedElementDescendantIterator.h"
63 #include "VisibleSelection.h"
64 #include "VisibleUnits.h"
65 #include "htmlediting.h"
66 #include <wtf/StdLibExtras.h>
67 #include <wtf/text/StringBuilder.h>
68
69 namespace WebCore {
70
71 using namespace HTMLNames;
72
73 static bool propertyMissingOrEqualToNone(StyleProperties*, CSSPropertyID);
74
75 class AttributeChange {
76 public:
77     AttributeChange()
78         : m_name(nullAtom, nullAtom, nullAtom)
79     {
80     }
81
82     AttributeChange(PassRefPtr<Element> element, const QualifiedName& name, const String& value)
83         : m_element(element), m_name(name), m_value(value)
84     {
85     }
86
87     void apply()
88     {
89         m_element->setAttribute(m_name, m_value);
90     }
91
92 private:
93     RefPtr<Element> m_element;
94     QualifiedName m_name;
95     String m_value;
96 };
97
98 static void completeURLs(DocumentFragment* fragment, const String& baseURL)
99 {
100     Vector<AttributeChange> changes;
101
102     URL parsedBaseURL(ParsedURLString, baseURL);
103
104     for (auto& element : descendantsOfType<Element>(*fragment)) {
105         if (!element.hasAttributes())
106             continue;
107         for (const Attribute& attribute : element.attributesIterator()) {
108             if (element.attributeContainsURL(attribute) && !attribute.value().isEmpty())
109                 changes.append(AttributeChange(&element, attribute.name(), element.completeURLsInAttributeValue(parsedBaseURL, attribute)));
110         }
111     }
112
113     size_t numChanges = changes.size();
114     for (size_t i = 0; i < numChanges; ++i)
115         changes[i].apply();
116 }
117     
118 class StyledMarkupAccumulator final : public MarkupAccumulator {
119 public:
120     enum RangeFullySelectsNode { DoesFullySelectNode, DoesNotFullySelectNode };
121
122     StyledMarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs, EAnnotateForInterchange, const Range*, bool needsPositionStyleConversion, Node* highestNodeToBeSerialized = 0);
123
124     Node* serializeNodes(Node* startNode, Node* pastEnd);
125     void wrapWithNode(Node&, bool convertBlocksToInlines = false, RangeFullySelectsNode = DoesFullySelectNode);
126     void wrapWithStyleNode(StyleProperties*, Document&, bool isBlock = false);
127     String takeResults();
128     
129     bool needRelativeStyleWrapper() const { return m_needRelativeStyleWrapper; }
130     bool needClearingDiv() const { return m_needClearingDiv; }
131
132     using MarkupAccumulator::appendString;
133
134 private:
135     void appendStyleNodeOpenTag(StringBuilder&, StyleProperties*, Document&, bool isBlock = false);
136     const String& styleNodeCloseTag(bool isBlock = false);
137
138     String renderedText(const Node&, const Range*);
139     String stringValueForRange(const Node&, const Range*);
140
141     void appendElement(StringBuilder& out, const Element&, bool addDisplayInline, RangeFullySelectsNode);
142     virtual void appendCustomAttributes(StringBuilder&, const Element&, Namespaces*) override;
143
144     virtual void appendText(StringBuilder& out, const Text&) override;
145     virtual void appendElement(StringBuilder& out, const Element& element, Namespaces*) override
146     {
147         appendElement(out, element, false, DoesFullySelectNode);
148     }
149
150     enum NodeTraversalMode { EmitString, DoNotEmitString };
151     Node* traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTraversalMode);
152
153     bool shouldAnnotate()
154     {
155         return m_shouldAnnotate == AnnotateForInterchange;
156     }
157
158     bool shouldApplyWrappingStyle(const Node& node) const
159     {
160         return m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->parentNode() == node.parentNode() && m_wrappingStyle && m_wrappingStyle->style();
161     }
162
163     Vector<String> m_reversedPrecedingMarkup;
164     const EAnnotateForInterchange m_shouldAnnotate;
165     Node* m_highestNodeToBeSerialized;
166     RefPtr<EditingStyle> m_wrappingStyle;
167     bool m_needRelativeStyleWrapper;
168     bool m_needsPositionStyleConversion;
169     bool m_needClearingDiv;
170 };
171
172 inline StyledMarkupAccumulator::StyledMarkupAccumulator(Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, EAnnotateForInterchange shouldAnnotate, const Range* range, bool needsPositionStyleConversion, Node* highestNodeToBeSerialized)
173     : MarkupAccumulator(nodes, shouldResolveURLs, range)
174     , m_shouldAnnotate(shouldAnnotate)
175     , m_highestNodeToBeSerialized(highestNodeToBeSerialized)
176     , m_needRelativeStyleWrapper(false)
177     , m_needsPositionStyleConversion(needsPositionStyleConversion)
178     , m_needClearingDiv(false)
179 {
180 }
181
182 void StyledMarkupAccumulator::wrapWithNode(Node& node, bool convertBlocksToInlines, RangeFullySelectsNode rangeFullySelectsNode)
183 {
184     StringBuilder markup;
185     if (is<Element>(node))
186         appendElement(markup, downcast<Element>(node), convertBlocksToInlines && isBlock(&node), rangeFullySelectsNode);
187     else
188         appendStartMarkup(markup, node, nullptr);
189     m_reversedPrecedingMarkup.append(markup.toString());
190     appendEndTag(node);
191     if (m_nodes)
192         m_nodes->append(&node);
193 }
194
195 void StyledMarkupAccumulator::wrapWithStyleNode(StyleProperties* style, Document& document, bool isBlock)
196 {
197     StringBuilder openTag;
198     appendStyleNodeOpenTag(openTag, style, document, isBlock);
199     m_reversedPrecedingMarkup.append(openTag.toString());
200     appendString(styleNodeCloseTag(isBlock));
201 }
202
203 void StyledMarkupAccumulator::appendStyleNodeOpenTag(StringBuilder& out, StyleProperties* style, Document& document, bool isBlock)
204 {
205     // wrappingStyleForSerialization should have removed -webkit-text-decorations-in-effect
206     ASSERT(propertyMissingOrEqualToNone(style, CSSPropertyWebkitTextDecorationsInEffect));
207     if (isBlock)
208         out.appendLiteral("<div style=\"");
209     else
210         out.appendLiteral("<span style=\"");
211     appendAttributeValue(out, style->asText(), document.isHTMLDocument());
212     out.appendLiteral("\">");
213 }
214
215 const String& StyledMarkupAccumulator::styleNodeCloseTag(bool isBlock)
216 {
217     DEPRECATED_DEFINE_STATIC_LOCAL(const String, divClose, (ASCIILiteral("</div>")));
218     DEPRECATED_DEFINE_STATIC_LOCAL(const String, styleSpanClose, (ASCIILiteral("</span>")));
219     return isBlock ? divClose : styleSpanClose;
220 }
221
222 String StyledMarkupAccumulator::takeResults()
223 {
224     StringBuilder result;
225     result.reserveCapacity(totalLength(m_reversedPrecedingMarkup) + length());
226
227     for (size_t i = m_reversedPrecedingMarkup.size(); i > 0; --i)
228         result.append(m_reversedPrecedingMarkup[i - 1]);
229
230     concatenateMarkup(result);
231
232     // We remove '\0' characters because they are not visibly rendered to the user.
233     return result.toString().replaceWithLiteral('\0', "");
234 }
235
236 void StyledMarkupAccumulator::appendText(StringBuilder& out, const Text& text)
237 {    
238     const bool parentIsTextarea = is<HTMLTextAreaElement>(text.parentElement());
239     const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextarea;
240     if (wrappingSpan) {
241         RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy();
242         // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance
243         // Make sure spans are inline style in paste side e.g. span { display: block }.
244         wrappingStyle->forceInline();
245         // FIXME: Should this be included in forceInline?
246         wrappingStyle->style()->setProperty(CSSPropertyFloat, CSSValueNone);
247
248         appendStyleNodeOpenTag(out, wrappingStyle->style(), text.document());
249     }
250
251     if (!shouldAnnotate() || parentIsTextarea)
252         MarkupAccumulator::appendText(out, text);
253     else {
254         const bool useRenderedText = !enclosingElementWithTag(firstPositionInNode(const_cast<Text*>(&text)), selectTag);
255         String content = useRenderedText ? renderedText(text, m_range) : stringValueForRange(text, m_range);
256         StringBuilder buffer;
257         appendCharactersReplacingEntities(buffer, content, 0, content.length(), EntityMaskInPCDATA);
258         out.append(convertHTMLTextToInterchangeFormat(buffer.toString(), &text));
259     }
260
261     if (wrappingSpan)
262         out.append(styleNodeCloseTag());
263 }
264     
265 String StyledMarkupAccumulator::renderedText(const Node& node, const Range* range)
266 {
267     if (!is<Text>(node))
268         return String();
269
270     const Text& textNode = downcast<Text>(node);
271     unsigned startOffset = 0;
272     unsigned endOffset = textNode.length();
273
274     TextIteratorBehavior behavior = TextIteratorDefaultBehavior;
275     if (range && &node == &range->startContainer())
276         startOffset = range->startOffset();
277     if (range && &node == &range->endContainer())
278         endOffset = range->endOffset();
279     else if (range)
280         behavior = TextIteratorBehavesAsIfNodesFollowing;
281
282     Position start = createLegacyEditingPosition(const_cast<Node*>(&node), startOffset);
283     Position end = createLegacyEditingPosition(const_cast<Node*>(&node), endOffset);
284     return plainText(Range::create(node.document(), start, end).ptr(), behavior);
285 }
286
287 String StyledMarkupAccumulator::stringValueForRange(const Node& node, const Range* range)
288 {
289     if (!range)
290         return node.nodeValue();
291
292     String nodeValue = node.nodeValue();
293     if (&node == &range->endContainer())
294         nodeValue.truncate(range->endOffset());
295     if (&node == &range->startContainer())
296         nodeValue.remove(0, range->startOffset());
297     return nodeValue;
298 }
299
300 void StyledMarkupAccumulator::appendCustomAttributes(StringBuilder& out, const Element&element, Namespaces* namespaces)
301 {
302 #if ENABLE(ATTACHMENT_ELEMENT)
303     if (!is<HTMLAttachmentElement>(element))
304         return;
305     
306     const HTMLAttachmentElement& attachment = downcast<HTMLAttachmentElement>(element);
307     if (attachment.file())
308         appendAttribute(out, element, Attribute(webkitattachmentpathAttr, attachment.file()->path()), namespaces);
309 #else
310     UNUSED_PARAM(out);
311     UNUSED_PARAM(element);
312     UNUSED_PARAM(namespaces);
313 #endif
314 }
315
316 void StyledMarkupAccumulator::appendElement(StringBuilder& out, const Element& element, bool addDisplayInline, RangeFullySelectsNode rangeFullySelectsNode)
317 {
318     const bool documentIsHTML = element.document().isHTMLDocument();
319     appendOpenTag(out, element, 0);
320
321     appendCustomAttributes(out, element, nullptr);
322
323     const bool shouldAnnotateOrForceInline = element.isHTMLElement() && (shouldAnnotate() || addDisplayInline);
324     const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element);
325     if (element.hasAttributes()) {
326         for (const Attribute& attribute : element.attributesIterator()) {
327             // We'll handle the style attribute separately, below.
328             if (attribute.name() == styleAttr && shouldOverrideStyleAttr)
329                 continue;
330             appendAttribute(out, element, attribute, 0);
331         }
332     }
333
334     if (shouldOverrideStyleAttr) {
335         RefPtr<EditingStyle> newInlineStyle;
336
337         if (shouldApplyWrappingStyle(element)) {
338             newInlineStyle = m_wrappingStyle->copy();
339             newInlineStyle->removePropertiesInElementDefaultStyle(const_cast<Element*>(&element));
340             newInlineStyle->removeStyleConflictingWithStyleOfNode(const_cast<Element*>(&element));
341         } else
342             newInlineStyle = EditingStyle::create();
343
344         if (is<StyledElement>(element) && downcast<StyledElement>(element).inlineStyle())
345             newInlineStyle->overrideWithStyle(downcast<StyledElement>(element).inlineStyle());
346
347         if (shouldAnnotateOrForceInline) {
348             if (shouldAnnotate())
349                 newInlineStyle->mergeStyleFromRulesForSerialization(downcast<HTMLElement>(const_cast<Element*>(&element)));
350
351             if (addDisplayInline)
352                 newInlineStyle->forceInline();
353             
354             if (m_needsPositionStyleConversion) {
355                 m_needRelativeStyleWrapper |= newInlineStyle->convertPositionStyle();
356                 m_needClearingDiv |= newInlineStyle->isFloating();
357             }
358
359             // If the node is not fully selected by the range, then we don't want to keep styles that affect its relationship to the nodes around it
360             // only the ones that affect it and the nodes within it.
361             if (rangeFullySelectsNode == DoesNotFullySelectNode && newInlineStyle->style())
362                 newInlineStyle->style()->removeProperty(CSSPropertyFloat);
363         }
364
365         if (!newInlineStyle->isEmpty()) {
366             out.appendLiteral(" style=\"");
367             appendAttributeValue(out, newInlineStyle->style()->asText(), documentIsHTML);
368             out.append('\"');
369         }
370     }
371
372     appendCloseTag(out, element);
373 }
374
375 Node* StyledMarkupAccumulator::serializeNodes(Node* startNode, Node* pastEnd)
376 {
377     if (!m_highestNodeToBeSerialized) {
378         Node* lastClosed = traverseNodesForSerialization(startNode, pastEnd, DoNotEmitString);
379         m_highestNodeToBeSerialized = lastClosed;
380     }
381
382     if (m_highestNodeToBeSerialized && m_highestNodeToBeSerialized->parentNode())
383         m_wrappingStyle = EditingStyle::wrappingStyleForSerialization(m_highestNodeToBeSerialized->parentNode(), shouldAnnotate());
384
385     return traverseNodesForSerialization(startNode, pastEnd, EmitString);
386 }
387
388 Node* StyledMarkupAccumulator::traverseNodesForSerialization(Node* startNode, Node* pastEnd, NodeTraversalMode traversalMode)
389 {
390     const bool shouldEmit = traversalMode == EmitString;
391     Vector<Node*> ancestorsToClose;
392     Node* next;
393     Node* lastClosed = nullptr;
394     for (Node* n = startNode; n != pastEnd; n = next) {
395         // According to <rdar://problem/5730668>, it is possible for n to blow
396         // past pastEnd and become null here. This shouldn't be possible.
397         // This null check will prevent crashes (but create too much markup)
398         // and the ASSERT will hopefully lead us to understanding the problem.
399         ASSERT(n);
400         if (!n)
401             break;
402         
403         next = NodeTraversal::next(*n);
404         bool openedTag = false;
405
406         if (isBlock(n) && canHaveChildrenForEditing(n) && next == pastEnd)
407             // Don't write out empty block containers that aren't fully selected.
408             continue;
409
410         if (!n->renderer() && !enclosingElementWithTag(firstPositionInOrBeforeNode(n), selectTag)) {
411             next = NodeTraversal::nextSkippingChildren(*n);
412             // Don't skip over pastEnd.
413             if (pastEnd && pastEnd->isDescendantOf(n))
414                 next = pastEnd;
415         } else {
416             // Add the node to the markup if we're not skipping the descendants
417             if (shouldEmit)
418                 appendStartTag(*n);
419
420             // If node has no children, close the tag now.
421             if (!n->hasChildNodes()) {
422                 if (shouldEmit)
423                     appendEndTag(*n);
424                 lastClosed = n;
425             } else {
426                 openedTag = true;
427                 ancestorsToClose.append(n);
428             }
429         }
430
431         // If we didn't insert open tag and there's no more siblings or we're at the end of the traversal, take care of ancestors.
432         // FIXME: What happens if we just inserted open tag and reached the end?
433         if (!openedTag && (!n->nextSibling() || next == pastEnd)) {
434             // Close up the ancestors.
435             while (!ancestorsToClose.isEmpty()) {
436                 Node* ancestor = ancestorsToClose.last();
437                 if (next != pastEnd && next->isDescendantOf(ancestor))
438                     break;
439                 // Not at the end of the range, close ancestors up to sibling of next node.
440                 if (shouldEmit)
441                     appendEndTag(*ancestor);
442                 lastClosed = ancestor;
443                 ancestorsToClose.removeLast();
444             }
445
446             // Surround the currently accumulated markup with markup for ancestors we never opened as we leave the subtree(s) rooted at those ancestors.
447             ContainerNode* nextParent = next ? next->parentNode() : 0;
448             if (next != pastEnd && n != nextParent) {
449                 Node* lastAncestorClosedOrSelf = n->isDescendantOf(lastClosed) ? lastClosed : n;
450                 for (ContainerNode* parent = lastAncestorClosedOrSelf->parentNode(); parent && parent != nextParent; parent = parent->parentNode()) {
451                     // All ancestors that aren't in the ancestorsToClose list should either be a) unrendered:
452                     if (!parent->renderer())
453                         continue;
454                     // or b) ancestors that we never encountered during a pre-order traversal starting at startNode:
455                     ASSERT(startNode->isDescendantOf(parent));
456                     if (shouldEmit)
457                         wrapWithNode(*parent);
458                     lastClosed = parent;
459                 }
460             }
461         }
462     }
463
464     return lastClosed;
465 }
466
467 static Node* ancestorToRetainStructureAndAppearanceForBlock(Node* commonAncestorBlock)
468 {
469     if (!commonAncestorBlock)
470         return 0;
471
472     if (commonAncestorBlock->hasTagName(tbodyTag) || commonAncestorBlock->hasTagName(trTag)) {
473         ContainerNode* table = commonAncestorBlock->parentNode();
474         while (table && !is<HTMLTableElement>(*table))
475             table = table->parentNode();
476
477         return table;
478     }
479
480     if (isNonTableCellHTMLBlockElement(commonAncestorBlock))
481         return commonAncestorBlock;
482
483     return 0;
484 }
485
486 static inline Node* ancestorToRetainStructureAndAppearance(Node* commonAncestor)
487 {
488     return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonAncestor));
489 }
490
491 static bool propertyMissingOrEqualToNone(StyleProperties* style, CSSPropertyID propertyID)
492 {
493     if (!style)
494         return false;
495     RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
496     if (!value)
497         return true;
498     if (!is<CSSPrimitiveValue>(*value))
499         return false;
500     return downcast<CSSPrimitiveValue>(*value).getValueID() == CSSValueNone;
501 }
502
503 static bool needInterchangeNewlineAfter(const VisiblePosition& v)
504 {
505     VisiblePosition next = v.next();
506     Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode();
507     Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode();
508     // Add an interchange newline if a paragraph break is selected and a br won't already be added to the markup to represent it.
509     return isEndOfParagraph(v) && isStartOfParagraph(next) && !(upstreamNode->hasTagName(brTag) && upstreamNode == downstreamNode);
510 }
511
512 static PassRefPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const Node* node)
513 {
514     if (!node->isHTMLElement())
515         return 0;
516
517     // FIXME: Having to const_cast here is ugly, but it is quite a bit of work to untangle
518     // the non-const-ness of styleFromMatchedRulesForElement.
519     HTMLElement* element = const_cast<HTMLElement*>(static_cast<const HTMLElement*>(node));
520     RefPtr<EditingStyle> style = EditingStyle::create(element->inlineStyle());
521     style->mergeStyleFromRules(element);
522     return style.release();
523 }
524
525 static bool isElementPresentational(const Node* node)
526 {
527     return node->hasTagName(uTag) || node->hasTagName(sTag) || node->hasTagName(strikeTag)
528         || node->hasTagName(iTag) || node->hasTagName(emTag) || node->hasTagName(bTag) || node->hasTagName(strongTag);
529 }
530
531 static Node* highestAncestorToWrapMarkup(const Range* range, EAnnotateForInterchange shouldAnnotate)
532 {
533     Node* commonAncestor = range->commonAncestorContainer();
534     ASSERT(commonAncestor);
535     Node* specialCommonAncestor = nullptr;
536     if (shouldAnnotate == AnnotateForInterchange) {
537         // Include ancestors that aren't completely inside the range but are required to retain 
538         // the structure and appearance of the copied markup.
539         specialCommonAncestor = ancestorToRetainStructureAndAppearance(commonAncestor);
540
541         if (Node* parentListNode = enclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isListItem)) {
542             if (WebCore::areRangesEqual(VisibleSelection::selectionFromContentsOfNode(parentListNode).toNormalizedRange().get(), range)) {
543                 specialCommonAncestor = parentListNode->parentNode();
544                 while (specialCommonAncestor && !isListElement(specialCommonAncestor))
545                     specialCommonAncestor = specialCommonAncestor->parentNode();
546             }
547         }
548
549         // Retain the Mail quote level by including all ancestor mail block quotes.
550         if (Node* highestMailBlockquote = highestEnclosingNodeOfType(firstPositionInOrBeforeNode(range->firstNode()), isMailBlockquote, CanCrossEditingBoundary))
551             specialCommonAncestor = highestMailBlockquote;
552     }
553
554     Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : commonAncestor;
555     if (checkAncestor->renderer() && checkAncestor->renderer()->containingBlock()) {
556         Node* newSpecialCommonAncestor = highestEnclosingNodeOfType(firstPositionInNode(checkAncestor), &isElementPresentational, CanCrossEditingBoundary, checkAncestor->renderer()->containingBlock()->element());
557         if (newSpecialCommonAncestor)
558             specialCommonAncestor = newSpecialCommonAncestor;
559     }
560
561     // If a single tab is selected, commonAncestor will be a text node inside a tab span.
562     // If two or more tabs are selected, commonAncestor will be the tab span.
563     // In either case, if there is a specialCommonAncestor already, it will necessarily be above 
564     // any tab span that needs to be included.
565     if (!specialCommonAncestor && isTabSpanTextNode(commonAncestor))
566         specialCommonAncestor = commonAncestor->parentNode();
567     if (!specialCommonAncestor && isTabSpanNode(commonAncestor))
568         specialCommonAncestor = commonAncestor;
569
570     if (auto* enclosingAnchor = enclosingElementWithTag(firstPositionInNode(specialCommonAncestor ? specialCommonAncestor : commonAncestor), aTag))
571         specialCommonAncestor = enclosingAnchor;
572
573     return specialCommonAncestor;
574 }
575
576 // FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForInterchange? 
577 // FIXME: At least, annotation and style info should probably not be included in range.markupString()
578 static String createMarkupInternal(Document& document, const Range& range, Vector<Node*>* nodes,
579     EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs)
580 {
581     DEPRECATED_DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, (ASCIILiteral("<br class=\"" AppleInterchangeNewline "\">")));
582
583     bool collapsed = range.collapsed();
584     if (collapsed)
585         return emptyString();
586     Node* commonAncestor = range.commonAncestorContainer();
587     if (!commonAncestor)
588         return emptyString();
589
590     document.updateLayoutIgnorePendingStylesheets();
591
592     auto* body = enclosingElementWithTag(firstPositionInNode(commonAncestor), bodyTag);
593     Element* fullySelectedRoot = nullptr;
594     // FIXME: Do this for all fully selected blocks, not just the body.
595     if (body && VisiblePosition(firstPositionInNode(body)) == VisiblePosition(range.startPosition())
596         && VisiblePosition(lastPositionInNode(body)) == VisiblePosition(range.endPosition()))
597         fullySelectedRoot = body;
598     Node* specialCommonAncestor = highestAncestorToWrapMarkup(&range, shouldAnnotate);
599
600     bool needsPositionStyleConversion = body && fullySelectedRoot == body
601         && document.settings() && document.settings()->shouldConvertPositionStyleOnCopy();
602     StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate, &range, needsPositionStyleConversion, specialCommonAncestor);
603     Node* pastEnd = range.pastLastNode();
604
605     Node* startNode = range.firstNode();
606     VisiblePosition visibleStart(range.startPosition(), VP_DEFAULT_AFFINITY);
607     VisiblePosition visibleEnd(range.endPosition(), VP_DEFAULT_AFFINITY);
608     if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(visibleStart)) {
609         if (visibleStart == visibleEnd.previous())
610             return interchangeNewlineString;
611
612         accumulator.appendString(interchangeNewlineString);
613         startNode = visibleStart.next().deepEquivalent().deprecatedNode();
614
615         if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, ASSERT_NO_EXCEPTION) >= 0)
616             return interchangeNewlineString;
617     }
618
619     Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd);
620
621     if (specialCommonAncestor && lastClosed) {
622         // Also include all of the ancestors of lastClosed up to this special ancestor.
623         for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ancestor = ancestor->parentNode()) {
624             if (ancestor == fullySelectedRoot && !convertBlocksToInlines) {
625                 RefPtr<EditingStyle> fullySelectedRootStyle = styleFromMatchedRulesAndInlineDecl(fullySelectedRoot);
626
627                 // Bring the background attribute over, but not as an attribute because a background attribute on a div
628                 // appears to have no effect.
629                 if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundImage))
630                     && fullySelectedRoot->hasAttribute(backgroundAttr))
631                     fullySelectedRootStyle->style()->setProperty(CSSPropertyBackgroundImage, "url('" + fullySelectedRoot->getAttribute(backgroundAttr) + "')");
632
633                 if (fullySelectedRootStyle->style()) {
634                     // Reset the CSS properties to avoid an assertion error in addStyleMarkup().
635                     // This assertion is caused at least when we select all text of a <body> element whose
636                     // 'text-decoration' property is "inherit", and copy it.
637                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyTextDecoration))
638                         fullySelectedRootStyle->style()->setProperty(CSSPropertyTextDecoration, CSSValueNone);
639                     if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyWebkitTextDecorationsInEffect))
640                         fullySelectedRootStyle->style()->setProperty(CSSPropertyWebkitTextDecorationsInEffect, CSSValueNone);
641                     accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(), document, true);
642                 }
643             } else {
644                 // Since this node and all the other ancestors are not in the selection we want to set RangeFullySelectsNode to DoesNotFullySelectNode
645                 // so that styles that affect the exterior of the node are not included.
646                 accumulator.wrapWithNode(*ancestor, convertBlocksToInlines, StyledMarkupAccumulator::DoesNotFullySelectNode);
647             }
648             if (nodes)
649                 nodes->append(ancestor);
650             
651             if (ancestor == specialCommonAncestor)
652                 break;
653         }
654     }
655     
656     if (accumulator.needRelativeStyleWrapper() && needsPositionStyleConversion) {
657         if (accumulator.needClearingDiv())
658             accumulator.appendString("<div style=\"clear: both;\"></div>");
659         RefPtr<EditingStyle> positionRelativeStyle = styleFromMatchedRulesAndInlineDecl(body);
660         positionRelativeStyle->style()->setProperty(CSSPropertyPosition, CSSValueRelative);
661         accumulator.wrapWithStyleNode(positionRelativeStyle->style(), document, true);
662     }
663
664     // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally.
665     if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(visibleEnd.previous()))
666         accumulator.appendString(interchangeNewlineString);
667
668     return accumulator.takeResults();
669 }
670
671 String createMarkup(const Range& range, Vector<Node*>* nodes, EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs)
672 {
673     return createMarkupInternal(range.ownerDocument(), range, nodes, shouldAnnotate, convertBlocksToInlines, shouldResolveURLs);
674 }
675
676 Ref<DocumentFragment> createFragmentFromMarkup(Document& document, const String& markup, const String& baseURL, ParserContentPolicy parserContentPolicy)
677 {
678     // We use a fake body element here to trick the HTML parser to using the InBody insertion mode.
679     auto fakeBody = HTMLBodyElement::create(document);
680     auto fragment = DocumentFragment::create(document);
681
682     fragment->parseHTML(markup, fakeBody.ptr(), parserContentPolicy);
683
684 #if ENABLE(ATTACHMENT_ELEMENT)
685     // When creating a fragment we must strip the webkit-attachment-path attribute after restoring the File object.
686     Vector<Ref<HTMLAttachmentElement>> attachments;
687     for (auto& attachment : descendantsOfType<HTMLAttachmentElement>(fragment))
688         attachments.append(attachment);
689
690     for (auto& attachment : attachments) {
691         attachment->setFile(File::create(attachment->fastGetAttribute(webkitattachmentpathAttr)).ptr());
692         attachment->removeAttribute(webkitattachmentpathAttr);
693     }
694 #endif
695     if (!baseURL.isEmpty() && baseURL != blankURL() && baseURL != document.baseURL())
696         completeURLs(fragment.ptr(), baseURL);
697
698     return fragment;
699 }
700
701 String createMarkup(const Node& node, EChildrenOnly childrenOnly, Vector<Node*>* nodes, EAbsoluteURLs shouldResolveURLs, Vector<QualifiedName>* tagNamesToSkip, EFragmentSerialization fragmentSerialization)
702 {
703     MarkupAccumulator accumulator(nodes, shouldResolveURLs, 0, fragmentSerialization);
704     return accumulator.serializeNodes(const_cast<Node&>(node), childrenOnly, tagNamesToSkip);
705 }
706
707 static void fillContainerFromString(ContainerNode& paragraph, const String& string)
708 {
709     Document& document = paragraph.document();
710
711     if (string.isEmpty()) {
712         paragraph.appendChild(createBlockPlaceholderElement(document), ASSERT_NO_EXCEPTION);
713         return;
714     }
715
716     ASSERT(string.find('\n') == notFound);
717
718     Vector<String> tabList;
719     string.split('\t', true, tabList);
720     String tabText = emptyString();
721     bool first = true;
722     size_t numEntries = tabList.size();
723     for (size_t i = 0; i < numEntries; ++i) {
724         const String& s = tabList[i];
725
726         // append the non-tab textual part
727         if (!s.isEmpty()) {
728             if (!tabText.isEmpty()) {
729                 paragraph.appendChild(createTabSpanElement(document, tabText), ASSERT_NO_EXCEPTION);
730                 tabText = emptyString();
731             }
732             Ref<Node> textNode = document.createTextNode(stringWithRebalancedWhitespace(s, first, i + 1 == numEntries));
733             paragraph.appendChild(WTF::move(textNode), ASSERT_NO_EXCEPTION);
734         }
735
736         // there is a tab after every entry, except the last entry
737         // (if the last character is a tab, the list gets an extra empty entry)
738         if (i + 1 != numEntries)
739             tabText.append('\t');
740         else if (!tabText.isEmpty())
741             paragraph.appendChild(createTabSpanElement(document, tabText), ASSERT_NO_EXCEPTION);
742
743         first = false;
744     }
745 }
746
747 bool isPlainTextMarkup(Node* node)
748 {
749     ASSERT(node);
750     if (!is<HTMLDivElement>(*node))
751         return false;
752
753     HTMLDivElement& element = downcast<HTMLDivElement>(*node);
754     if (element.hasAttributes())
755         return false;
756
757     Node* firstChild = element.firstChild();
758     if (!firstChild)
759         return false;
760
761     Node* secondChild = firstChild->nextSibling();
762     if (!secondChild)
763         return firstChild->isTextNode() || firstChild->firstChild();
764     
765     if (secondChild->nextSibling())
766         return false;
767     
768     return isTabSpanTextNode(firstChild->firstChild()) && secondChild->isTextNode();
769 }
770
771 static bool contextPreservesNewline(const Range& context)
772 {
773     VisiblePosition position(context.startPosition());
774     Node* container = position.deepEquivalent().containerNode();
775     if (!container || !container->renderer())
776         return false;
777
778     return container->renderer()->style().preserveNewline();
779 }
780
781 Ref<DocumentFragment> createFragmentFromText(Range& context, const String& text)
782 {
783     Document& document = context.ownerDocument();
784     Ref<DocumentFragment> fragment = document.createDocumentFragment();
785     
786     if (text.isEmpty())
787         return fragment;
788
789     String string = text;
790     string.replace("\r\n", "\n");
791     string.replace('\r', '\n');
792
793     if (contextPreservesNewline(context)) {
794         fragment->appendChild(document.createTextNode(string), ASSERT_NO_EXCEPTION);
795         if (string.endsWith('\n')) {
796             Ref<Element> element = createBreakElement(document);
797             element->setAttribute(classAttr, AppleInterchangeNewline);            
798             fragment->appendChild(WTF::move(element), ASSERT_NO_EXCEPTION);
799         }
800         return fragment;
801     }
802
803     // A string with no newlines gets added inline, rather than being put into a paragraph.
804     if (string.find('\n') == notFound) {
805         fillContainerFromString(fragment, string);
806         return fragment;
807     }
808
809     // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
810     Node* blockNode = enclosingBlock(context.firstNode());
811     Element* block = downcast<Element>(blockNode);
812     bool useClonesOfEnclosingBlock = blockNode
813         && blockNode->isElementNode()
814         && !block->hasTagName(bodyTag)
815         && !block->hasTagName(htmlTag)
816         && block != editableRootForPosition(context.startPosition());
817     bool useLineBreak = enclosingTextFormControl(context.startPosition());
818
819     Vector<String> list;
820     string.split('\n', true, list); // true gets us empty strings in the list
821     size_t numLines = list.size();
822     for (size_t i = 0; i < numLines; ++i) {
823         const String& s = list[i];
824
825         RefPtr<Element> element;
826         if (s.isEmpty() && i + 1 == numLines) {
827             // For last line, use the "magic BR" rather than a P.
828             element = createBreakElement(document);
829             element->setAttribute(classAttr, AppleInterchangeNewline);
830         } else if (useLineBreak) {
831             element = createBreakElement(document);
832             fillContainerFromString(fragment, s);
833         } else {
834             if (useClonesOfEnclosingBlock)
835                 element = block->cloneElementWithoutChildren(document);
836             else
837                 element = createDefaultParagraphElement(document);
838             fillContainerFromString(*element, s);
839         }
840         fragment->appendChild(element.releaseNonNull(), ASSERT_NO_EXCEPTION);
841     }
842     return fragment;
843 }
844
845 String documentTypeString(const Document& document)
846 {
847     DocumentType* documentType = document.doctype();
848     if (!documentType)
849         return emptyString();
850     return createMarkup(*documentType);
851 }
852
853 String createFullMarkup(const Node& node)
854 {
855     // FIXME: This is never "for interchange". Is that right?
856     String markupString = createMarkup(node, IncludeNode, 0);
857
858     Node::NodeType nodeType = node.nodeType();
859     if (nodeType != Node::DOCUMENT_NODE && nodeType != Node::DOCUMENT_TYPE_NODE)
860         markupString = documentTypeString(node.document()) + markupString;
861
862     return markupString;
863 }
864
865 String createFullMarkup(const Range& range)
866 {
867     // FIXME: This is always "for interchange". Is that right?
868     return documentTypeString(range.startContainer().document()) + createMarkup(range, 0, AnnotateForInterchange);
869 }
870
871 String urlToMarkup(const URL& url, const String& title)
872 {
873     StringBuilder markup;
874     markup.appendLiteral("<a href=\"");
875     markup.append(url.string());
876     markup.appendLiteral("\">");
877     MarkupAccumulator::appendCharactersReplacingEntities(markup, title, 0, title.length(), EntityMaskInPCDATA);
878     markup.appendLiteral("</a>");
879     return markup.toString();
880 }
881
882 PassRefPtr<DocumentFragment> createFragmentForInnerOuterHTML(const String& markup, Element* contextElement, ParserContentPolicy parserContentPolicy, ExceptionCode& ec)
883 {
884     Document* document = &contextElement->document();
885 #if ENABLE(TEMPLATE_ELEMENT)
886     if (contextElement->hasTagName(templateTag))
887         document = &document->ensureTemplateDocument();
888 #endif
889     RefPtr<DocumentFragment> fragment = DocumentFragment::create(*document);
890
891     if (document->isHTMLDocument()) {
892         fragment->parseHTML(markup, contextElement, parserContentPolicy);
893         return fragment;
894     }
895
896     bool wasValid = fragment->parseXML(markup, contextElement, parserContentPolicy);
897     if (!wasValid) {
898         ec = SYNTAX_ERR;
899         return 0;
900     }
901     return fragment.release();
902 }
903
904 PassRefPtr<DocumentFragment> createFragmentForTransformToFragment(const String& sourceString, const String& sourceMIMEType, Document* outputDoc)
905 {
906     RefPtr<DocumentFragment> fragment = outputDoc->createDocumentFragment();
907     
908     if (sourceMIMEType == "text/html") {
909         // As far as I can tell, there isn't a spec for how transformToFragment is supposed to work.
910         // Based on the documentation I can find, it looks like we want to start parsing the fragment in the InBody insertion mode.
911         // Unfortunately, that's an implementation detail of the parser.
912         // We achieve that effect here by passing in a fake body element as context for the fragment.
913         RefPtr<HTMLBodyElement> fakeBody = HTMLBodyElement::create(*outputDoc);
914         fragment->parseHTML(sourceString, fakeBody.get());
915     } else if (sourceMIMEType == "text/plain")
916         fragment->parserAppendChild(Text::create(*outputDoc, sourceString));
917     else {
918         bool successfulParse = fragment->parseXML(sourceString, 0);
919         if (!successfulParse)
920             return 0;
921     }
922     
923     // FIXME: Do we need to mess with URLs here?
924     
925     return fragment.release();
926 }
927
928 static Vector<Ref<HTMLElement>> collectElementsToRemoveFromFragment(ContainerNode& container)
929 {
930     Vector<Ref<HTMLElement>> toRemove;
931     for (auto& element : childrenOfType<HTMLElement>(container)) {
932         if (is<HTMLHtmlElement>(element)) {
933             toRemove.append(element);
934             collectElementsToRemoveFromFragment(element);
935             continue;
936         }
937         if (is<HTMLHeadElement>(element) || is<HTMLBodyElement>(element))
938             toRemove.append(element);
939     }
940     return toRemove;
941 }
942
943 static void removeElementFromFragmentPreservingChildren(DocumentFragment& fragment, HTMLElement& element)
944 {
945     RefPtr<Node> nextChild;
946     for (RefPtr<Node> child = element.firstChild(); child; child = nextChild) {
947         nextChild = child->nextSibling();
948         element.removeChild(*child, ASSERT_NO_EXCEPTION);
949         fragment.insertBefore(*child, &element, ASSERT_NO_EXCEPTION);
950     }
951     fragment.removeChild(element, ASSERT_NO_EXCEPTION);
952 }
953
954 PassRefPtr<DocumentFragment> createContextualFragment(const String& markup, HTMLElement* element, ParserContentPolicy parserContentPolicy, ExceptionCode& ec)
955 {
956     ASSERT(element);
957     if (element->ieForbidsInsertHTML()) {
958         ec = NOT_SUPPORTED_ERR;
959         return nullptr;
960     }
961
962     if (element->hasTagName(colTag) || element->hasTagName(colgroupTag) || element->hasTagName(framesetTag)
963         || element->hasTagName(headTag) || element->hasTagName(styleTag) || element->hasTagName(titleTag)) {
964         ec = NOT_SUPPORTED_ERR;
965         return nullptr;
966     }
967
968     RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, element, parserContentPolicy, ec);
969     if (!fragment)
970         return nullptr;
971
972     // We need to pop <html> and <body> elements and remove <head> to
973     // accommodate folks passing complete HTML documents to make the
974     // child of an element.
975     auto toRemove = collectElementsToRemoveFromFragment(*fragment);
976     for (auto& element : toRemove)
977         removeElementFromFragmentPreservingChildren(*fragment, element);
978
979     return fragment.release();
980 }
981
982 static inline bool hasOneChild(ContainerNode& node)
983 {
984     Node* firstChild = node.firstChild();
985     return firstChild && !firstChild->nextSibling();
986 }
987
988 static inline bool hasOneTextChild(ContainerNode& node)
989 {
990     return hasOneChild(node) && node.firstChild()->isTextNode();
991 }
992
993 void replaceChildrenWithFragment(ContainerNode& container, Ref<DocumentFragment>&& fragment, ExceptionCode& ec)
994 {
995     Ref<ContainerNode> containerNode(container);
996     ChildListMutationScope mutation(containerNode);
997
998     if (!fragment->firstChild()) {
999         containerNode->removeChildren();
1000         return;
1001     }
1002
1003     if (hasOneTextChild(containerNode) && hasOneTextChild(fragment)) {
1004         downcast<Text>(*containerNode->firstChild()).setData(downcast<Text>(*fragment->firstChild()).data(), ec);
1005         return;
1006     }
1007
1008     if (hasOneChild(containerNode)) {
1009         containerNode->replaceChild(WTF::move(fragment), *containerNode->firstChild(), ec);
1010         return;
1011     }
1012
1013     containerNode->removeChildren();
1014     containerNode->appendChild(WTF::move(fragment), ec);
1015 }
1016
1017 void replaceChildrenWithText(ContainerNode& container, const String& text, ExceptionCode& ec)
1018 {
1019     Ref<ContainerNode> containerNode(container);
1020     ChildListMutationScope mutation(containerNode);
1021
1022     if (hasOneTextChild(containerNode)) {
1023         downcast<Text>(*containerNode->firstChild()).setData(text, ec);
1024         return;
1025     }
1026
1027     Ref<Text> textNode = Text::create(containerNode->document(), text);
1028
1029     if (hasOneChild(containerNode)) {
1030         containerNode->replaceChild(WTF::move(textNode), *containerNode->firstChild(), ec);
1031         return;
1032     }
1033
1034     containerNode->removeChildren();
1035     containerNode->appendChild(WTF::move(textNode), ec);
1036 }
1037
1038 }