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