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