Title: [168652] branches/safari-538.34-branch/Source/WebCore

Diff

Modified: branches/safari-538.34-branch/Source/WebCore/ChangeLog (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/ChangeLog	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/ChangeLog	2014-05-12 23:01:49 UTC (rev 168652)
@@ -1,5 +1,61 @@
 2014-04-17  Lucas Forschler  <lforsch...@apple.com>
 
+        Merge r168650
+
+    2014-05-12  Brady Eidson  <beid...@apple.com>
+
+            Teach Editor to support more direct replacement of a Node
+            <rdar://problem/16817952> and https://bugs.webkit.org/show_bug.cgi?id=132834
+
+            Reviewed by Enrica Casucci.
+
+            The new method "Editor::replaceNodeFromPasteboard" has the intent that the new DocumentFragment
+            from the pasteboard is as similar to the old Node as possible.
+
+            In practice, the new DocumentFragment:
+            1 - Can represent a single node that's missing various attributes the original Node had.
+            2 - Can be an unwanted fragment of arbitrary depth when the replacement happens inside Mail.app
+
+            This fixes both of these issues.
+
+            Add a MailBlockquoteHandling enum class for various Editor operations to pass through to the
+            ReplaceSelectionCommand:
+            * editing/Editor.cpp:
+            (WebCore::Editor::handleTextEvent):
+            (WebCore::Editor::pasteAsFragment):
+            (WebCore::Editor::pasteWithPasteboard):
+            (WebCore::Editor::replaceSelectionWithFragment):
+            * editing/Editor.h:
+
+            * dom/TextEvent.cpp:
+            (WebCore::TextEvent::createForPlainTextPaste):
+            (WebCore::TextEvent::createForFragmentPaste):
+            (WebCore::TextEvent::TextEvent):
+            * dom/TextEvent.h:
+            (WebCore::TextEvent::mailBlockquoteHandling):
+
+            * editing/ReplaceSelectionCommand.cpp:
+            (WebCore::ReplaceSelectionCommand::ReplaceSelectionCommand):
+            (WebCore::ReplaceSelectionCommand::doApply): Consider whether or not this particular Editor
+              operation was meant to give special consideration to Mail's Blockquotes.
+            * editing/ReplaceSelectionCommand.h:
+
+            * editing/efl/EditorEfl.cpp:
+            (WebCore::Editor::pasteWithPasteboard):
+            * editing/ios/EditorIOS.mm:
+            (WebCore::Editor::pasteWithPasteboard):
+
+            * editing/mac/EditorMac.mm:
+            (WebCore::Editor::pasteWithPasteboard):
+            (WebCore::Editor::readSelectionFromPasteboard):
+            (WebCore::maybeCopyNodeAttributesToFragment): If the new DocumentFragment represents a single HTML node
+              with the same tag name is the original HTML node, copy over most attributes from the original node.
+            (WebCore::Editor::replaceNodeFromPasteboard): Create the fragment, run it through maybeCopyNodeAttributesToFragment.
+
+            * WebCore.exp.in:
+
+2014-04-17  Lucas Forschler  <lforsch...@apple.com>
+
         Merge r168565
 
     2014-05-09  Joseph Pecoraro  <pecor...@apple.com>

Modified: branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/WebCore.exp.in	2014-05-12 23:01:49 UTC (rev 168652)
@@ -1144,7 +1144,7 @@
 __ZN7WebCore6Editor13rangeForPointERKNS_8IntPointE
 __ZN7WebCore6Editor14setCompositionERKN3WTF6StringERKNS1_6VectorINS_20CompositionUnderlineELm0ENS1_15CrashOnOverflowEEEjj
 __ZN7WebCore6Editor14simplifyMarkupEPNS_4NodeES2_
-__ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbb
+__ZN7WebCore6Editor15pasteAsFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbNS_22MailBlockquoteHandlingE
 __ZN7WebCore6Editor16pasteAsPlainTextEv
 __ZN7WebCore6Editor17cancelCompositionEv
 __ZN7WebCore6Editor17insertOrderedListEv
@@ -1164,7 +1164,7 @@
 __ZN7WebCore6Editor26increaseSelectionListLevelEv
 __ZN7WebCore6Editor26toggleOverwriteModeEnabledEv
 __ZN7WebCore6Editor26writeSelectionToPasteboardERNS_10PasteboardE
-__ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbb
+__ZN7WebCore6Editor28replaceSelectionWithFragmentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbbNS_22MailBlockquoteHandlingE
 __ZN7WebCore6Editor28updateEditorUINowIfScheduledEv
 __ZN7WebCore6Editor29canDecreaseSelectionListLevelEv
 __ZN7WebCore6Editor29canIncreaseSelectionListLevelEv
@@ -2249,7 +2249,7 @@
 __ZN7WebCore6Editor24advanceToNextMisspellingEb
 __ZN7WebCore6Editor25replaceNodeFromPasteboardEPNS_4NodeERKN3WTF6StringE
 __ZN7WebCore6Editor26dataSelectionForPasteboardERKN3WTF6StringE
-__ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringE
+__ZN7WebCore6Editor27readSelectionFromPasteboardERKN3WTF6StringENS_22MailBlockquoteHandlingE
 __ZN7WebCore6Editor28stringSelectionForPasteboardEv
 __ZN7WebCore6Editor28toggleAutomaticLinkDetectionEv
 __ZN7WebCore6Editor30toggleAutomaticTextReplacementEv

Modified: branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.cpp	2014-05-12 23:01:49 UTC (rev 168652)
@@ -28,6 +28,7 @@
 #include "TextEvent.h"
 
 #include "DocumentFragment.h"
+#include "Editor.h"
 
 namespace WebCore {
 
@@ -43,12 +44,12 @@
 
 PassRefPtr<TextEvent> TextEvent::createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace)
 {
-    return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false));
+    return adoptRef(new TextEvent(view, data, 0, shouldSmartReplace, false, MailBlockquoteHandling::RespectBlockquote));
 }
 
-PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle)
+PassRefPtr<TextEvent> TextEvent::createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
 {
-    return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle));
+    return adoptRef(new TextEvent(view, "", data, shouldSmartReplace, shouldMatchStyle, mailBlockquoteHandling));
 }
 
 PassRefPtr<TextEvent> TextEvent::createForDrop(PassRefPtr<AbstractView> view, const String& data)
@@ -65,6 +66,7 @@
     : m_inputType(TextEventInputKeyboard)
     , m_shouldSmartReplace(false)
     , m_shouldMatchStyle(false)
+    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
 {
 }
 
@@ -75,17 +77,18 @@
     , m_pastingFragment(0)
     , m_shouldSmartReplace(false)
     , m_shouldMatchStyle(false)
+    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
 {
 }
 
-TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment,
-                     bool shouldSmartReplace, bool shouldMatchStyle)
+TextEvent::TextEvent(PassRefPtr<AbstractView> view, const String& data, PassRefPtr<DocumentFragment> pastingFragment, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling mailBlockquoteHandling)
     : UIEvent(eventNames().textInputEvent, true, true, view, 0)
     , m_inputType(TextEventInputPaste)
     , m_data(data)
     , m_pastingFragment(pastingFragment)
     , m_shouldSmartReplace(shouldSmartReplace)
     , m_shouldMatchStyle(shouldMatchStyle)
+    , m_mailBlockquoteHandling(mailBlockquoteHandling)
 {
 }
 
@@ -95,6 +98,7 @@
     , m_data(data)
     , m_shouldSmartReplace(false)
     , m_shouldMatchStyle(false)
+    , m_mailBlockquoteHandling(MailBlockquoteHandling::RespectBlockquote)
     , m_dictationAlternatives(dictationAlternatives)
 {
 }

Modified: branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/dom/TextEvent.h	2014-05-12 23:01:49 UTC (rev 168652)
@@ -35,14 +35,16 @@
 
     class DocumentFragment;
 
+    enum class MailBlockquoteHandling;
+
     class TextEvent : public UIEvent {
     public:
 
         static PassRefPtr<TextEvent> create();
         static PassRefPtr<TextEvent> create(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
-        static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView> view, const String& data, bool shouldSmartReplace);
-        static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView> view, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle);
-        static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView> view, const String& data);
+        static PassRefPtr<TextEvent> createForPlainTextPaste(PassRefPtr<AbstractView>, const String& data, bool shouldSmartReplace);
+        static PassRefPtr<TextEvent> createForFragmentPaste(PassRefPtr<AbstractView>, PassRefPtr<DocumentFragment> data, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
+        static PassRefPtr<TextEvent> createForDrop(PassRefPtr<AbstractView>, const String& data);
         static PassRefPtr<TextEvent> createForDictation(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
 
         virtual ~TextEvent();
@@ -62,6 +64,7 @@
 
         bool shouldSmartReplace() const { return m_shouldSmartReplace; }
         bool shouldMatchStyle() const { return m_shouldMatchStyle; }
+        MailBlockquoteHandling mailBlockquoteHandling() const { return m_mailBlockquoteHandling; }
         DocumentFragment* pastingFragment() const { return m_pastingFragment.get(); }
         const Vector<DictationAlternative>& dictationAlternatives() const { return m_dictationAlternatives; }
 
@@ -69,8 +72,7 @@
         TextEvent();
 
         TextEvent(PassRefPtr<AbstractView>, const String& data, TextEventInputType = TextEventInputKeyboard);
-        TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>,
-                  bool shouldSmartReplace, bool shouldMatchStyle);
+        TextEvent(PassRefPtr<AbstractView>, const String& data, PassRefPtr<DocumentFragment>, bool shouldSmartReplace, bool shouldMatchStyle, MailBlockquoteHandling);
         TextEvent(PassRefPtr<AbstractView>, const String& data, const Vector<DictationAlternative>& dictationAlternatives);
 
         virtual bool isTextEvent() const override;
@@ -81,6 +83,7 @@
         RefPtr<DocumentFragment> m_pastingFragment;
         bool m_shouldSmartReplace;
         bool m_shouldMatchStyle;
+        MailBlockquoteHandling m_mailBlockquoteHandling;
         Vector<DictationAlternative> m_dictationAlternatives;
     };
 

Modified: branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/Editor.cpp	2014-05-12 23:01:49 UTC (rev 168652)
@@ -266,7 +266,7 @@
             if (client()->performsTwoStepPaste(event->pastingFragment()))
                 return true;
 #endif
-            replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
+            replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle(), event->mailBlockquoteHandling());
 #if PLATFORM(IOS)
         }
 #endif
@@ -528,12 +528,12 @@
     target->dispatchEvent(TextEvent::createForPlainTextPaste(document().domWindow(), pastingText, smartReplace), IGNORE_EXCEPTION);
 }
 
-void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
+void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle, MailBlockquoteHandling respectsMailBlockquote)
 {
     Node* target = findEventTargetFromSelection();
     if (!target)
         return;
-    target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
+    target->dispatchEvent(TextEvent::createForFragmentPaste(document().domWindow(), pastingFragment, smartReplace, matchStyle, respectsMailBlockquote), IGNORE_EXCEPTION);
 }
 
 void Editor::pasteAsPlainTextBypassingDHTML()
@@ -565,7 +565,7 @@
 #endif
 
 #if !PLATFORM(COCOA) && !PLATFORM(EFL)
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
 {
     RefPtr<Range> range = selectedRange();
     if (!range)
@@ -574,7 +574,7 @@
     bool chosePlainText;
     RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, *range, allowPlainText, chosePlainText);
     if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
-        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText);
+        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), chosePlainText, mailBlockquoteHandling);
 }
 #endif
 
@@ -597,7 +597,7 @@
     return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
 }
 
-void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
+void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling mailBlockquoteHandling)
 {
     VisibleSelection selection = m_frame.selection().selection();
     if (selection.isNone() || !selection.isContentEditable() || !fragment)
@@ -610,6 +610,9 @@
         options |= ReplaceSelectionCommand::SmartReplace;
     if (matchStyle)
         options |= ReplaceSelectionCommand::MatchStyle;
+    if (mailBlockquoteHandling == MailBlockquoteHandling::IgnoreBlockquote)
+        options |= ReplaceSelectionCommand::IgnoreMailBlockquote;
+
     applyCommand(ReplaceSelectionCommand::create(document(), fragment, options, EditActionPaste));
     revealSelectionAfterEditingOperation();
 

Modified: branches/safari-538.34-branch/Source/WebCore/editing/Editor.h (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/Editor.h	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/Editor.h	2014-05-12 23:01:49 UTC (rev 168652)
@@ -90,6 +90,11 @@
 enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
 enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
 
+enum class MailBlockquoteHandling {
+    RespectBlockquote,
+    IgnoreBlockquote,
+};
+
 class Editor {
 public:
     explicit Editor(Frame&);
@@ -335,7 +340,7 @@
     void handleAlternativeTextUIResult(const String& correction);
     void dismissCorrectionPanelAsIgnored();
 
-    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle);
+    void pasteAsFragment(PassRefPtr<DocumentFragment>, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
     void pasteAsPlainText(const String&, bool smartReplace);
 
     // This is only called on the mac where paste is implemented primarily at the WebKit level.
@@ -377,7 +382,7 @@
     void textDidChangeInTextArea(Element*);
     WritingDirection baseWritingDirectionForSelectionStart() const;
 
-    void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle);
+    void replaceSelectionWithFragment(PassRefPtr<DocumentFragment>, bool selectReplacement, bool smartReplace, bool matchStyle, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
     void replaceSelectionWithText(const String&, bool selectReplacement, bool smartReplace);
     bool selectionStartHasMarkerFor(DocumentMarker::MarkerType, int from, int length) const;
     void updateMarkersForWordsAffectedByEditing(bool onlyHandleWordsContainingSelection);
@@ -431,7 +436,7 @@
 #if !PLATFORM(IOS)
     bool canCopyExcludingStandaloneImages();
     void takeFindStringFromSelection();
-    void readSelectionFromPasteboard(const String& pasteboardName);
+    void readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
     void replaceNodeFromPasteboard(Node*, const String& pasteboardName);
     PassRefPtr<SharedBuffer> dataSelectionForPasteboard(const String& pasteboardName);
 #endif // !PLATFORM(IOS)
@@ -450,7 +455,7 @@
     bool canDeleteRange(Range*) const;
     bool canSmartReplaceWithPasteboard(Pasteboard&);
     void pasteAsPlainTextWithPasteboard(Pasteboard&);
-    void pasteWithPasteboard(Pasteboard*, bool allowPlainText);
+    void pasteWithPasteboard(Pasteboard*, bool allowPlainText, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
     String plainTextFromPasteboard(const PasteboardPlainText&);
 
     void revealSelectionAfterEditingOperation(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);

Modified: branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.cpp	2014-05-12 23:01:49 UTC (rev 168652)
@@ -378,6 +378,7 @@
     , m_editAction(editAction)
     , m_sanitizeFragment(options & SanitizeFragment)
     , m_shouldMergeEnd(false)
+    , m_ignoreMailBlockquote(options & IgnoreMailBlockquote)
 {
 }
 
@@ -933,12 +934,12 @@
     Node* startBlock = enclosingBlock(visibleStart.deepEquivalent().deprecatedNode());
     
     Position insertionPos = selection.start();
-    bool startIsInsideMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary);
+    bool shouldHandleMailBlockquote = enclosingNodeOfType(insertionPos, isMailBlockquote, CanCrossEditingBoundary) && !m_ignoreMailBlockquote;
     bool selectionIsPlainText = !selection.isContentRichlyEditable();
     Element* currentRoot = selection.rootEditableElement();
 
-    if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !startIsInsideMailBlockquote) ||
-        startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
+    if ((selectionStartWasStartOfParagraph && selectionEndWasEndOfParagraph && !shouldHandleMailBlockquote)
+        || startBlock == currentRoot || isListItem(startBlock) || selectionIsPlainText)
         m_preventNesting = false;
     
     if (selection.isRange()) {
@@ -948,7 +949,7 @@
         // will leave hanging block(s).
         // Merge blocks if the start of the selection was in a Mail blockquote, since we handle  
         // that case specially to prevent nesting. 
-        bool mergeBlocksAfterDelete = startIsInsideMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
+        bool mergeBlocksAfterDelete = shouldHandleMailBlockquote || isEndOfParagraph(visibleEnd) || isStartOfBlock(visibleStart);
         // FIXME: We should only expand to include fully selected special elements if we are copying a 
         // selection and pasting it on top of itself.
         deleteSelection(false, mergeBlocksAfterDelete, true, false);
@@ -977,7 +978,7 @@
         // As long as the  div styles are the same, visually you'd expect: <div>xbar</div><div>bar</div><div>bazx</div>, 
         // not <div>xbar<div>bar</div><div>bazx</div></div>.
         // Don't do this if the selection started in a Mail blockquote.
-        if (m_preventNesting && !startIsInsideMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
+        if (m_preventNesting && !shouldHandleMailBlockquote && !isEndOfParagraph(visibleStart) && !isStartOfParagraph(visibleStart)) {
             insertParagraphSeparator();
             setEndingSelection(endingSelection().visibleStart().previous());
         }
@@ -987,7 +988,7 @@
     // We don't want any of the pasted content to end up nested in a Mail blockquote, so first break 
     // out of any surrounding Mail blockquotes. Unless we're inserting in a table, in which case
     // breaking the blockquote will prevent the content from actually being inserted in the table.
-    if (startIsInsideMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) { 
+    if (shouldHandleMailBlockquote && m_preventNesting && !(enclosingNodeOfType(insertionPos, &isTableStructureNode))) {
         applyCommandToComposite(BreakBlockquoteCommand::create(document())); 
         // This will leave a br between the split. 
         Node* br = endingSelection().start().deprecatedNode(); 
@@ -1016,7 +1017,7 @@
     
     // Adjust insertionPos to prevent nesting.
     // If the start was in a Mail blockquote, we will have already handled adjusting insertionPos above.
-    if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !startIsInsideMailBlockquote) {
+    if (m_preventNesting && insertionBlock && !isTableCell(insertionBlock.get()) && !shouldHandleMailBlockquote) {
         ASSERT(insertionBlock != currentRoot);
         VisiblePosition visibleInsertionPos(insertionPos);
         if (isEndOfBlock(visibleInsertionPos) && !(isStartOfBlock(visibleInsertionPos) && fragment.hasInterchangeNewlineAtEnd()))
@@ -1162,7 +1163,7 @@
     // the start merge so that the start merge doesn't effect our decision.
     m_shouldMergeEnd = shouldMergeEnd(selectionEndWasEndOfParagraph);
     
-    if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), startIsInsideMailBlockquote)) {
+    if (shouldMergeStart(selectionStartWasStartOfParagraph, fragment.hasInterchangeNewlineAtStart(), shouldHandleMailBlockquote)) {
         VisiblePosition startOfParagraphToMove = positionAtStartOfInsertedContent();
         VisiblePosition destination = startOfParagraphToMove.previous();
         // We need to handle the case where we need to merge the end
@@ -1211,7 +1212,7 @@
                 } else {
                     // Use a default paragraph element (a plain div) for the empty paragraph, using the last paragraph
                     // block's style seems to annoy users.
-                    insertParagraphSeparator(true, !startIsInsideMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
+                    insertParagraphSeparator(true, !shouldHandleMailBlockquote && highestEnclosingNodeOfType(endOfInsertedContent.deepEquivalent(),
                         isMailBlockquote, CannotCrossEditingBoundary, insertedNodes.firstNodeInserted()->parentNode()));
                 }
 

Modified: branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ReplaceSelectionCommand.h	2014-05-12 23:01:49 UTC (rev 168652)
@@ -42,7 +42,8 @@
         MatchStyle = 1 << 2,
         PreventNesting = 1 << 3,
         MovingParagraph = 1 << 4,
-        SanitizeFragment = 1 << 5
+        SanitizeFragment = 1 << 5,
+        IgnoreMailBlockquote = 1 << 6,
     };
 
     typedef unsigned CommandOptions;
@@ -115,6 +116,7 @@
     EditAction m_editAction;
     bool m_sanitizeFragment;
     bool m_shouldMergeEnd;
+    bool m_ignoreMailBlockquote;
 };
 
 } // namespace WebCore

Modified: branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/efl/EditorEfl.cpp	2014-05-12 23:01:49 UTC (rev 168652)
@@ -42,7 +42,7 @@
     notImplemented();
 }
 
-void Editor::pasteWithPasteboard(Pasteboard*, bool)
+void Editor::pasteWithPasteboard(Pasteboard*, bool, MailBlockquoteHandling)
 {
     notImplemented();
 }

Modified: branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/ios/EditorIOS.mm	2014-05-12 23:01:49 UTC (rev 168652)
@@ -536,7 +536,7 @@
     return reader.fragment.release();
 }
 
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
 {
     RefPtr<Range> range = selectedRange();
 
@@ -546,7 +546,7 @@
         fragment = webContentFromPasteboard(*pasteboard, *range, allowPlainText, chosePlainText);
 
     if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
-        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
+        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
 }
 
 PassRefPtr<DocumentFragment> Editor::createFragmentAndAddResources(NSAttributedString *string)

Modified: branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm (168651 => 168652)


--- branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm	2014-05-12 22:57:46 UTC (rev 168651)
+++ branches/safari-538.34-branch/Source/WebCore/editing/mac/EditorMac.mm	2014-05-12 23:01:49 UTC (rev 168652)
@@ -81,7 +81,7 @@
     [[NSApplication sharedApplication] orderFrontColorPanel:nil];
 }
 
-void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
+void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText, MailBlockquoteHandling mailBlockquoteHandling)
 {
     RefPtr<Range> range = selectedRange();
 
@@ -92,7 +92,7 @@
     RefPtr<DocumentFragment> fragment = webContentFromPasteboard(*pasteboard, *range, allowPlainText, chosePlainText);
 
     if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
-        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false);
+        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(*pasteboard), false, mailBlockquoteHandling);
 
     client()->setInsertionPasteboard(String());
 }
@@ -256,15 +256,39 @@
     platformStrategies()->pasteboardStrategy()->setStringForType(m_frame.displayStringModifiedByEncoding(selectedTextForDataTransfer()), NSStringPboardType, NSFindPboard);
 }
 
-void Editor::readSelectionFromPasteboard(const String& pasteboardName)
+void Editor::readSelectionFromPasteboard(const String& pasteboardName, MailBlockquoteHandling mailBlockquoteHandling)
 {
     Pasteboard pasteboard(pasteboardName);
     if (m_frame.selection().selection().isContentRichlyEditable())
-        pasteWithPasteboard(&pasteboard, true);
+        pasteWithPasteboard(&pasteboard, true, mailBlockquoteHandling);
     else
         pasteAsPlainTextWithPasteboard(pasteboard);
 }
 
+static void maybeCopyNodeAttributesToFragment(Node* node, DocumentFragment* fragment)
+{
+    // This is only supported for single-Node fragments.
+    Node* firstChild = fragment->firstChild();
+    if (firstChild != fragment->lastChild())
+        return;
+
+    // And only supported for HTML elements.
+    if (!node->isHTMLElement() || !firstChild->isHTMLElement())
+        return;
+
+    // And only if the source Element and destination Element have the same HTML tag name.
+    const Element& oldElement = toHTMLElement(*node);
+    Element& newElement = toHTMLElement(*firstChild);
+    if (!oldElement.hasTagName(newElement.tagQName()))
+        return;
+
+    for (const Attribute& attribute : oldElement.attributesIterator()) {
+        if (newElement.hasAttribute(attribute.name()))
+            continue;
+        newElement.setAttribute(attribute.name(), attribute.value());
+    }
+}
+
 void Editor::replaceNodeFromPasteboard(Node* node, const String& pasteboardName)
 {
     ASSERT(node);
@@ -275,7 +299,25 @@
     RefPtr<Range> range = Range::create(node->document(), Position(node, Position::PositionIsBeforeAnchor), Position(node, Position::PositionIsAfterAnchor));
     m_frame.selection().setSelection(VisibleSelection(range.get()), FrameSelection::DoNotSetFocus);
 
-    readSelectionFromPasteboard(pasteboardName);
+    Pasteboard pasteboard(pasteboardName);
+
+    if (!m_frame.selection().selection().isContentRichlyEditable()) {
+        pasteAsPlainTextWithPasteboard(pasteboard);
+        return;
+    }
+
+    // FIXME: How can this hard-coded pasteboard name be right, given that the passed-in pasteboard has a name?
+    client()->setInsertionPasteboard(NSGeneralPboard);
+
+    bool chosePlainText;
+    RefPtr<DocumentFragment> fragment = webContentFromPasteboard(pasteboard, *range, true, chosePlainText);
+
+    maybeCopyNodeAttributesToFragment(node, fragment.get());
+
+    if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
+        pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false, MailBlockquoteHandling::IgnoreBlockquote);
+
+    client()->setInsertionPasteboard(String());
 }
 
 // FIXME: Makes no sense that selectedTextForDataTransfer always includes alt text, but stringSelectionForPasteboard does not.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to