Title: [221660] trunk
Revision
221660
Author
wenson_hs...@apple.com
Date
2017-09-05 19:41:52 -0700 (Tue, 05 Sep 2017)

Log Message

[iOS WK2] Add plumbing for WKContentView to ask the web process for additional drag items
https://bugs.webkit.org/show_bug.cgi?id=176348
Work towards <rdar://problem/31144674>

Reviewed by Tim Horton.

Source/WebKit:

Adds boilerplate plumbing to request additional items to an existing session. This implements some UI-side logic
in WKContentView to send an additional drag items request and handle a response from the web process.
To start, WebPageProxy::requestAdditionalItemsForDragSession is invoked by -_dragInteraction:
itemsForAddingToSession:withTouchAtPoint:completion: in WKContentView, and the response from the web process is
handled in -[WKContentView _didHandleAdditionalDragItemsRequest:].

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _simulateItemsForAddingToSession:atLocation:completion:]):
* UIProcess/API/Cocoa/WKWebViewPrivate.h:

Add SPI to simulate a request for additional drag items. See Tools/ChangeLog for more detail.

* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:

Add an IPC message handler for the additional drag items response from the web process.

* UIProcess/ios/DragDropInteractionState.h:
(WebKit::DragDropInteractionState::BlockPtr<void):
* UIProcess/ios/DragDropInteractionState.mm:
(WebKit::DragDropInteractionState::shouldRequestAdditionalItemForDragSession const):
(WebKit::DragDropInteractionState::dragSessionWillRequestAdditionalItem):

Invoke the new additional items completion handler when tearing down to avoid getting UIKit into a bad state.

(WebKit::DragDropInteractionState::dragAndDropSessionsDidEnd):
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::didHandleAdditionalDragItemsRequest):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _didHandleAdditionalDragItemsRequest:]):
(-[WKContentView _itemsForBeginningOrAddingToSessionWithRegistrationList:stagedDragSource:]):

Factors common logic to convert a staged WebItemProviderRegistrationInfoList and DragSourceState into a list of
drag items, invoking the private UI delegate in the process. This is called both when starting a drag session,
and adding items to an existing drag session.

(-[WKContentView _dragInteraction:itemsForAddingToSession:withTouchAtPoint:completion:]):

Implements a (proposed) additional drag item delegate that serves as an asynchronous alternative to the API
variant, -_dragInteraction:itemsForAddingToSession:withTouchAtPoint:. See <rdar://problem/33146803> for more
information.

(-[WKContentView dragInteraction:itemsForBeginningSession:]):

Refactored to use -_itemsForBeginningOrAddingToSessionWithRegistrationList:stagedDragSource:.

(-[WKContentView _simulateItemsForAddingToSession:atLocation:completion:]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::didHandleAdditionalDragItemsRequest):
(WebKit::WebPageProxy::requestAdditionalItemsForDragSession):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Add an IPC message handler for the additional drag items request from the UI process.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestAdditionalItemsForDragSession):

Tools:

Introduces new test infrastructure to simulate tapping to add additional items to the current drag session. We
add -[DataInteractionSimulator runFrom:to:additionalItemRequestLocations:], for which the last argument is a
dictionary mapping progress (a double between 0 and 1) to NSValues representing the location from which the drag
and drop simulation will request an additional drag item. During the simulated drag and drop, when the progress
value exceeds a value in the map of remaining additional item request locations, we halt drag simulation
progress for that runloop and instead request additional items from the location specified.

The only (useful) passing test we can create using the new machinery is one that verifies that preventDefault()
on dragstart works as expected, preventing additional items from being added. While this trivially passes now,
since the web-process-side of the additional items flow is not yet implemented, it should continue to pass after
the web process portion is implemented.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/selected-text-image-link-and-editable.html: Added.

Add a new test page that contains some non-editable text, an image, a link, and a rich text editable area.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[MockDragDropSession addItems:]):

Convenience method to add additional mock drag items to a drag or drop session.

(-[DataInteractionSimulator _resetSimulatedState]):
(-[DataInteractionSimulator runFrom:to:]):

Converted into a convenience wrapper around the latter version, passing in nil for the additional item request
locations dictionary.

(-[DataInteractionSimulator runFrom:to:additionalItemRequestLocations:]):
(-[DataInteractionSimulator _enqueuePendingAdditionalItemRequestLocations]):
(-[DataInteractionSimulator _sendQueuedAdditionalItemRequest]):

New helper methods to detect when and where additional items should be "added", and subsequently simulate adding
drag items at these given locations.

(-[DataInteractionSimulator _advanceProgress]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (221659 => 221660)


--- trunk/Source/WebKit/ChangeLog	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/ChangeLog	2017-09-06 02:41:52 UTC (rev 221660)
@@ -1,3 +1,72 @@
+2017-09-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS WK2] Add plumbing for WKContentView to ask the web process for additional drag items
+        https://bugs.webkit.org/show_bug.cgi?id=176348
+        Work towards <rdar://problem/31144674>
+
+        Reviewed by Tim Horton.
+
+        Adds boilerplate plumbing to request additional items to an existing session. This implements some UI-side logic
+        in WKContentView to send an additional drag items request and handle a response from the web process. 
+        To start, WebPageProxy::requestAdditionalItemsForDragSession is invoked by -_dragInteraction:
+        itemsForAddingToSession:withTouchAtPoint:completion: in WKContentView, and the response from the web process is
+        handled in -[WKContentView _didHandleAdditionalDragItemsRequest:].
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _simulateItemsForAddingToSession:atLocation:completion:]):
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
+        Add SPI to simulate a request for additional drag items. See Tools/ChangeLog for more detail.
+
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+
+        Add an IPC message handler for the additional drag items response from the web process.
+
+        * UIProcess/ios/DragDropInteractionState.h:
+        (WebKit::DragDropInteractionState::BlockPtr<void):
+        * UIProcess/ios/DragDropInteractionState.mm:
+        (WebKit::DragDropInteractionState::shouldRequestAdditionalItemForDragSession const):
+        (WebKit::DragDropInteractionState::dragSessionWillRequestAdditionalItem):
+
+        Invoke the new additional items completion handler when tearing down to avoid getting UIKit into a bad state.
+
+        (WebKit::DragDropInteractionState::dragAndDropSessionsDidEnd):
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::didHandleAdditionalDragItemsRequest):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _didHandleAdditionalDragItemsRequest:]):
+        (-[WKContentView _itemsForBeginningOrAddingToSessionWithRegistrationList:stagedDragSource:]):
+
+        Factors common logic to convert a staged WebItemProviderRegistrationInfoList and DragSourceState into a list of
+        drag items, invoking the private UI delegate in the process. This is called both when starting a drag session,
+        and adding items to an existing drag session.
+
+        (-[WKContentView _dragInteraction:itemsForAddingToSession:withTouchAtPoint:completion:]):
+
+        Implements a (proposed) additional drag item delegate that serves as an asynchronous alternative to the API
+        variant, -_dragInteraction:itemsForAddingToSession:withTouchAtPoint:. See <rdar://problem/33146803> for more
+        information.
+
+        (-[WKContentView dragInteraction:itemsForBeginningSession:]):
+
+        Refactored to use -_itemsForBeginningOrAddingToSessionWithRegistrationList:stagedDragSource:.
+
+        (-[WKContentView _simulateItemsForAddingToSession:atLocation:completion:]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::didHandleAdditionalDragItemsRequest):
+        (WebKit::WebPageProxy::requestAdditionalItemsForDragSession):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        Add an IPC message handler for the additional drag items request from the UI process.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::requestAdditionalItemsForDragSession):
+
 2017-09-05  Alex Christensen  <achristen...@webkit.org>
 
         Add WKUIDelegatePrivate equivalent of WKPageUIClient's mouseDidMoveOverElement

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -5831,6 +5831,13 @@
 #endif
 }
 
+- (void)_simulateItemsForAddingToSession:(id)session atLocation:(CGPoint)location completion:(void(^)(NSArray *))completion
+{
+#if ENABLE(DATA_INTERACTION)
+    [_contentView _simulateItemsForAddingToSession:session atLocation:location completion:completion];
+#endif
+}
+
 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion
 {
 #if ENABLE(DATA_INTERACTION)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -373,6 +373,7 @@
 - (void)_simulateDataInteractionSessionDidEnd:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (void)_simulateWillBeginDataInteractionWithSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (NSArray *)_simulatedItemsForSession:(id)session WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (void)_simulateItemsForAddingToSession:(id)session atLocation:(CGPoint)location completion:(void(^)(NSArray *))completion WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (void)_simulateLongPressActionAtLocation:(CGPoint)location;
 

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -381,6 +381,7 @@
 #if ENABLE(DATA_INTERACTION)
     virtual void didPerformDataInteractionControllerOperation(bool handled) = 0;
     virtual void didHandleStartDataInteractionRequest(bool started) = 0;
+    virtual void didHandleAdditionalDragItemsRequest(bool added) = 0;
     virtual void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle& image) = 0;
     virtual void didConcludeEditDataInteraction(std::optional<WebCore::TextIndicatorData>) = 0;
     virtual void didChangeDataInteractionCaretRect(const WebCore::IntRect& previousCaretRect, const WebCore::IntRect& caretRect) = 0;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -561,7 +561,9 @@
 #if ENABLE(DATA_INTERACTION)
     void didPerformDataInteractionControllerOperation(bool handled);
     void didHandleStartDataInteractionRequest(bool started);
+    void didHandleAdditionalDragItemsRequest(bool added);
     void requestStartDataInteraction(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
+    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
     void didConcludeEditDataInteraction(std::optional<WebCore::TextIndicatorData>);
 #endif
 #endif

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2017-09-06 02:41:52 UTC (rev 221660)
@@ -317,6 +317,7 @@
 #if ENABLE(DATA_INTERACTION)
     DidPerformDataInteractionControllerOperation(bool handled)
     DidHandleStartDataInteractionRequest(bool started)
+    DidHandleAdditionalDragItemsRequest(bool added)
     DidConcludeEditDataInteraction(std::optional<WebCore::TextIndicatorData> textIndicator)
 #endif
 

Modified: trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -70,6 +70,8 @@
     void clearStagedDragSource(DidBecomeActive = DidBecomeActive::No);
     UITargetedDragPreview *previewForDragItem(UIDragItem *, UIView *contentView, UIView *previewContainer) const;
     void dragSessionWillDelaySetDownAnimation(dispatch_block_t completion);
+    bool shouldRequestAdditionalItemForDragSession(id <UIDragSession>) const;
+    void dragSessionWillRequestAdditionalItem(void (^completion)(NSArray <UIDragItem *> *));
 
     // These helper methods are unique to UIDropInteraction.
     void dropSessionDidEnterOrUpdate(id <UIDropSession>, const WebCore::DragData&);
@@ -86,6 +88,7 @@
     id<UIDropSession> dropSession() const { return m_dropSession.get(); }
     BlockPtr<void()> takeDragStartCompletionBlock() { return WTFMove(m_dragStartCompletionBlock); }
     BlockPtr<void()> takeDragCancelSetDownBlock() { return WTFMove(m_dragCancelSetDownBlock); }
+    BlockPtr<void(NSArray<UIDragItem *> *)> takeAddDragItemCompletionBlock() { return WTFMove(m_addDragItemCompletionBlock); }
 
 private:
     void updatePreviewsForActiveDragSources();
@@ -99,6 +102,7 @@
     RetainPtr<id <UIDropSession>> m_dropSession;
     BlockPtr<void()> m_dragStartCompletionBlock;
     BlockPtr<void()> m_dragCancelSetDownBlock;
+    BlockPtr<void(NSArray<UIDragItem *> *)> m_addDragItemCompletionBlock;
 
     std::optional<DragSourceState> m_stagedDragSource;
     Vector<DragSourceState> m_activeDragSources;

Modified: trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/DragDropInteractionState.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -167,6 +167,17 @@
     m_dragCancelSetDownBlock = completion;
 }
 
+bool DragDropInteractionState::shouldRequestAdditionalItemForDragSession(id <UIDragSession> session) const
+{
+    return m_dragSession == session && !m_addDragItemCompletionBlock && !m_dragStartCompletionBlock;
+}
+
+void DragDropInteractionState::dragSessionWillRequestAdditionalItem(void (^completion)(NSArray <UIDragItem *> *))
+{
+    clearStagedDragSource();
+    m_addDragItemCompletionBlock = completion;
+}
+
 void DragDropInteractionState::dropSessionDidEnterOrUpdate(id <UIDropSession> session, const DragData& dragData)
 {
     m_dropSession = session;
@@ -210,6 +221,9 @@
     if (auto completionBlock = takeDragCancelSetDownBlock())
         completionBlock();
 
+    if (auto completionBlock = takeAddDragItemCompletionBlock())
+        completionBlock(@[ ]);
+
     if (auto completionBlock = takeDragStartCompletionBlock())
         completionBlock();
 }

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -205,6 +205,7 @@
 #if ENABLE(DATA_INTERACTION)
     void didPerformDataInteractionControllerOperation(bool handled) override;
     void didHandleStartDataInteractionRequest(bool started) override;
+    void didHandleAdditionalDragItemsRequest(bool added) override;
     void startDrag(const WebCore::DragItem&, const ShareableBitmap::Handle& image) override;
     void didConcludeEditDataInteraction(std::optional<WebCore::TextIndicatorData>) override;
     void didChangeDataInteractionCaretRect(const WebCore::IntRect& previousCaretRect, const WebCore::IntRect& caretRect) override;

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -786,6 +786,11 @@
     [m_contentView _didHandleStartDataInteractionRequest:started];
 }
 
+void PageClientImpl::didHandleAdditionalDragItemsRequest(bool added)
+{
+    [m_contentView _didHandleAdditionalDragItemsRequest:added];
+}
+
 void PageClientImpl::startDrag(const DragItem& item, const ShareableBitmap::Handle& image)
 {
     [m_contentView _startDrag:ShareableBitmap::create(image)->makeCGImageCopy() item:item];

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -321,6 +321,7 @@
 - (void)_didChangeDragInteractionPolicy;
 - (void)_didPerformDataInteractionControllerOperation:(BOOL)handled;
 - (void)_didHandleStartDataInteractionRequest:(BOOL)started;
+- (void)_didHandleAdditionalDragItemsRequest:(BOOL)added;
 - (void)_startDrag:(RetainPtr<CGImageRef>)image item:(const WebCore::DragItem&)item;
 - (void)_didConcludeEditDataInteraction:(std::optional<WebCore::TextIndicatorData>)data;
 - (void)_didChangeDataInteractionCaretRect:(CGRect)previousRect currentRect:(CGRect)rect;
@@ -333,6 +334,7 @@
 - (void)_simulateWillBeginDataInteractionWithSession:(id)session;
 - (NSArray *)_simulatedItemsForSession:(id)session;
 - (void)_simulatePrepareForDataInteractionSession:(id)session completion:(dispatch_block_t)completion;
+- (void)_simulateItemsForAddingToSession:(id)session atLocation:(CGPoint)location completion:(void(^)(NSArray *))completion;
 #endif
 
 - (void)_simulateLongPressActionAtLocation:(CGPoint)location;

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -4259,6 +4259,31 @@
     _dragDropInteractionState.stageDragItem(item, dragImage.get());
 }
 
+- (void)_didHandleAdditionalDragItemsRequest:(BOOL)added
+{
+    auto completion = _dragDropInteractionState.takeAddDragItemCompletionBlock();
+    if (!completion)
+        return;
+
+    WebItemProviderRegistrationInfoList *registrationList = [[WebItemProviderPasteboard sharedInstance] takeRegistrationList];
+    if (!added || !registrationList || !_dragDropInteractionState.hasStagedDragSource()) {
+        _dragDropInteractionState.clearStagedDragSource();
+        completion(@[ ]);
+        return;
+    }
+
+    auto stagedDragSource = _dragDropInteractionState.stagedDragSource();
+    NSArray *dragItemsToAdd = [self _itemsForBeginningOrAddingToSessionWithRegistrationList:registrationList stagedDragSource:stagedDragSource];
+
+    RELEASE_LOG(DragAndDrop, "Drag session: %p adding %tu items", _dragDropInteractionState.dragSession(), dragItemsToAdd.count);
+    _dragDropInteractionState.clearStagedDragSource(dragItemsToAdd.count ? DragDropInteractionState::DidBecomeActive::Yes : DragDropInteractionState::DidBecomeActive::No);
+
+    completion(dragItemsToAdd);
+
+    if (dragItemsToAdd.count)
+        _page->didStartDrag();
+}
+
 - (void)_didHandleStartDataInteractionRequest:(BOOL)started
 {
     BlockPtr<void()> savedCompletionBlock = _dragDropInteractionState.takeDragStartCompletionBlock();
@@ -4454,6 +4479,37 @@
     _shouldRestoreCalloutBarAfterDrop = NO;
 }
 
+- (NSArray<UIDragItem *> *)_itemsForBeginningOrAddingToSessionWithRegistrationList:(WebItemProviderRegistrationInfoList *)registrationList stagedDragSource:(const DragSourceState&)stagedDragSource
+{
+    UIItemProvider *defaultItemProvider = registrationList.itemProvider;
+    if (!defaultItemProvider)
+        return @[ ];
+
+    NSArray *adjustedItemProviders;
+    id <WKUIDelegatePrivate> uiDelegate = self.webViewUIDelegate;
+    if ([uiDelegate respondsToSelector:@selector(_webView:adjustedDataInteractionItemProvidersForItemProvider:representingObjects:additionalData:)]) {
+        auto representingObjects = adoptNS([[NSMutableArray alloc] init]);
+        auto additionalData = adoptNS([[NSMutableDictionary alloc] init]);
+        [registrationList enumerateItems:[representingObjects, additionalData] (WebItemProviderRegistrationInfo *item, NSUInteger) {
+            if (item.representingObject)
+                [representingObjects addObject:item.representingObject];
+            if (item.typeIdentifier && item.data)
+                [additionalData setObject:item.data forKey:item.typeIdentifier];
+        }];
+        adjustedItemProviders = [uiDelegate _webView:_webView adjustedDataInteractionItemProvidersForItemProvider:defaultItemProvider representingObjects:representingObjects.get() additionalData:additionalData.get()];
+    } else
+        adjustedItemProviders = @[ defaultItemProvider ];
+
+    NSMutableArray *dragItems = [NSMutableArray arrayWithCapacity:adjustedItemProviders.count];
+    for (UIItemProvider *itemProvider in adjustedItemProviders) {
+        auto item = adoptNS([[UIDragItem alloc] initWithItemProvider:itemProvider]);
+        [item _setPrivateLocalContext:@(stagedDragSource.itemIdentifier)];
+        [dragItems addObject:item.autorelease()];
+    }
+
+    return dragItems;
+}
+
 #pragma mark - UIDragInteractionDelegate
 
 - (BOOL)_dragInteraction:(UIDragInteraction *)interaction shouldDelayCompetingGestureRecognizer:(UIGestureRecognizer *)competingGestureRecognizer
@@ -4477,6 +4533,17 @@
     return dataOwner;
 }
 
+- (void)_dragInteraction:(UIDragInteraction *)interaction itemsForAddingToSession:(id <UIDragSession>)session withTouchAtPoint:(CGPoint)point completion:(void(^)(NSArray<UIDragItem *> *))completion
+{
+    if (!_dragDropInteractionState.shouldRequestAdditionalItemForDragSession(session)) {
+        completion(@[ ]);
+        return;
+    }
+
+    _dragDropInteractionState.dragSessionWillRequestAdditionalItem(completion);
+    _page->requestAdditionalItemsForDragSession(roundedIntPoint(point), roundedIntPoint(point));
+}
+
 - (void)_dragInteraction:(UIDragInteraction *)interaction prepareForSession:(id <UIDragSession>)session completion:(dispatch_block_t)completion
 {
     [self _cancelLongPressGestureRecognizer];
@@ -4515,37 +4582,7 @@
 
     auto stagedDragSource = _dragDropInteractionState.stagedDragSource();
     WebItemProviderRegistrationInfoList *registrationList = [[WebItemProviderPasteboard sharedInstance] takeRegistrationList];
-    UIItemProvider *defaultItemProvider = registrationList.itemProvider;
-    if (!defaultItemProvider) {
-        RELEASE_LOG(DragAndDrop, "Drag session failed: %p (no item providers generated before adjustment)", session);
-        _page->dragCancelled();
-        _dragDropInteractionState.clearStagedDragSource();
-        return @[ ];
-    }
-
-    // Give internal clients such as Mail one final chance to augment the contents of each UIItemProvider before sending the drag items off to UIKit.
-    NSArray *adjustedItemProviders;
-    id <WKUIDelegatePrivate> uiDelegate = self.webViewUIDelegate;
-    if ([uiDelegate respondsToSelector:@selector(_webView:adjustedDataInteractionItemProvidersForItemProvider:representingObjects:additionalData:)]) {
-        auto representingObjects = adoptNS([[NSMutableArray alloc] init]);
-        auto additionalData = adoptNS([[NSMutableDictionary alloc] init]);
-        [registrationList enumerateItems:[representingObjects, additionalData] (WebItemProviderRegistrationInfo *item, NSUInteger) {
-            if (item.representingObject)
-                [representingObjects addObject:item.representingObject];
-            if (item.typeIdentifier && item.data)
-                [additionalData setObject:item.data forKey:item.typeIdentifier];
-        }];
-        adjustedItemProviders = [uiDelegate _webView:_webView adjustedDataInteractionItemProvidersForItemProvider:defaultItemProvider representingObjects:representingObjects.get() additionalData:additionalData.get()];
-    } else
-        adjustedItemProviders = @[ defaultItemProvider ];
-
-    NSMutableArray *dragItems = [NSMutableArray arrayWithCapacity:adjustedItemProviders.count];
-    for (UIItemProvider *itemProvider in adjustedItemProviders) {
-        auto item = adoptNS([[UIDragItem alloc] initWithItemProvider:itemProvider]);
-        [item _setPrivateLocalContext:@(stagedDragSource.itemIdentifier)];
-        [dragItems addObject:item.autorelease()];
-    }
-
+    NSArray *dragItems = [self _itemsForBeginningOrAddingToSessionWithRegistrationList:registrationList stagedDragSource:stagedDragSource];
     if (![dragItems count])
         _page->dragCancelled();
 
@@ -4828,6 +4865,11 @@
     [self _dragInteraction:_dragInteraction.get() prepareForSession:session completion:completion];
 }
 
+- (void)_simulateItemsForAddingToSession:(id)session atLocation:(CGPoint)location completion:(void(^)(NSArray *))completion
+{
+    [self _dragInteraction:_dragInteraction.get() itemsForAddingToSession:session withTouchAtPoint:location completion:completion];
+}
+
 #endif
 
 - (void)_simulateLongPressActionAtLocation:(CGPoint)location

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (221659 => 221660)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -1094,6 +1094,11 @@
     m_pageClient.didHandleStartDataInteractionRequest(started);
 }
 
+void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
+{
+    m_pageClient.didHandleAdditionalDragItemsRequest(added);
+}
+
 void WebPageProxy::requestStartDataInteraction(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition)
 {
     if (isValid())
@@ -1100,6 +1105,12 @@
         m_process->send(Messages::WebPage::RequestStartDataInteraction(clientPosition, globalPosition), m_pageID);
 }
 
+void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
+{
+    if (isValid())
+        m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition), m_pageID);
+}
+
 void WebPageProxy::didConcludeEditDataInteraction(std::optional<TextIndicatorData> data)
 {
     m_pageClient.didConcludeEditDataInteraction(data);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (221659 => 221660)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -1032,6 +1032,7 @@
     RefPtr<WebCore::Range> switchToBlockSelectionAtPoint(const WebCore::IntPoint&, SelectionHandlePosition);
 #if ENABLE(DATA_INTERACTION)
     void requestStartDataInteraction(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
+    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
 #endif
 #endif
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (221659 => 221660)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2017-09-06 02:41:52 UTC (rev 221660)
@@ -253,6 +253,7 @@
 
 #if ENABLE(DATA_INTERACTION)
     RequestStartDataInteraction(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition)
+    RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition)
 #endif
 
     # Popup menu.

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (221659 => 221660)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -631,6 +631,13 @@
     send(Messages::WebPageProxy::DidHandleStartDataInteractionRequest(didStart));
 }
 
+void WebPage::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
+{
+    notImplemented();
+
+    send(Messages::WebPageProxy::DidHandleAdditionalDragItemsRequest(false));
+}
+
 void WebPage::didConcludeEditDataInteraction()
 {
     std::optional<TextIndicatorData> textIndicatorData;

Modified: trunk/Tools/ChangeLog (221659 => 221660)


--- trunk/Tools/ChangeLog	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Tools/ChangeLog	2017-09-06 02:41:52 UTC (rev 221660)
@@ -1,3 +1,51 @@
+2017-09-05  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS WK2] Add plumbing for WKContentView to ask the web process for additional drag items
+        https://bugs.webkit.org/show_bug.cgi?id=176348
+        Work towards <rdar://problem/31144674>
+
+        Reviewed by Tim Horton.
+
+        Introduces new test infrastructure to simulate tapping to add additional items to the current drag session. We
+        add -[DataInteractionSimulator runFrom:to:additionalItemRequestLocations:], for which the last argument is a
+        dictionary mapping progress (a double between 0 and 1) to NSValues representing the location from which the drag
+        and drop simulation will request an additional drag item. During the simulated drag and drop, when the progress
+        value exceeds a value in the map of remaining additional item request locations, we halt drag simulation
+        progress for that runloop and instead request additional items from the location specified.
+
+        The only (useful) passing test we can create using the new machinery is one that verifies that preventDefault()
+        on dragstart works as expected, preventing additional items from being added. While this trivially passes now,
+        since the web-process-side of the additional items flow is not yet implemented, it should continue to pass after
+        the web process portion is implemented.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/selected-text-image-link-and-editable.html: Added.
+
+        Add a new test page that contains some non-editable text, an image, a link, and a rich text editable area.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/DataInteractionSimulator.mm:
+        (-[MockDragDropSession addItems:]):
+
+        Convenience method to add additional mock drag items to a drag or drop session.
+
+        (-[DataInteractionSimulator _resetSimulatedState]):
+        (-[DataInteractionSimulator runFrom:to:]):
+
+        Converted into a convenience wrapper around the latter version, passing in nil for the additional item request
+        locations dictionary.
+
+        (-[DataInteractionSimulator runFrom:to:additionalItemRequestLocations:]):
+        (-[DataInteractionSimulator _enqueuePendingAdditionalItemRequestLocations]):
+        (-[DataInteractionSimulator _sendQueuedAdditionalItemRequest]):
+
+        New helper methods to detect when and where additional items should be "added", and subsequently simulate adding
+        drag items at these given locations.
+
+        (-[DataInteractionSimulator _advanceProgress]):
+
 2017-09-05  Alex Christensen  <achristen...@webkit.org>
 
         Add WKUIDelegatePrivate equivalent of WKPageUIClient's mouseDidMoveOverElement

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (221659 => 221660)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-06 02:41:52 UTC (rev 221660)
@@ -694,6 +694,7 @@
 		F4D4F3B61E4E2BCB00BB2767 /* DataInteractionSimulator.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D4F3B41E4E2BCB00BB2767 /* DataInteractionSimulator.mm */; };
 		F4D4F3B91E4E36E400BB2767 /* DataInteractionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4D4F3B71E4E36E400BB2767 /* DataInteractionTests.mm */; };
 		F4D5E4E81F0C5D38008C1A49 /* dragstart-clear-selection.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4D5E4E71F0C5D27008C1A49 /* dragstart-clear-selection.html */; };
+		F4D65DA81F5E4704009D8C27 /* selected-text-image-link-and-editable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4D65DA71F5E46C0009D8C27 /* selected-text-image-link-and-editable.html */; };
 		F4DEF6ED1E9B4DB60048EF61 /* image-in-link-and-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4DEF6EC1E9B4D950048EF61 /* image-in-link-and-input.html */; };
 		F4F137921D9B683E002BEC57 /* large-video-test-now-playing.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */; };
 		F4F405BC1D4C0D1C007A9707 /* full-size-autoplaying-video-with-audio.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */; };
@@ -953,6 +954,7 @@
 				F6FDDDD614241C6F004F1729 /* push-state.html in Copy Resources */,
 				A12DDC001E8373E700CF6CAE /* rendered-image-excluding-overflow.html in Copy Resources */,
 				F46849C01EEF5EF300B937FE /* rich-and-plain-text.html in Copy Resources */,
+				F4D65DA81F5E4704009D8C27 /* selected-text-image-link-and-editable.html in Copy Resources */,
 				7A66BDB81EAF18D500CCC924 /* set-long-title.html in Copy Resources */,
 				52B8CF9815868D9100281053 /* SetDocumentURI.html in Copy Resources */,
 				CEBABD491B71687C0051210A /* should-open-external-schemes.html in Copy Resources */,
@@ -1724,6 +1726,7 @@
 		F4D4F3B51E4E2BCB00BB2767 /* DataInteractionSimulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataInteractionSimulator.h; sourceTree = "<group>"; };
 		F4D4F3B71E4E36E400BB2767 /* DataInteractionTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DataInteractionTests.mm; sourceTree = "<group>"; };
 		F4D5E4E71F0C5D27008C1A49 /* dragstart-clear-selection.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "dragstart-clear-selection.html"; sourceTree = "<group>"; };
+		F4D65DA71F5E46C0009D8C27 /* selected-text-image-link-and-editable.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "selected-text-image-link-and-editable.html"; sourceTree = "<group>"; };
 		F4DEF6EC1E9B4D950048EF61 /* image-in-link-and-input.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "image-in-link-and-input.html"; sourceTree = "<group>"; };
 		F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "large-video-test-now-playing.html"; sourceTree = "<group>"; };
 		F4F405BA1D4C0CF8007A9707 /* full-size-autoplaying-video-with-audio.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "full-size-autoplaying-video-with-audio.html"; sourceTree = "<group>"; };
@@ -2234,6 +2237,7 @@
 				F41AB99A1EF4692C0083FA08 /* prevent-start.html */,
 				A12DDBFF1E8373C100CF6CAE /* rendered-image-excluding-overflow.html */,
 				F46849BF1EEF5EDC00B937FE /* rich-and-plain-text.html */,
+				F4D65DA71F5E46C0009D8C27 /* selected-text-image-link-and-editable.html */,
 				C9B4AD291ECA6EA500F5FEA0 /* silence-long.m4a */,
 				F4F405BB1D4C0CF8007A9707 /* skinny-autoplaying-video-with-audio.html */,
 				515BE16E1D4288FF00DD7C68 /* StoreBlobToBeDeleted.html */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/selected-text-image-link-and-editable.html (0 => 221660)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/selected-text-image-link-and-editable.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/selected-text-image-link-and-editable.html	2017-09-06 02:41:52 UTC (rev 221660)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<style>
+html, body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+}
+
+#text, #image, #link {
+    height: 100px;
+    font-size: 80px;
+    white-space: nowrap;
+}
+
+#editor {
+    border: black 1px solid;
+    height: calc(100% - 300px);
+}
+</style>
+</head>
+
+<body>
+<div id="text">ABCD</div>
+<div><img id="image" src=""
+<div><a id="link" href="" link</a></div>
+<div contenteditable id="editor"></div>
+<script>
+getSelection().setBaseAndExtent(text, 0, text, 1);
+</script>
+</body>
+</html>

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (221659 => 221660)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -1234,6 +1234,21 @@
     EXPECT_WK_STREQ("FAR OFFSCREEN", [webView stringByEvaluatingJavaScript:@"getSelection().getRangeAt(0).toString()"]);
 }
 
+TEST(DataInteractionTests, AdditionalItemsCanBePreventedOnDragStart)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@"selected-text-image-link-and-editable"];
+    [webView stringByEvaluatingJavaScript:@"link.addEventListener('dragstart', e => e.preventDefault())"];
+    [webView stringByEvaluatingJavaScript:@"image.addEventListener('dragstart', e => e.preventDefault())"];
+
+    auto simulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [simulator runFrom:CGPointMake(50, 50) to:CGPointMake(50, 400) additionalItemRequestLocations:@{
+        @0.33: [NSValue valueWithCGPoint:CGPointMake(50, 150)],
+        @0.66: [NSValue valueWithCGPoint:CGPointMake(50, 250)]
+    }];
+    EXPECT_WK_STREQ("ABCD", [webView stringByEvaluatingJavaScript:@"editor.textContent"]);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(DATA_INTERACTION)

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h (221659 => 221660)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-09-06 02:41:52 UTC (rev 221660)
@@ -86,6 +86,8 @@
 extern NSString * const DataInteractionLeaveEventName;
 extern NSString * const DataInteractionStartEventName;
 
+typedef NSDictionary<NSNumber *, NSValue *> *ProgressToCGPointValueMap;
+
 typedef NS_ENUM(NSInteger, DataInteractionPhase) {
     DataInteractionCancelled = 0,
     DataInteractionBeginning = 1,
@@ -107,6 +109,9 @@
     CGPoint _endLocation;
     CGRect _lastKnownDragCaretRect;
 
+    RetainPtr<NSMutableDictionary<NSNumber *, NSValue *>>_remainingAdditionalItemRequestLocationsByProgress;
+    RetainPtr<NSMutableArray<NSValue *>>_queuedAdditionalItemRequestLocations;
+
     bool _isDoneWaitingForInputSession;
     BOOL _shouldPerformOperation;
     double _currentProgress;
@@ -115,7 +120,9 @@
 }
 
 - (instancetype)initWithWebView:(TestWKWebView *)webView;
+// The start location, end location, and locations of additional item requests are all in window coordinates.
 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation;
+- (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation additionalItemRequestLocations:(ProgressToCGPointValueMap)additionalItemRequestLocations;
 - (void)waitForInputSession;
 
 @property (nonatomic) BOOL allowsFocusToStartInputSession;

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm (221659 => 221660)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-09-06 02:37:41 UTC (rev 221659)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-09-06 02:41:52 UTC (rev 221660)
@@ -133,6 +133,17 @@
     _mockItems = items;
 }
 
+- (void)addItems:(NSArray<UIDragItem *> *)items
+{
+    if (![items count])
+        return;
+
+    if (![_mockItems count])
+        _mockItems = items;
+    else
+        _mockItems = [_mockItems arrayByAddingObjectsFromArray:items];
+}
+
 - (CGPoint)locationInView:(UIView *)view
 {
     return [_window convertPoint:_mockLocationInWindow toView:view];
@@ -307,6 +318,8 @@
     _dataOperationSession = nil;
     _shouldPerformOperation = NO;
     _lastKnownDragCaretRect = CGRectZero;
+    _remainingAdditionalItemRequestLocationsByProgress = nil;
+    _queuedAdditionalItemRequestLocations = adoptNS([[NSMutableArray alloc] init]);
 }
 
 - (NSArray *)observedEventNames
@@ -326,6 +339,11 @@
 
 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation
 {
+    [self runFrom:startLocation to:endLocation additionalItemRequestLocations:nil];
+}
+
+- (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation additionalItemRequestLocations:(ProgressToCGPointValueMap)additionalItemRequestLocations
+{
     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
     [defaultCenter addObserver:self selector:@selector(simulateAllTouchesCanceled:) name:TestWebKitAPISimulateCancelAllTouchesNotificationName object:nil];
 
@@ -334,6 +352,9 @@
 
     [self _resetSimulatedState];
 
+    if (additionalItemRequestLocations)
+        _remainingAdditionalItemRequestLocationsByProgress = adoptNS([additionalItemRequestLocations mutableCopy]);
+
     RetainPtr<DataInteractionSimulator> strongSelf = self;
     for (NSString *eventName in dataInteractionEventNames()) {
         DataInteractionSimulator *weakSelf = strongSelf.get();
@@ -391,8 +412,45 @@
         [_webView _simulateDataInteractionSessionDidEnd:_dataInteractionSession.get()];
 }
 
+- (void)_enqueuePendingAdditionalItemRequestLocations
+{
+    NSMutableArray *progressValuesToRemove = [NSMutableArray array];
+    for (NSNumber *progressValue in _remainingAdditionalItemRequestLocationsByProgress.get()) {
+        double progress = progressValue.doubleValue;
+        if (progress > _currentProgress)
+            continue;
+        [progressValuesToRemove addObject:progressValue];
+        [_queuedAdditionalItemRequestLocations addObject:[_remainingAdditionalItemRequestLocationsByProgress objectForKey:progressValue]];
+    }
+
+    for (NSNumber *progressToRemove in progressValuesToRemove)
+        [_remainingAdditionalItemRequestLocationsByProgress removeObjectForKey:progressToRemove];
+}
+
+- (BOOL)_sendQueuedAdditionalItemRequest
+{
+    if (![_queuedAdditionalItemRequestLocations count])
+        return NO;
+
+    RetainPtr<NSValue> requestLocationValue = [_queuedAdditionalItemRequestLocations objectAtIndex:0];
+    [_queuedAdditionalItemRequestLocations removeObjectAtIndex:0];
+
+    auto requestLocation = [[_webView window] convertPoint:[requestLocationValue CGPointValue] toView:_webView.get()];
+    [_webView _simulateItemsForAddingToSession:_dataInteractionSession.get() atLocation:requestLocation completion:[dragSession = _dataInteractionSession, dropSession = _dataOperationSession] (NSArray *items) {
+        [dragSession addItems:items];
+        [dropSession addItems:items];
+    }];
+    return YES;
+}
+
 - (void)_advanceProgress
 {
+    [self _enqueuePendingAdditionalItemRequestLocations];
+    if ([self _sendQueuedAdditionalItemRequest]) {
+        [self _scheduleAdvanceProgress];
+        return;
+    }
+
     _lastKnownDragCaretRect = [_webView _dragCaretRect];
     _currentProgress += progressIncrementStep;
     CGPoint locationInWindow = self._currentLocation;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to