Make HTMLConverter take two Positions in preparation to make it work with shadow DOM
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Dec 2018 21:20:10 +0000 (21:20 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Dec 2018 21:20:10 +0000 (21:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192613

Reviewed by Darin Adler.

This patch makes HTMLConverter store two Position's instead of a Range so that HTMLConverter can work with
a selection which spans across shadow boundaries in the future.

No new tests since there should be no observable behavioral change.

* editing/cocoa/EditorCocoa.mm:
(WebCore::Editor::writeSelectionToPasteboard): Uses the newly introduced writeSelectionToPasteboard.
(WebCore::Editor::writeSelection): Ditto.
* editing/cocoa/HTMLConverter.h:
* editing/cocoa/HTMLConverter.mm:
(HTMLConverter::HTMLConverter): Now takes two Position's.
(HTMLConverter::convert): Updated to work with Position's.
(HTMLConverter::_processText): Ditto.
(HTMLConverter::_traverseNode): Ditto.
(HTMLConverter::_traverseFooterNode): Ditto.
(HTMLConverterCaches::cacheAncestorsOfStartToBeConverted): Ditto.
(WebCore::attributedStringFromRange): Ditto.
(WebCore::attributedStringFromSelection): Added. For now, we first create a Range via toNormalizedRange
in order to preserve the exact behavior.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@239127 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/editing/cocoa/EditorCocoa.mm
Source/WebCore/editing/cocoa/HTMLConverter.h
Source/WebCore/editing/cocoa/HTMLConverter.mm

index 5c1d0b9..6e1ab3d 100644 (file)
@@ -1,3 +1,30 @@
+2018-12-11  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Make HTMLConverter take two Positions in preparation to make it work with shadow DOM
+        https://bugs.webkit.org/show_bug.cgi?id=192613
+
+        Reviewed by Darin Adler.
+
+        This patch makes HTMLConverter store two Position's instead of a Range so that HTMLConverter can work with
+        a selection which spans across shadow boundaries in the future.
+
+        No new tests since there should be no observable behavioral change.
+
+        * editing/cocoa/EditorCocoa.mm:
+        (WebCore::Editor::writeSelectionToPasteboard): Uses the newly introduced writeSelectionToPasteboard.
+        (WebCore::Editor::writeSelection): Ditto.
+        * editing/cocoa/HTMLConverter.h:
+        * editing/cocoa/HTMLConverter.mm:
+        (HTMLConverter::HTMLConverter): Now takes two Position's.
+        (HTMLConverter::convert): Updated to work with Position's.
+        (HTMLConverter::_processText): Ditto.
+        (HTMLConverter::_traverseNode): Ditto.
+        (HTMLConverter::_traverseFooterNode): Ditto.
+        (HTMLConverterCaches::cacheAncestorsOfStartToBeConverted): Ditto.
+        (WebCore::attributedStringFromRange): Ditto.
+        (WebCore::attributedStringFromSelection): Added. For now, we first create a Range via toNormalizedRange
+        in order to preserve the exact behavior.
+
 2018-12-12  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Unreviewed manual rollout of r239100-r239102 and r239116
index e3129ab..5ccf446 100644 (file)
@@ -103,7 +103,7 @@ void Editor::getPasteboardTypesAndDataForAttachment(Element& element, Vector<Str
 
 void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
 {
-    NSAttributedString *attributedString = attributedStringFromRange(*selectedRange());
+    NSAttributedString *attributedString = attributedStringFromSelection(m_frame.selection().selection());
 
     PasteboardWebContent content;
     content.contentOrigin = m_frame.document()->originIdentifierForPasteboard();
@@ -121,7 +121,7 @@ void Editor::writeSelectionToPasteboard(Pasteboard& pasteboard)
 
 void Editor::writeSelection(PasteboardWriterData& pasteboardWriterData)
 {
-    NSAttributedString *attributedString = attributedStringFromRange(*selectedRange());
+    NSAttributedString *attributedString = attributedStringFromSelection(m_frame.selection().selection());
 
     PasteboardWriterData::WebContent webContent;
     webContent.contentOrigin = m_frame.document()->originIdentifierForPasteboard();
index 8762cc0..f05c9a0 100644 (file)
@@ -30,9 +30,11 @@ OBJC_CLASS NSAttributedString;
 namespace WebCore {
     
 class Range;
+class VisibleSelection;
 
 enum class IncludeImagesInAttributedString { Yes, No };
-    
+
+NSAttributedString *attributedStringFromSelection(const VisibleSelection&);
 WEBCORE_EXPORT NSAttributedString *attributedStringFromRange(Range&);
 #if !PLATFORM(IOS_FAMILY)
 WEBCORE_EXPORT NSAttributedString *editingAttributedStringFromRange(Range&, IncludeImagesInAttributedString = IncludeImagesInAttributedString::Yes);
index 06dc891..b7698c4 100644 (file)
@@ -36,6 +36,7 @@
 #import "ColorMac.h"
 #import "Document.h"
 #import "DocumentLoader.h"
+#import "Editing.h"
 #import "Element.h"
 #import "ElementTraversal.h"
 #import "File.h"
@@ -61,6 +62,7 @@
 #import "StyleProperties.h"
 #import "StyledElement.h"
 #import "TextIterator.h"
+#import "VisibleSelection.h"
 #import <objc/runtime.h>
 #import <pal/spi/cocoa/NSAttributedStringSPI.h>
 #import <wtf/ASCIICType.h>
@@ -336,7 +338,7 @@ public:
     RefPtr<CSSValue> computedStylePropertyForElement(Element&, CSSPropertyID);
     RefPtr<CSSValue> inlineStylePropertyForElement(Element&, CSSPropertyID);
 
-    Node* cacheAncestorsOfStartToBeConverted(const Range&);
+    Node* cacheAncestorsOfStartToBeConverted(const Position&, const Position&);
     bool isAncestorsOfStartToBeConverted(Node& node) const { return m_ancestorsUnderCommonAncestor.contains(&node); }
 
 private:
@@ -359,13 +361,14 @@ private:
 
 class HTMLConverter {
 public:
-    HTMLConverter(Range&);
+    HTMLConverter(const Position&, const Position&);
     ~HTMLConverter();
     
     NSAttributedString* convert();
     
 private:
-    Ref<Range> m_range;
+    Position m_start;
+    Position m_end;
     DocumentLoader* m_dataSource;
     
     HashMap<RefPtr<Element>, RetainPtr<NSDictionary>> m_attributesForElements;
@@ -434,8 +437,9 @@ private:
     void _adjustTrailingNewline();
 };
 
-HTMLConverter::HTMLConverter(Range& range)
-    : m_range(range)
+HTMLConverter::HTMLConverter(const Position& start, const Position& end)
+    : m_start(start)
+    , m_end(end)
     , m_dataSource(nullptr)
 {
     _attrStr = [[NSMutableAttributedString alloc] init];
@@ -481,7 +485,10 @@ HTMLConverter::~HTMLConverter()
 
 NSAttributedString *HTMLConverter::convert()
 {
-    Node* commonAncestorContainer = _caches->cacheAncestorsOfStartToBeConverted(m_range);
+    if (comparePositions(m_start, m_end) > 0)
+        return nil;
+
+    Node* commonAncestorContainer = _caches->cacheAncestorsOfStartToBeConverted(m_start, m_end);
     ASSERT(commonAncestorContainer);
 
     m_dataSource = commonAncestorContainer->document().frame()->loader().documentLoader();
@@ -2197,13 +2204,13 @@ void HTMLConverter::_processText(CharacterData& characterData)
     String originalString = characterData.data();
     unsigned startOffset = 0;
     unsigned endOffset = originalString.length();
-    if (&characterData == &m_range->startContainer()) {
-        startOffset = m_range->startOffset();
+    if (&characterData == m_start.containerNode()) {
+        startOffset = m_start.offsetInContainerNode();
         _domRangeStartIndex = [_attrStr length];
         _flags.reachedStart = YES;
     }
-    if (&characterData == &m_range->endContainer()) {
-        endOffset = m_range->endOffset();
+    if (&characterData == m_end.containerNode()) {
+        endOffset = m_end.offsetInContainerNode();
         _flags.reachedEnd = YES;
     }
     if ((startOffset > 0 || endOffset < originalString.length()) && endOffset >= startOffset)
@@ -2277,13 +2284,13 @@ void HTMLConverter::_traverseNode(Node& node, unsigned depth, bool embedded)
     unsigned endOffset = UINT_MAX;
     bool isStart = false;
     bool isEnd = false;
-    if (&node == &m_range->startContainer()) {
-        startOffset = m_range->startOffset();
+    if (&node == m_start.containerNode()) {
+        startOffset = m_start.offsetInContainerNode();
         isStart = true;
         _flags.reachedStart = YES;
     }
-    if (&node == &m_range->endContainer()) {
-        endOffset = m_range->endOffset();
+    if (&node == m_end.containerNode()) {
+        endOffset = m_end.offsetInContainerNode();
         isEnd = true;
     }
     
@@ -2338,13 +2345,13 @@ void HTMLConverter::_traverseFooterNode(Element& element, unsigned depth)
     unsigned endOffset = UINT_MAX;
     bool isStart = false;
     bool isEnd = false;
-    if (&element == &m_range->startContainer()) {
-        startOffset = m_range->startOffset();
+    if (&element == m_start.containerNode()) {
+        startOffset = m_start.offsetInContainerNode();
         isStart = true;
         _flags.reachedStart = YES;
     }
-    if (&element == &m_range->endContainer()) {
-        endOffset = m_range->endOffset();
+    if (&element == m_end.containerNode()) {
+        endOffset = m_end.offsetInContainerNode();
         isEnd = true;
     }
     
@@ -2379,10 +2386,10 @@ void HTMLConverter::_adjustTrailingNewline()
         [_attrStr replaceCharactersInRange:NSMakeRange(textLength, 0) withString:@"\n"];
 }
 
-Node* HTMLConverterCaches::cacheAncestorsOfStartToBeConverted(const Range& range)
+Node* HTMLConverterCaches::cacheAncestorsOfStartToBeConverted(const Position& start, const Position& end)
 {
-    Node* commonAncestor = range.commonAncestorContainer();
-    Node* ancestor = &range.startContainer();
+    Node* commonAncestor = Range::commonAncestorContainer(start.containerNode(), end.containerNode());
+    Node* ancestor = start.containerNode();
 
     while (ancestor) {
         m_ancestorsUnderCommonAncestor.add(ancestor);
@@ -2453,8 +2460,14 @@ namespace WebCore {
 // This function supports more HTML features than the editing variant below, such as tables.
 NSAttributedString *attributedStringFromRange(Range& range)
 {
-    HTMLConverter converter(range);
-    return converter.convert();
+    return HTMLConverter { range.startPosition(), range.endPosition() }.convert();
+}
+
+NSAttributedString *attributedStringFromSelection(const VisibleSelection& selection)
+{
+    auto range = selection.toNormalizedRange();
+    ASSERT(range);
+    return HTMLConverter { range->startPosition(), range->endPosition() }.convert();
 }
     
 #if !PLATFORM(IOS_FAMILY)