[iOS] Do not allow starting selection drags when selection views are not visible
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Apr 2019 22:49:20 +0000 (22:49 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Apr 2019 22:49:20 +0000 (22:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196686
<rdar://problem/49399192>

Reviewed by Tim Horton.

Source/WebCore:

See WebKit ChangeLog for more details.

Tests:  DragAndDropTests.CanDragImageWhenNotFirstResponder
        DragAndDropTests.DoNotPerformSelectionDragWhenNotFirstResponder

* page/DragController.cpp:
(WebCore::DragController::draggableElement const):

Make this respect the case where m_dragSourceAction does not include DragSourceActionSelection. All the other
drag source types are currently consulted in this method, with the exception of DragSourceActionSelection.

Source/WebKit:

Currently, on iOS, it's possible to start dragging selected text in a web view even if the selection itself is
not visible. This can happen if the user selects some text, focuses a native text field, and then long presses
the previously selected text. This is because the text is still selected in the document since we don't clear
the selection when resigning first responder on iOS, despite the fact that the native selection view is no
longer present.

To fix this, we add plumbing to specify the set of allowed drag source actions when requesting drag start; this
set of allowed drag source actions only includes DragSourceActionSelection if the selection view can be visible
(i.e. the content view is first responder, and isn't suppressing text interactions). We then update WebPage's
allowed drag source actions with this given set of actions, while sending "dragstart" to the page.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView hasSelectablePositionAtPoint:]):
(-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):

Only bail out of text selection in text that is already selected if the web view allows dragging text selections
(i.e. the web view is first responder, and is not suppressing text interactions).

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

Pass the set of allowed drag source actions when requesting a drag start or adding items to an existing session.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::requestDragStart):
(WebKit::WebPageProxy::requestAdditionalItemsForDragSession):

Plumb the allowed drag source actions from the UI process (WKContentView) over to the web process (WebPage).

* WebProcess/WebCoreSupport/WebDragClient.cpp:
(WebKit::WebDragClient::dragSourceActionMaskForPoint):

Instead of always returning Any, consult WebPage's allowed drag source actions.

* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::allowedDragSourceActions const):
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestDragStart):
(WebKit::WebPage::requestAdditionalItemsForDragSession):

Set WebPage's allowed drag source actions to the given set of actions when sending a drag start to the page.

Tools:

Adjust some existing API tests to make the web view become first responder before trying to begin dragging, and
also add some new API tests to cover scenarios where the web view is not first responder.

* TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/DragAndDropSimulator.h:

Add a switch to optionally make the web view first responder when starting the simulated drag.

* TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:
(-[DragAndDropSimulator initWithWebView:]):
(-[DragAndDropSimulator runFrom:to:additionalItemRequestLocations:]):

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

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/DragController.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebCoreSupport/WebDragClient.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm
Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h
Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm

index 285c7bb..52ba667 100644 (file)
@@ -1,3 +1,22 @@
+2019-04-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Do not allow starting selection drags when selection views are not visible
+        https://bugs.webkit.org/show_bug.cgi?id=196686
+        <rdar://problem/49399192>
+
+        Reviewed by Tim Horton.
+
+        See WebKit ChangeLog for more details.
+
+        Tests:  DragAndDropTests.CanDragImageWhenNotFirstResponder
+                DragAndDropTests.DoNotPerformSelectionDragWhenNotFirstResponder
+
+        * page/DragController.cpp:
+        (WebCore::DragController::draggableElement const):
+
+        Make this respect the case where m_dragSourceAction does not include DragSourceActionSelection. All the other
+        drag source types are currently consulted in this method, with the exception of DragSourceActionSelection.
+
 2019-04-08  Youenn Fablet  <youenn@apple.com>
 
         Add a test to check for the service worker process name
index e9f833b..651cba4 100644 (file)
@@ -826,7 +826,10 @@ Element* DragController::draggableElement(const Frame* sourceFrame, Element* sta
     }
 
     // We either have nothing to drag or we have a selection and we're not over a draggable element.
-    return (state.type & DragSourceActionSelection) ? startElement : nullptr;
+    if (state.type & DragSourceActionSelection && m_dragSourceAction & DragSourceActionSelection)
+        return startElement;
+
+    return nullptr;
 }
 
 static CachedImage* getCachedImage(Element& element)
index f042d3d..43159f0 100644 (file)
@@ -1,3 +1,56 @@
+2019-04-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Do not allow starting selection drags when selection views are not visible
+        https://bugs.webkit.org/show_bug.cgi?id=196686
+        <rdar://problem/49399192>
+
+        Reviewed by Tim Horton.
+
+        Currently, on iOS, it's possible to start dragging selected text in a web view even if the selection itself is
+        not visible. This can happen if the user selects some text, focuses a native text field, and then long presses
+        the previously selected text. This is because the text is still selected in the document since we don't clear
+        the selection when resigning first responder on iOS, despite the fact that the native selection view is no
+        longer present.
+
+        To fix this, we add plumbing to specify the set of allowed drag source actions when requesting drag start; this
+        set of allowed drag source actions only includes DragSourceActionSelection if the selection view can be visible
+        (i.e. the content view is first responder, and isn't suppressing text interactions). We then update WebPage's
+        allowed drag source actions with this given set of actions, while sending "dragstart" to the page.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView hasSelectablePositionAtPoint:]):
+        (-[WKContentView textInteractionGesture:shouldBeginAtPoint:]):
+
+        Only bail out of text selection in text that is already selected if the web view allows dragging text selections
+        (i.e. the web view is first responder, and is not suppressing text interactions).
+
+        (-[WKContentView _allowedDragSourceActions]):
+        (-[WKContentView _dragInteraction:itemsForAddingToSession:withTouchAtPoint:completion:]):
+        (-[WKContentView _dragInteraction:prepareForSession:completion:]):
+
+        Pass the set of allowed drag source actions when requesting a drag start or adding items to an existing session.
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::requestDragStart):
+        (WebKit::WebPageProxy::requestAdditionalItemsForDragSession):
+
+        Plumb the allowed drag source actions from the UI process (WKContentView) over to the web process (WebPage).
+
+        * WebProcess/WebCoreSupport/WebDragClient.cpp:
+        (WebKit::WebDragClient::dragSourceActionMaskForPoint):
+
+        Instead of always returning Any, consult WebPage's allowed drag source actions.
+
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::allowedDragSourceActions const):
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::requestDragStart):
+        (WebKit::WebPage::requestAdditionalItemsForDragSession):
+
+        Set WebPage's allowed drag source actions to the given set of actions when sending a drag start to the page.
+
 2019-04-08  Justin Fan  <justin_fan@apple.com>
 
         [Web GPU] Fix Web GPU experimental feature on iOS
index a1c83ac..460a193 100644 (file)
@@ -716,8 +716,8 @@ public:
 #if ENABLE(DATA_INTERACTION)
     void didHandleDragStartRequest(bool started);
     void didHandleAdditionalDragItemsRequest(bool added);
-    void requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
-    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
+    void requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, WebCore::DragSourceAction allowedActions);
+    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, WebCore::DragSourceAction allowedActions);
     void didConcludeEditDrag(Optional<WebCore::TextIndicatorData>);
 #endif
 #endif
index a39638a..09e96ab 100644 (file)
@@ -2053,9 +2053,9 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (![self ensurePositionInformationIsUpToDate:request])
         return NO;
 
-#if ENABLE(DATA_INTERACTION)
-    if (_positionInformation.hasSelectionAtPosition) {
-        // If the position might initiate a data interaction, we don't want to consider the content at this position to be selectable.
+#if ENABLE(DRAG_SUPPORT)
+    if (_positionInformation.hasSelectionAtPosition && self._allowedDragSourceActions & WebCore::DragSourceActionSelection) {
+        // If the position might initiate a drag, we don't want to consider the content at this position to be selectable.
         // FIXME: This should be renamed to something more precise, such as textSelectionShouldRecognizeGestureAtPoint:
         return NO;
     }
@@ -2093,9 +2093,9 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (![self ensurePositionInformationIsUpToDate:request])
         return NO;
 
-#if ENABLE(DATA_INTERACTION)
-    if (_positionInformation.hasSelectionAtPosition && gesture == UIWKGestureLoupe) {
-        // If the position might initiate data interaction, we don't want to change the selection.
+#if ENABLE(DRAG_SUPPORT)
+    if (_positionInformation.hasSelectionAtPosition && gesture == UIWKGestureLoupe && self._allowedDragSourceActions & WebCore::DragSourceActionSelection) {
+        // If the position might initiate a drag, we don't want to change the selection.
         return NO;
     }
 #endif
@@ -6289,6 +6289,16 @@ static NSArray<NSItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     return WKDragDestinationActionAny & ~WKDragDestinationActionLoad;
 }
 
+- (WebCore::DragSourceAction)_allowedDragSourceActions
+{
+    auto allowedActions = WebCore::DragSourceActionAny;
+    if (!self.isFirstResponder || !_suppressSelectionAssistantReasons.isEmpty()) {
+        // Don't allow starting a drag on a selection when selection views are not visible.
+        allowedActions = static_cast<WebCore::DragSourceAction>(allowedActions & ~WebCore::DragSourceActionSelection);
+    }
+    return allowedActions;
+}
+
 - (id <UIDragDropSession>)currentDragOrDropSession
 {
     if (_dragDropInteractionState.dropSession())
@@ -6448,7 +6458,7 @@ static WebKit::DocumentEditingContextRequest toWebRequest(UIWKDocumentRequest *r
     }
 
     _dragDropInteractionState.dragSessionWillRequestAdditionalItem(completion);
-    _page->requestAdditionalItemsForDragSession(WebCore::roundedIntPoint(point), WebCore::roundedIntPoint(point));
+    _page->requestAdditionalItemsForDragSession(WebCore::roundedIntPoint(point), WebCore::roundedIntPoint(point), self._allowedDragSourceActions);
 }
 
 - (void)_dragInteraction:(UIDragInteraction *)interaction prepareForSession:(id <UIDragSession>)session completion:(dispatch_block_t)completion
@@ -6468,7 +6478,7 @@ static WebKit::DocumentEditingContextRequest toWebRequest(UIWKDocumentRequest *r
     _dragDropInteractionState.prepareForDragSession(session, completion);
 
     auto dragOrigin = WebCore::roundedIntPoint([session locationInView:self]);
-    _page->requestDragStart(dragOrigin, WebCore::roundedIntPoint([self convertPoint:dragOrigin toView:self.window]));
+    _page->requestDragStart(dragOrigin, WebCore::roundedIntPoint([self convertPoint:dragOrigin toView:self.window]), self._allowedDragSourceActions);
 
     RELEASE_LOG(DragAndDrop, "Drag session requested: %p at origin: {%d, %d}", session, dragOrigin.x(), dragOrigin.y());
 }
index b96f894..ff8bf69 100644 (file)
@@ -1177,16 +1177,16 @@ void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
     pageClient().didHandleAdditionalDragItemsRequest(added);
 }
 
-void WebPageProxy::requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition)
+void WebPageProxy::requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, WebCore::DragSourceAction allowedActions)
 {
     if (hasRunningProcess())
-        m_process->send(Messages::WebPage::RequestDragStart(clientPosition, globalPosition), m_pageID);
+        m_process->send(Messages::WebPage::RequestDragStart(clientPosition, globalPosition, allowedActions), m_pageID);
 }
 
-void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
+void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition, WebCore::DragSourceAction allowedActions)
 {
     if (hasRunningProcess())
-        m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition), m_pageID);
+        m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition, allowedActions), m_pageID);
 }
 
 void WebPageProxy::didConcludeEditDrag(Optional<TextIndicatorData> data)
index 98d8f69..60959a7 100644 (file)
@@ -47,7 +47,7 @@ void WebDragClient::willPerformDragSourceAction(DragSourceAction, const IntPoint
 
 DragSourceAction WebDragClient::dragSourceActionMaskForPoint(const IntPoint&)
 {
-    return DragSourceActionAny;
+    return m_page->allowedDragSourceActions();
 }
 
 #if !PLATFORM(COCOA) && !PLATFORM(GTK)
index 9ab010b..df4c75d 100644 (file)
@@ -57,6 +57,7 @@
 #include <WebCore/ActivityState.h>
 #include <WebCore/DictionaryPopupInfo.h>
 #include <WebCore/DisabledAdaptations.h>
+#include <WebCore/DragActions.h>
 #include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/HTMLMenuElement.h>
 #include <WebCore/HTMLMenuItemElement.h>
@@ -846,6 +847,7 @@ public:
     void willStartDrag() { ASSERT(!m_isStartingDrag); m_isStartingDrag = true; }
     void didStartDrag();
     void dragCancelled();
+    WebCore::DragSourceAction allowedDragSourceActions() const { return m_allowedDragSourceActions; }
 #endif
 
     void beginPrinting(uint64_t frameID, const PrintInfo&);
@@ -1229,8 +1231,8 @@ private:
 #endif
 
 #if PLATFORM(IOS_FAMILY) && ENABLE(DATA_INTERACTION)
-    void requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
-    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition);
+    void requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t allowedActions);
+    void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, uint64_t allowedActions);
 #endif
 
 #if !PLATFORM(COCOA) && !PLATFORM(WPE)
@@ -1732,6 +1734,7 @@ private:
 
 #if ENABLE(DRAG_SUPPORT)
     bool m_isStartingDrag { false };
+    WebCore::DragSourceAction m_allowedDragSourceActions { WebCore::DragSourceActionAny };
 #endif
 
     bool m_cachedMainFrameIsPinnedToLeftSide { true };
index 87c3396..23493e7 100644 (file)
@@ -301,8 +301,8 @@ messages -> WebPage LegacyReceiver {
 #endif
 
 #if ENABLE(DATA_INTERACTION)
-    RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition)
-    RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition)
+    RequestDragStart(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t allowedActions)
+    RequestAdditionalItemsForDragSession(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t allowedActions)
 #endif
 
     # Popup menu.
index c600a8d..b37aff5 100644 (file)
@@ -714,14 +714,16 @@ void WebPage::requestFocusedElementInformation(WebKit::CallbackID callbackID)
 }
 
 #if ENABLE(DATA_INTERACTION)
-void WebPage::requestDragStart(const IntPoint& clientPosition, const IntPoint& globalPosition)
+void WebPage::requestDragStart(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t allowedActions)
 {
+    SetForScope<WebCore::DragSourceAction> allowedActionsForScope(m_allowedDragSourceActions, static_cast<WebCore::DragSourceAction>(allowedActions));
     bool didStart = m_page->mainFrame().eventHandler().tryToBeginDragAtPoint(clientPosition, globalPosition);
     send(Messages::WebPageProxy::DidHandleDragStartRequest(didStart));
 }
 
-void WebPage::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
+void WebPage::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition, uint64_t allowedActions)
 {
+    SetForScope<WebCore::DragSourceAction> allowedActionsForScope(m_allowedDragSourceActions, static_cast<WebCore::DragSourceAction>(allowedActions));
     // To augment the platform drag session with additional items, end the current drag session and begin a new drag session with the new drag item.
     // This process is opaque to the UI process, which still maintains the old drag item in its drag session. Similarly, this persistent drag session
     // is opaque to the web process, which only sees that the current drag has ended, and that a new one is beginning.
index 8b49be9..702b2b3 100644 (file)
@@ -1,3 +1,24 @@
+2019-04-08  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Do not allow starting selection drags when selection views are not visible
+        https://bugs.webkit.org/show_bug.cgi?id=196686
+        <rdar://problem/49399192>
+
+        Reviewed by Tim Horton.
+
+        Adjust some existing API tests to make the web view become first responder before trying to begin dragging, and
+        also add some new API tests to cover scenarios where the web view is not first responder.
+
+        * TestWebKitAPI/Tests/ios/DragAndDropTestsIOS.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/cocoa/DragAndDropSimulator.h:
+
+        Add a switch to optionally make the web view first responder when starting the simulated drag.
+
+        * TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:
+        (-[DragAndDropSimulator initWithWebView:]):
+        (-[DragAndDropSimulator runFrom:to:additionalItemRequestLocations:]):
+
 2019-04-08  Justin Fan  <justin_fan@apple.com>
 
         [Web GPU] Fix Web GPU experimental feature on iOS
index 9ad4095..21936bd 100644 (file)
@@ -430,6 +430,31 @@ TEST(DragAndDropTests, NonEditableTextSelectionToTextarea)
     EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"destination.value"]);
 }
 
+TEST(DragAndDropTests, DoNotPerformSelectionDragWhenNotFirstResponder)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
+    [simulator setShouldBecomeFirstResponder:NO];
+
+    [webView synchronouslyLoadTestPageNamed:@"selected-text-and-textarea"];
+    [simulator runFrom:CGPointMake(160, 100) to:CGPointMake(160, 300)];
+
+    EXPECT_WK_STREQ("", [webView stringByEvaluatingJavaScript:@"destination.value"]);
+}
+
+TEST(DragAndDropTests, CanDragImageWhenNotFirstResponder)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
+    [simulator setShouldBecomeFirstResponder:NO];
+
+    [webView synchronouslyLoadTestPageNamed:@"image-and-contenteditable"];
+    [simulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 250)];
+
+    NSURL *droppedImageURL = [NSURL URLWithString:[webView stringByEvaluatingJavaScript:@"editor.querySelector('img').src"]];
+    EXPECT_WK_STREQ("blob", droppedImageURL.scheme);
+}
+
 TEST(DragAndDropTests, ContentEditableMoveParagraphs)
 {
     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
index 081e8b5..847c776 100644 (file)
@@ -95,6 +95,7 @@ typedef NSDictionary<NSNumber *, NSValue *> *ProgressToCGPointValueMap;
 @property (nonatomic, readonly) DragAndDropPhase phase;
 @property (nonatomic) BOOL allowsFocusToStartInputSession;
 @property (nonatomic) BOOL shouldEnsureUIApplication;
+@property (nonatomic) BOOL shouldBecomeFirstResponder;
 @property (nonatomic) BOOL shouldAllowMoveOperation;
 @property (nonatomic, strong) NSArray *externalItemProviders;
 @property (nonatomic, readonly) UIDropProposal *lastKnownDropProposal;
index 604cbca..5bed8cc 100644 (file)
@@ -343,6 +343,7 @@ static NSArray *dragAndDropEventNames()
     if (self = [super init]) {
         _webView = webView;
         _shouldEnsureUIApplication = NO;
+        _shouldBecomeFirstResponder = YES;
         _shouldAllowMoveOperation = YES;
         [_webView setUIDelegate:self];
         [_webView _setInputDelegate:self];
@@ -415,6 +416,9 @@ static NSArray *dragAndDropEventNames()
     if (_shouldEnsureUIApplication)
         UIApplicationInstantiateSingleton([DragAndDropSimulatorApplication class]);
 
+    if (_shouldBecomeFirstResponder)
+        [_webView becomeFirstResponder];
+
     [self _resetSimulatedState];
 
     if (additionalItemRequestLocations)