Title: [218014] trunk
Revision
218014
Author
[email protected]
Date
2017-06-09 13:10:59 -0700 (Fri, 09 Jun 2017)

Log Message

[iOS DnD] Add a hook to perform two-step drops in editable content
https://bugs.webkit.org/show_bug.cgi?id=172992
<rdar://problem/32590174>

Reviewed by Tim Horton.

Source/WebCore:

Adds hooks in DragController::concludeEditDrag to give the client layer a chance to perform custom handling when
dropping in editable content.
Tests:  DataInteractionTests.InjectedBundleOverridePerformTwoStepDrop
        DataInteractionTests.InjectedBundleAllowPerformTwoStepDrop

* loader/EmptyClients.cpp:
* page/DragController.cpp:
(WebCore::DragController::concludeEditDrag):
* page/EditorClient.h:

Source/WebKit/ios:

Add an empty implementation of performTwoStepDrop for WebDefaultUIKitDelegate. See WebCore ChangeLogs.

* DefaultDelegates/WebDefaultUIKitDelegate.m:
(-[WebDefaultUIKitDelegate performTwoStepDrop:atDestination:isMove:]):
* WebView/WebUIKitDelegate.h:

Source/WebKit/mac:

Adds a new SPI to WebUIKitDelegate to allow WK1 clients to override default drop behavior. Returning YES from
-performTwoStepDrop:atDestination:isMove: will prevent content from being inserted on drop in WebKit; otherwise,
returning NO will continue with default WebKit behavior.

* WebCoreSupport/WebEditorClient.h:
* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::performTwoStepDrop):

Source/WebKit/win:

Add a stub implementation for performTwoStepDrop on Windows.

* WebCoreSupport/WebEditorClient.h:

Source/WebKit2:

Add plumbing to support an injected bundle hook for overriding two-step drops. See WebCore ChangeLog.

* WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h:
(API::InjectedBundle::EditorClient::performTwoStepDrop):
* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h:
* WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h:
* WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
(-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
* WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp:
(WebKit::InjectedBundlePageEditorClient::performTwoStepDrop):
* WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::performTwoStepDrop):
* WebProcess/WebCoreSupport/WebEditorClient.h:

Tools:

Adds 2 new API tests to cover using the injected editing bundle to override performTwoStepDrop.
Tests:  DataInteractionTests.InjectedBundleOverridePerformTwoStepDrop
        DataInteractionTests.InjectedBundleAllowPerformTwoStepDrop

* TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegatePlugIn.mm:
(-[BundleEditingDelegatePlugIn webProcessPlugIn:didCreateBrowserContextController:]):
(-[BundleEditingDelegatePlugIn _webProcessPlugInBrowserContextController:performTwoStepDrop:atDestination:isMove:]):

Allow the BundleOverridePerformTwoStepDrop bundle parameter to determine whether or not two-step drops should
be overridden. Currently, this is overridden to just return true.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):
* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::InjectedBundlePage):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (218013 => 218014)


--- trunk/Source/WebCore/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebCore/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,21 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Adds hooks in DragController::concludeEditDrag to give the client layer a chance to perform custom handling when
+        dropping in editable content.
+        Tests:  DataInteractionTests.InjectedBundleOverridePerformTwoStepDrop
+                DataInteractionTests.InjectedBundleAllowPerformTwoStepDrop
+
+        * loader/EmptyClients.cpp:
+        * page/DragController.cpp:
+        (WebCore::DragController::concludeEditDrag):
+        * page/EditorClient.h:
+
 2017-06-09  Matthew Hanson  <[email protected]>
 
         Revert r217955. rdar://problem/21125708

Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (218013 => 218014)


--- trunk/Source/WebCore/loader/EmptyClients.cpp	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp	2017-06-09 20:10:59 UTC (rev 218014)
@@ -213,6 +213,8 @@
     int pasteboardChangeCount() final { return 0; }
 #endif
 
+    bool performTwoStepDrop(DocumentFragment&, Range&, bool) final { return false; }
+
 #if PLATFORM(COCOA)
     NSString *userVisibleString(NSURL *) final { return nullptr; }
     void setInsertionPasteboard(const String&) final { };

Modified: trunk/Source/WebCore/page/DragController.cpp (218013 => 218014)


--- trunk/Source/WebCore/page/DragController.cpp	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebCore/page/DragController.cpp	2017-06-09 20:10:59 UTC (rev 218014)
@@ -569,18 +569,23 @@
         return false;
 
     ResourceCacheValidationSuppressor validationSuppressor(range->ownerDocument().cachedResourceLoader());
-    if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) {
+    auto& editor = innerFrame->editor();
+    bool isMove = dragIsMove(innerFrame->selection(), dragData);
+    if (isMove || dragCaret.isContentRichlyEditable()) {
         bool chosePlainText = false;
         RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, *innerFrame, *range, true, chosePlainText);
-        if (!fragment || !innerFrame->editor().shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Dropped)) {
+        if (!fragment || !editor.shouldInsertFragment(*fragment, range.get(), EditorInsertAction::Dropped))
             return false;
-        }
 
         m_client.willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
-        if (dragIsMove(innerFrame->selection(), dragData)) {
+
+        if (editor.client() && editor.client()->performTwoStepDrop(*fragment, *range, isMove))
+            return true;
+
+        if (isMove) {
             // NSTextView behavior is to always smart delete on moving a selection,
             // but only to smart insert if the selection granularity is word granularity.
-            bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled();
+            bool smartDelete = editor.smartInsertDeleteEnabled();
             bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData.canSmartReplace();
             MoveSelectionCommand::create(fragment.releaseNonNull(), dragCaret.base(), smartInsert, smartDelete)->apply();
         } else {
@@ -595,13 +600,19 @@
         }
     } else {
         String text = dragData.asPlainText();
-        if (text.isEmpty() || !innerFrame->editor().shouldInsertText(text, range.get(), EditorInsertAction::Dropped)) {
+        if (text.isEmpty() || !editor.shouldInsertText(text, range.get(), EditorInsertAction::Dropped))
             return false;
-        }
 
         m_client.willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
+        RefPtr<DocumentFragment> fragment = createFragmentFromText(*range, text);
+        if (!fragment)
+            return false;
+
+        if (editor.client() && editor.client()->performTwoStepDrop(*fragment, *range, isMove))
+            return true;
+
         if (setSelectionToDragCaret(innerFrame.get(), dragCaret, range, point))
-            ReplaceSelectionCommand::create(*m_documentUnderMouse, createFragmentFromText(*range, text),  ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting, EditActionInsertFromDrop)->apply();
+            ReplaceSelectionCommand::create(*m_documentUnderMouse, fragment.get(), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting, EditActionInsertFromDrop)->apply();
     }
 
     if (rootEditableElement) {

Modified: trunk/Source/WebCore/page/EditorClient.h (218013 => 218014)


--- trunk/Source/WebCore/page/EditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebCore/page/EditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -185,6 +185,8 @@
     // Support for global selections, used on platforms like the X Window System that treat
     // selection as a type of clipboard.
     virtual bool supportsGlobalSelection() { return false; }
+
+    virtual bool performTwoStepDrop(DocumentFragment&, Range& destination, bool isMove) = 0;
 };
 
 }

Modified: trunk/Source/WebKit/ios/ChangeLog (218013 => 218014)


--- trunk/Source/WebKit/ios/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/ios/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,17 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Add an empty implementation of performTwoStepDrop for WebDefaultUIKitDelegate. See WebCore ChangeLogs.
+
+        * DefaultDelegates/WebDefaultUIKitDelegate.m:
+        (-[WebDefaultUIKitDelegate performTwoStepDrop:atDestination:isMove:]):
+        * WebView/WebUIKitDelegate.h:
+
 2017-06-07  Zalan Bujtas  <[email protected]>
 
         [iOS WK1 WebThread] Do not call out to the main thread for device orientation.

Modified: trunk/Source/WebKit/ios/DefaultDelegates/WebDefaultUIKitDelegate.m (218013 => 218014)


--- trunk/Source/WebKit/ios/DefaultDelegates/WebDefaultUIKitDelegate.m	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/ios/DefaultDelegates/WebDefaultUIKitDelegate.m	2017-06-09 20:10:59 UTC (rev 218014)
@@ -27,6 +27,7 @@
 
 #import "WebDefaultUIKitDelegate.h"
 
+#import "DOMRange.h"
 #import "WebUIDelegate.h"
 
 static WebDefaultUIKitDelegate *sharedDelegate = nil;
@@ -262,6 +263,11 @@
     return NO;
 }
 
+- (BOOL)performTwoStepDrop:(DOMDocumentFragment *)fragment atDestination:(DOMRange *)destination isMove:(BOOL)isMove
+{
+    return NO;
+}
+
 - (NSInteger)getPasteboardChangeCount
 {
     return 0;

Modified: trunk/Source/WebKit/ios/WebView/WebUIKitDelegate.h (218013 => 218014)


--- trunk/Source/WebKit/ios/WebView/WebUIKitDelegate.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/ios/WebView/WebUIKitDelegate.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -29,8 +29,9 @@
 #import <WebKitLegacy/WAKAppKitStubs.h>
 #import <WebKitLegacy/WKContentObservation.h>
 
+@class DOMDocumentFragment;
 @class DOMNode;
-@class DOMDocumentFragment;
+@class DOMRange;
 @class WAKView;
 @class WebDataSource;
 @class WebFrame;
@@ -118,6 +119,7 @@
 - (NSArray*)supportedPasteboardTypesForCurrentSelection;
 - (BOOL)hasRichlyEditableSelection;
 - (BOOL)performsTwoStepPaste:(DOMDocumentFragment*)fragment;
+- (BOOL)performTwoStepDrop:(DOMDocumentFragment *)fragment atDestination:(DOMRange *)destination isMove:(BOOL)isMove;
 - (NSInteger)getPasteboardChangeCount;
 - (CGPoint)interactionLocation;
 - (void)showPlaybackTargetPicker:(BOOL)hasVideo fromRect:(CGRect)elementRect;

Modified: trunk/Source/WebKit/mac/ChangeLog (218013 => 218014)


--- trunk/Source/WebKit/mac/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/mac/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,19 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Adds a new SPI to WebUIKitDelegate to allow WK1 clients to override default drop behavior. Returning YES from
+        -performTwoStepDrop:atDestination:isMove: will prevent content from being inserted on drop in WebKit; otherwise,
+        returning NO will continue with default WebKit behavior.
+
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::performTwoStepDrop):
+
 2017-06-08  Jer Noble  <[email protected]>
 
         Clients of the WK2 C-API don't have their mediaContentTypesRequiringHardwareSupport setting initialized correctly.

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -150,6 +150,8 @@
     bool performsTwoStepPaste(WebCore::DocumentFragment*) final;
     int pasteboardChangeCount() final;
 #endif
+
+    bool performTwoStepDrop(WebCore::DocumentFragment&, WebCore::Range& destination, bool isMove) final;
     
     bool shouldEraseMarkersAfterChangeSelection(WebCore::TextCheckingType) const final;
     void ignoreWordInSpellDocument(const String&) final;

Modified: trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm (218013 => 218014)


--- trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm	2017-06-09 20:10:59 UTC (rev 218014)
@@ -923,6 +923,14 @@
     return false;
 }
 
+bool WebEditorClient::performTwoStepDrop(DocumentFragment& fragment, Range& destination, bool isMove)
+{
+    if ([[m_webView _UIKitDelegateForwarder] respondsToSelector:@selector(performTwoStepDrop:atDestination:isMove:)])
+        return [[m_webView _UIKitDelegateForwarder] performTwoStepDrop:kit(&fragment) atDestination:kit(&destination) isMove:isMove];
+
+    return false;
+}
+
 int WebEditorClient::pasteboardChangeCount()
 {
     if ([[m_webView _UIKitDelegateForwarder] respondsToSelector:@selector(getPasteboardChangeCount)])
@@ -955,6 +963,11 @@
 
 #if !PLATFORM(IOS)
 
+bool WebEditorClient::performTwoStepDrop(DocumentFragment&, Range&, bool)
+{
+    return false;
+}
+
 bool WebEditorClient::shouldEraseMarkersAfterChangeSelection(TextCheckingType type) const
 {
     // This prevents erasing spelling markers on OS X Lion or later to match AppKit on these Mac OS X versions.

Modified: trunk/Source/WebKit/win/ChangeLog (218013 => 218014)


--- trunk/Source/WebKit/win/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/win/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,15 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Add a stub implementation for performTwoStepDrop on Windows.
+
+        * WebCoreSupport/WebEditorClient.h:
+
 2017-06-04  Konstantin Tokarev  <[email protected]>
 
         Fix build of Windows-specific code with ICU 59.1

Modified: trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -111,6 +111,7 @@
     void willSetInputMethodState() final;
     void setInputMethodState(bool) final;
     void requestCheckingOfString(WebCore::TextCheckingRequest&, const WebCore::VisibleSelection&) final { }
+    bool performTwoStepDrop(WebCore::DocumentFragment&, WebCore::Range&, bool) final { return false; }
 
     WebCore::TextCheckerClient* textChecker() final { return this; }
 

Modified: trunk/Source/WebKit2/ChangeLog (218013 => 218014)


--- trunk/Source/WebKit2/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,26 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Add plumbing to support an injected bundle hook for overriding two-step drops. See WebCore ChangeLog.
+
+        * WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h:
+        (API::InjectedBundle::EditorClient::performTwoStepDrop):
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h:
+        * WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h:
+        * WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
+        (-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
+        * WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp:
+        (WebKit::InjectedBundlePageEditorClient::performTwoStepDrop):
+        * WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::performTwoStepDrop):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2017-06-09  Brent Fulgham  <[email protected]>
 
         Use Function rather than std::function for thread safety in WebsiteDataStore

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 class CSSStyleDeclaration;
+class DocumentFragment;
 class Node;
 class Range;
 class SharedBuffer;
@@ -63,6 +64,7 @@
     virtual void willWriteToPasteboard(WebKit::WebPage&, WebCore::Range*) { }
     virtual void getPasteboardDataForRange(WebKit::WebPage&, WebCore::Range*, Vector<WTF::String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) { }
     virtual void didWriteToPasteboard(WebKit::WebPage&) { }
+    virtual bool performTwoStepDrop(WebKit::WebPage&, WebCore::DocumentFragment&, WebCore::Range&, bool) { return false; }
 };
 
 } // namespace InjectedBundle

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -28,6 +28,7 @@
 #if WK_API_ENABLED
 
 #import <WebKit/WKWebProcessPlugInBrowserContextController.h>
+#import <WebKit/WKWebProcessPlugInNodeHandle.h>
 #import <WebKit/WKWebProcessPlugInRangeHandle.h>
 
 #if TARGET_OS_IPHONE
@@ -59,6 +60,7 @@
 - (void)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller willWriteRangeToPasteboard:(WKWebProcessPlugInRangeHandle *)range;
 - (NSDictionary<NSString *, NSData *> *)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller pasteboardDataForRange:(WKWebProcessPlugInRangeHandle *)range;
 - (void)_webProcessPlugInBrowserContextControllerDidWriteToPasteboard:(WKWebProcessPlugInBrowserContextController *)controller;
+- (BOOL)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller performTwoStepDrop:(WKWebProcessPlugInNodeHandle *)fragment atDestination:(WKWebProcessPlugInRangeHandle *)destination isMove:(BOOL)isMove;
 
 @end
 

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -63,6 +63,7 @@
 typedef void (*WKBundlePageWillWriteToPasteboard)(WKBundlePageRef page, WKBundleRangeHandleRef range,  const void* clientInfo);
 typedef void (*WKBundlePageGetPasteboardDataForRange)(WKBundlePageRef page, WKBundleRangeHandleRef range, WKArrayRef* pasteboardTypes, WKArrayRef* pasteboardData, const void* clientInfo);
 typedef void (*WKBundlePageDidWriteToPasteboard)(WKBundlePageRef page, const void* clientInfo);
+typedef bool (*WKBundlePagePerformTwoStepDrop)(WKBundlePageRef page, WKBundleNodeHandleRef fragment, WKBundleRangeHandleRef destination, bool isMove, const void* clientInfo);
 
 typedef struct WKBundlePageEditorClientBase {
     int                                                                 version;
@@ -106,6 +107,7 @@
     WKBundlePageWillWriteToPasteboard                                   willWriteToPasteboard;
     WKBundlePageGetPasteboardDataForRange                               getPasteboardDataForRange;
     WKBundlePageDidWriteToPasteboard                                    didWriteToPasteboard;
+    WKBundlePagePerformTwoStepDrop                                      performTwoStepDrop;
 } WKBundlePageEditorClientV1;
 
 #endif // WKBundlePageEditorClient_h

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2017-06-09 20:10:59 UTC (rev 218014)
@@ -60,6 +60,7 @@
 #import "_WKRenderingProgressEventsInternal.h"
 #import "_WKSameDocumentNavigationTypeInternal.h"
 #import <WebCore/Document.h>
+#import <WebCore/DocumentFragment.h>
 #import <WebCore/Frame.h>
 #import <WebCore/HTMLFormElement.h>
 #import <WebCore/HTMLInputElement.h>
@@ -658,6 +659,16 @@
             [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextControllerDidWriteToPasteboard:m_controller];
         }
 
+        bool performTwoStepDrop(WebKit::WebPage&, WebCore::DocumentFragment& fragment, WebCore::Range& range, bool isMove) final
+        {
+            if (!m_delegateMethods.performTwoStepDrop)
+                return false;
+
+            auto rangeHandle = InjectedBundleRangeHandle::getOrCreate(&range);
+            auto nodeHandle = InjectedBundleNodeHandle::getOrCreate(&fragment);
+            return [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextController:m_controller performTwoStepDrop:wrapper(*nodeHandle) atDestination:wrapper(*rangeHandle) isMove:isMove];
+        }
+
         WKWebProcessPlugInBrowserContextController *m_controller;
         const struct DelegateMethods {
             DelegateMethods(RetainPtr<id <WKWebProcessPlugInEditingDelegate>> delegate)
@@ -667,6 +678,7 @@
                 , willWriteToPasteboard([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:willWriteRangeToPasteboard:)])
                 , getPasteboardDataForRange([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:pasteboardDataForRange:)])
                 , didWriteToPasteboard([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextControllerDidWriteToPasteboard:)])
+                , performTwoStepDrop([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:performTwoStepDrop:atDestination:isMove:)])
             {
             }
 
@@ -676,6 +688,7 @@
             bool willWriteToPasteboard;
             bool getPasteboardDataForRange;
             bool didWriteToPasteboard;
+            bool performTwoStepDrop;
         } m_delegateMethods;
     };
 

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp	2017-06-09 20:10:59 UTC (rev 218014)
@@ -35,6 +35,7 @@
 #include "WKBundleAPICast.h"
 #include "WKString.h"
 #include "WebPage.h"
+#include <WebCore/DocumentFragment.h>
 #include <wtf/text/WTFString.h>
 
 using namespace WebCore;
@@ -172,6 +173,16 @@
     }
 }
 
+bool InjectedBundlePageEditorClient::performTwoStepDrop(WebPage& page, DocumentFragment& fragment, Range& destination, bool isMove)
+{
+    if (!m_client.performTwoStepDrop)
+        return false;
+
+    auto rangeHandle = InjectedBundleRangeHandle::getOrCreate(&destination);
+    auto nodeHandle = InjectedBundleNodeHandle::getOrCreate(&fragment);
+    return m_client.performTwoStepDrop(toAPI(&page), toAPI(nodeHandle.get()), toAPI(rangeHandle.get()), isMove, m_client.base.clientInfo);
+}
+
 void InjectedBundlePageEditorClient::didWriteToPasteboard(WebPage& page)
 {
     if (m_client.didWriteToPasteboard)

Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -37,6 +37,7 @@
 
 namespace WebCore {
 class CSSStyleDeclaration;
+class DocumentFragment;
 class Node;
 class Range;
 }
@@ -65,6 +66,7 @@
     void willWriteToPasteboard(WebPage&, WebCore::Range*) final;
     void getPasteboardDataForRange(WebPage&, WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final;
     void didWriteToPasteboard(WebPage&) final;
+    bool performTwoStepDrop(WebPage&, WebCore::DocumentFragment&, WebCore::Range& destination, bool isMove) final;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp	2017-06-09 20:10:59 UTC (rev 218014)
@@ -239,6 +239,11 @@
     m_page->injectedBundleEditorClient().getPasteboardDataForRange(*m_page, range, pasteboardTypes, pasteboardData);
 }
 
+bool WebEditorClient::performTwoStepDrop(DocumentFragment& fragment, Range& destination, bool isMove)
+{
+    return m_page->injectedBundleEditorClient().performTwoStepDrop(*m_page, fragment, destination, isMove);
+}
+
 void WebEditorClient::registerUndoStep(UndoStep& step)
 {
     // FIXME: Add assertion that the command being reapplied is the same command that is

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h (218013 => 218014)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h	2017-06-09 20:10:59 UTC (rev 218014)
@@ -168,6 +168,7 @@
     int pasteboardChangeCount() final;
 #endif
 
+    bool performTwoStepDrop(WebCore::DocumentFragment&, WebCore::Range&, bool isMove) final;
     bool supportsGlobalSelection() final;
 
     WebPage* m_page;

Modified: trunk/Tools/ChangeLog (218013 => 218014)


--- trunk/Tools/ChangeLog	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Tools/ChangeLog	2017-06-09 20:10:59 UTC (rev 218014)
@@ -1,3 +1,27 @@
+2017-06-09  Wenson Hsieh  <[email protected]>
+
+        [iOS DnD] Add a hook to perform two-step drops in editable content
+        https://bugs.webkit.org/show_bug.cgi?id=172992
+        <rdar://problem/32590174>
+
+        Reviewed by Tim Horton.
+
+        Adds 2 new API tests to cover using the injected editing bundle to override performTwoStepDrop.
+        Tests:  DataInteractionTests.InjectedBundleOverridePerformTwoStepDrop
+                DataInteractionTests.InjectedBundleAllowPerformTwoStepDrop
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegatePlugIn.mm:
+        (-[BundleEditingDelegatePlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+        (-[BundleEditingDelegatePlugIn _webProcessPlugInBrowserContextController:performTwoStepDrop:atDestination:isMove:]):
+
+        Allow the BundleOverridePerformTwoStepDrop bundle parameter to determine whether or not two-step drops should
+        be overridden. Currently, this is overridden to just return true.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::InjectedBundlePage):
+
 2017-06-09  Zan Dobersek  <[email protected]>
 
         [WPE] Enable ENCRYPTED_MEDIA for build-webkit builds

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegatePlugIn.mm (218013 => 218014)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegatePlugIn.mm	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegatePlugIn.mm	2017-06-09 20:10:59 UTC (rev 218014)
@@ -46,6 +46,7 @@
     RetainPtr<WKWebProcessPlugInController> _plugInController;
     RetainPtr<id <BundleEditingDelegateProtocol>> _remoteObject;
     BOOL _editingDelegateShouldInsertText;
+    BOOL _shouldOverridePerformTwoStepDrop;
 }
 
 - (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
@@ -61,6 +62,8 @@
     } else
         _editingDelegateShouldInsertText = YES;
 
+    _shouldOverridePerformTwoStepDrop = [[plugInController.parameters valueForKey:@"BundleOverridePerformTwoStepDrop"] boolValue];
+
     _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(BundleEditingDelegateProtocol)];
     _remoteObject = [browserContextController._remoteObjectRegistry remoteObjectProxyWithInterface:interface];
 
@@ -90,6 +93,11 @@
     [_remoteObject didWriteToPasteboard];
 }
 
+- (BOOL)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller performTwoStepDrop:(WKWebProcessPlugInNodeHandle *)fragment atDestination:(WKWebProcessPlugInRangeHandle *)destination isMove:(BOOL)isMove
+{
+    return _shouldOverridePerformTwoStepDrop;
+}
+
 @end
 
 #endif // WK_API_ENABLED

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (218013 => 218014)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-06-09 20:10:59 UTC (rev 218014)
@@ -37,6 +37,7 @@
 #import <UIKit/UIImage+UIItemProvider.h>
 #import <UIKit/UIItemProvider_Private.h>
 #import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
 #import <WebKit/_WKProcessPoolConfiguration.h>
 
@@ -711,6 +712,52 @@
     TestWebKitAPI::Util::run(&finishedLoadingData);
 }
 
+TEST(DataInteractionTests, InjectedBundleOverridePerformTwoStepDrop)
+{
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];
+    [configuration.processPool _setObject:@YES forBundleParameter:@"BundleOverridePerformTwoStepDrop"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration]);
+    [webView loadTestPageNamed:@"autofocus-contenteditable"];
+    [webView stringByEvaluatingJavaScript:@"getSelection().removeAllRanges()"];
+
+    auto simulatedItemProvider = adoptNS([[UIItemProvider alloc] init]);
+    [simulatedItemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeUTF8PlainText options:nil loadHandler:^NSProgress *(UIItemProviderDataLoadCompletionBlock completionBlock)
+    {
+        completionBlock([@"Hello world" dataUsingEncoding:NSUTF8StringEncoding], nil);
+        return [NSProgress discreteProgressWithTotalUnitCount:100];
+    }];
+
+    auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [dataInteractionSimulator setExternalItemProviders:@[ simulatedItemProvider.get() ]];
+    [dataInteractionSimulator runFrom:CGPointMake(300, 400) to:CGPointMake(100, 300)];
+
+    EXPECT_EQ(0UL, [webView stringByEvaluatingJavaScript:@"editor.textContent"].length);
+}
+
+TEST(DataInteractionTests, InjectedBundleAllowPerformTwoStepDrop)
+{
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];
+    [configuration.processPool _setObject:@NO forBundleParameter:@"BundleOverridePerformTwoStepDrop"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500) configuration:configuration]);
+    [webView loadTestPageNamed:@"autofocus-contenteditable"];
+    [webView stringByEvaluatingJavaScript:@"getSelection().removeAllRanges()"];
+
+    auto simulatedItemProvider = adoptNS([[UIItemProvider alloc] init]);
+    [simulatedItemProvider registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeUTF8PlainText options:nil loadHandler:^NSProgress *(UIItemProviderDataLoadCompletionBlock completionBlock)
+    {
+        completionBlock([@"Hello world" dataUsingEncoding:NSUTF8StringEncoding], nil);
+        return [NSProgress discreteProgressWithTotalUnitCount:100];
+    }];
+
+    auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [dataInteractionSimulator setExternalItemProviders:@[ simulatedItemProvider.get() ]];
+    [dataInteractionSimulator runFrom:CGPointMake(300, 400) to:CGPointMake(100, 300)];
+
+    EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"editor.textContent"].UTF8String);
+}
+
 TEST(DataInteractionTests, AttachmentElementItemProviders)
 {
     RetainPtr<WKWebViewConfiguration> configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"];

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp (218013 => 218014)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2017-06-09 19:47:07 UTC (rev 218013)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2017-06-09 20:10:59 UTC (rev 218014)
@@ -372,7 +372,8 @@
         didChangeSelection,
         0, /* willWriteToPasteboard */
         0, /* getPasteboardDataForRange */
-        0  /* didWriteToPasteboard */
+        0, /* didWriteToPasteboard */
+        0, /* performTwoStepDrop */
     };
     WKBundlePageSetEditorClient(m_page, &editorClient.base);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to