[Extra zoom mode] Form control values are stale after dismissing and representing...
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Feb 2018 05:50:13 +0000 (05:50 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Feb 2018 05:50:13 +0000 (05:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182877
<rdar://problem/37604395>

Reviewed by Tim Horton.

Currently, when presenting an input view controller for a focused element, we populate the initial form control
value using the WKContentView's assisted node information when it was last focused. However, if the user edits
the value of a form control, dismisses to the form control view controller (while the element is still focused)
and then begins editing the field again, the initial text will be the previous value of the input, since the
AssistedNodeInformation isn't up to date.

To fix this, we introduce a mechanism to update WKContentView's AssistedNodeInformation for the current assisted
node. This overwrites _assistedNodeInformation with new information computed from the web process, as long as
the assisted node before and after the request is made in the UI process has not changed. We accomplish this by
adding an identifier to AssistedNodeInformation, which is monotonically incremented when an element is focused
in the web process. The UI process may then use this identifier to determine whether AssistedNodeInformations
are describing the same focused element.

One interesting consideration here is that a normal AssistedNodeInformation update (propagated when focusing an
element) may be deferred in the UI process until the next layer tree commit. In the absence of the assisted node
identifier check, one could imagine a scenario in which the assisted node information in the UI process gets
"updated" from a new value to an old value:

1. The web process focuses an element and sends AssistedNodeInformation `A`.
2. WKContentView calls -updateCurrentAssistedNodeInformation.
3. The web process sends AssistedNodeInformation `B`.
4. `A` is received in the UI process, but deferred.
5. The UI process receives `B` and sets _assistedNodeInformation to `B`.
6. The UI process calls -_startAssistingNode: and sets _assistedNodeInformation to `A`.

This would mean that the _assistedNodeInformation is set to an earlier value, `A`, after being set to a later
value, `B`. However, because the AssistedNodeInformation identifier in step (2) refers to the assisted node
prior to step (1), the assisted node identifier in (5) would not match this identifier, and we would simply bail
instead of overwriting assisted node information.

We use this AssistedNodeInformation update mechanism after inserting text via input view controllers, and also
after reentering edit mode from the focused form control view controller. This fixes two issues where changing
the size of the focused element after editing it results in the focused form overlay highlighting a stale frame,
and also when setting the initial text when reentering edit mode for a form control that is already focused.

* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
(WebKit::AssistedNodeInformation::decode):
* Shared/AssistedNodeInformation.h:

Add a new monotonically increasing identifier (per WebPage) which associates a AssistedNodeInformation with a
focused element. In the event that the web process crashes and relaunches (thus resetting this identifier),
AssistedNodeInformation state in the UI process is now also reset (see -cleanupInteraction), so we won't end up
confusing AssistedNodeInformations computed by different WebPages between a web process crash.

* UIProcess/WebPageProxy.h:

A bit of related refactoring here to remove an unnecessary bool flag that indicates whether we have a deferred
assisted node information. Instead, just use the presence of m_deferredNodeAssistanceArguments.

* UIProcess/WebPageProxy.messages.in:

Add a AssistedNodeInformationCallback IPC message.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanupInteraction]):

Clear out the previous AssistedNodeInformation. See above for details.

(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
(-[WKContentView updateCurrentAssistedNodeInformation:]):

Tries to update AssistedNodeInformation for the current assisted node, invoking the completion callback when
finished. This may result in the assisted node information not being updated due to the current assisted node
changing in the time between the start of the request and the information being received in the UI process.

(-[WKContentView presentViewControllerForCurrentAssistedNode]):

Refactored from -presentViewControllerForAssistedNode:, such that it no longer takes an AssistedNodeInformation
as an argument, but rather just uses WKContentView's current _assistedNodeInformation. This was just being
called with _assistedNodeInformation from all call sites anyways.

(-[WKContentView textInputController:didCommitText:]):

Request an AssistedNodeInformation update after setting the value of a form control; if the assisted node hasn't
changed, update the focused form control overlay. This is needed to handle cases where the focused element's
frame may have changed after inserting text (e.g. due to line wrapping), and the focused form control overlay
needs to be updated to reflect this change.

(-[WKContentView focusedFormControlControllerDidBeginEditing:]):

Request an AssistedNodeInformation update before reentering edit mode; if the assisted node hasn't changed since
the start of the request, present the appropriate input view controller.

(-[WKContentView presentViewControllerForAssistedNode:]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::assistedNodeInformationCallback):
(WebKit::WebPageProxy::requestAssistedNodeInformation):
(WebKit::WebPageProxy::didCommitLayerTree):
(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::stopAssistingNode):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::elementDidFocus):

Increment the assisted node identifier.

* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::requestAssistedNodeInformation):

Compute and return an AssistedNodeInformation.

(WebKit::WebPage::getAssistedNodeInformation):

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

Source/WebKit/ChangeLog
Source/WebKit/Shared/AssistedNodeInformation.cpp
Source/WebKit/Shared/AssistedNodeInformation.h
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index 03c2176..bbff7dd 100644 (file)
@@ -1,3 +1,116 @@
+2018-02-17  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Extra zoom mode] Form control values are stale after dismissing and representing input view controllers
+        https://bugs.webkit.org/show_bug.cgi?id=182877
+        <rdar://problem/37604395>
+
+        Reviewed by Tim Horton.
+
+        Currently, when presenting an input view controller for a focused element, we populate the initial form control
+        value using the WKContentView's assisted node information when it was last focused. However, if the user edits
+        the value of a form control, dismisses to the form control view controller (while the element is still focused)
+        and then begins editing the field again, the initial text will be the previous value of the input, since the
+        AssistedNodeInformation isn't up to date.
+
+        To fix this, we introduce a mechanism to update WKContentView's AssistedNodeInformation for the current assisted
+        node. This overwrites _assistedNodeInformation with new information computed from the web process, as long as
+        the assisted node before and after the request is made in the UI process has not changed. We accomplish this by
+        adding an identifier to AssistedNodeInformation, which is monotonically incremented when an element is focused
+        in the web process. The UI process may then use this identifier to determine whether AssistedNodeInformations
+        are describing the same focused element.
+
+        One interesting consideration here is that a normal AssistedNodeInformation update (propagated when focusing an
+        element) may be deferred in the UI process until the next layer tree commit. In the absence of the assisted node
+        identifier check, one could imagine a scenario in which the assisted node information in the UI process gets
+        "updated" from a new value to an old value:
+
+        1. The web process focuses an element and sends AssistedNodeInformation `A`.
+        2. WKContentView calls -updateCurrentAssistedNodeInformation.
+        3. The web process sends AssistedNodeInformation `B`.
+        4. `A` is received in the UI process, but deferred.
+        5. The UI process receives `B` and sets _assistedNodeInformation to `B`.
+        6. The UI process calls -_startAssistingNode: and sets _assistedNodeInformation to `A`.
+
+        This would mean that the _assistedNodeInformation is set to an earlier value, `A`, after being set to a later
+        value, `B`. However, because the AssistedNodeInformation identifier in step (2) refers to the assisted node
+        prior to step (1), the assisted node identifier in (5) would not match this identifier, and we would simply bail
+        instead of overwriting assisted node information.
+
+        We use this AssistedNodeInformation update mechanism after inserting text via input view controllers, and also
+        after reentering edit mode from the focused form control view controller. This fixes two issues where changing
+        the size of the focused element after editing it results in the focused form overlay highlighting a stale frame,
+        and also when setting the initial text when reentering edit mode for a form control that is already focused.
+
+        * Shared/AssistedNodeInformation.cpp:
+        (WebKit::AssistedNodeInformation::encode const):
+        (WebKit::AssistedNodeInformation::decode):
+        * Shared/AssistedNodeInformation.h:
+
+        Add a new monotonically increasing identifier (per WebPage) which associates a AssistedNodeInformation with a
+        focused element. In the event that the web process crashes and relaunches (thus resetting this identifier),
+        AssistedNodeInformation state in the UI process is now also reset (see -cleanupInteraction), so we won't end up
+        confusing AssistedNodeInformations computed by different WebPages between a web process crash.
+
+        * UIProcess/WebPageProxy.h:
+
+        A bit of related refactoring here to remove an unnecessary bool flag that indicates whether we have a deferred
+        assisted node information. Instead, just use the presence of m_deferredNodeAssistanceArguments.
+
+        * UIProcess/WebPageProxy.messages.in:
+
+        Add a AssistedNodeInformationCallback IPC message.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView cleanupInteraction]):
+
+        Clear out the previous AssistedNodeInformation. See above for details.
+
+        (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+        (-[WKContentView updateCurrentAssistedNodeInformation:]):
+
+        Tries to update AssistedNodeInformation for the current assisted node, invoking the completion callback when
+        finished. This may result in the assisted node information not being updated due to the current assisted node
+        changing in the time between the start of the request and the information being received in the UI process.
+
+        (-[WKContentView presentViewControllerForCurrentAssistedNode]):
+
+        Refactored from -presentViewControllerForAssistedNode:, such that it no longer takes an AssistedNodeInformation
+        as an argument, but rather just uses WKContentView's current _assistedNodeInformation. This was just being
+        called with _assistedNodeInformation from all call sites anyways.
+
+        (-[WKContentView textInputController:didCommitText:]):
+
+        Request an AssistedNodeInformation update after setting the value of a form control; if the assisted node hasn't
+        changed, update the focused form control overlay. This is needed to handle cases where the focused element's
+        frame may have changed after inserting text (e.g. due to line wrapping), and the focused form control overlay
+        needs to be updated to reflect this change.
+
+        (-[WKContentView focusedFormControlControllerDidBeginEditing:]):
+
+        Request an AssistedNodeInformation update before reentering edit mode; if the assisted node hasn't changed since
+        the start of the request, present the appropriate input view controller.
+
+        (-[WKContentView presentViewControllerForAssistedNode:]): Deleted.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::assistedNodeInformationCallback):
+        (WebKit::WebPageProxy::requestAssistedNodeInformation):
+        (WebKit::WebPageProxy::didCommitLayerTree):
+        (WebKit::WebPageProxy::startAssistingNode):
+        (WebKit::WebPageProxy::stopAssistingNode):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::elementDidFocus):
+
+        Increment the assisted node identifier.
+
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::requestAssistedNodeInformation):
+
+        Compute and return an AssistedNodeInformation.
+
+        (WebKit::WebPage::getAssistedNodeInformation):
+
 2018-02-16  Dean Jackson  <dino@apple.com>
 
         Use OPENGL macros to be more clear about which OpenGL/ES WebGL uses on Cocoa
index 4236e09..dc984c8 100644 (file)
@@ -89,6 +89,7 @@ void AssistedNodeInformation::encode(IPC::Encoder& encoder) const
     encoder << acceptsAutofilledLoginCredentials;
     encoder << representingPageURL;
     encoder.encodeEnum(autofillFieldName);
+    encoder << assistedNodeIdentifier;
 }
 
 bool AssistedNodeInformation::decode(IPC::Decoder& decoder, AssistedNodeInformation& result)
@@ -171,6 +172,9 @@ bool AssistedNodeInformation::decode(IPC::Decoder& decoder, AssistedNodeInformat
     if (!decoder.decodeEnum(result.autofillFieldName))
         return false;
 
+    if (!decoder.decode(result.assistedNodeIdentifier))
+        return false;
+
     return true;
 }
 #endif
index 08a9f72..e4f3d49 100644 (file)
@@ -114,6 +114,8 @@ struct AssistedNodeInformation {
     WebCore::URL representingPageURL;
     WebCore::AutofillFieldName autofillFieldName { WebCore::AutofillFieldName::None };
 
+    uint64_t assistedNodeIdentifier { 0 };
+
     void encode(IPC::Encoder&) const;
     static bool decode(IPC::Decoder&, AssistedNodeInformation&);
 };
index 0c238c4..5210b70 100644 (file)
@@ -285,6 +285,7 @@ typedef GenericCallback<const String&, double, bool> FontAtSelectionCallback;
 typedef GenericCallback<const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t> GestureCallback;
 typedef GenericCallback<const WebCore::IntPoint&, uint32_t, uint32_t> TouchesCallback;
 typedef GenericCallback<const Vector<WebCore::SelectionRect>&> SelectionRectsCallback;
+typedef GenericCallback<const AssistedNodeInformation&> AssistedNodeInformationCallback;
 struct NodeAssistanceArguments {
     AssistedNodeInformation m_nodeInformation;
     bool m_userIsInteracting;
@@ -1090,6 +1091,7 @@ public:
     void setShouldRecordNavigationSnapshots(bool shouldRecordSnapshots) { m_shouldRecordNavigationSnapshots = shouldRecordSnapshots; }
     void recordAutomaticNavigationSnapshot();
     void recordNavigationSnapshot(WebBackForwardListItem&);
+    void requestAssistedNodeInformation(Function<void(const AssistedNodeInformation&, CallbackBase::Error)>&&);
 
 #if PLATFORM(COCOA)
     RefPtr<ViewSnapshot> takeViewSnapshot();
@@ -1625,6 +1627,7 @@ private:
 
     void enableInspectorNodeSearch();
     void disableInspectorNodeSearch();
+    void assistedNodeInformationCallback(const AssistedNodeInformation&, CallbackID);
 #endif // PLATFORM(IOS)
 
 #if ENABLE(DATA_DETECTION)
@@ -2081,7 +2084,6 @@ private:
 #endif
 
 #if PLATFORM(IOS)
-    bool m_hasDeferredStartAssistingNode { false };
     std::unique_ptr<NodeAssistanceArguments> m_deferredNodeAssistanceArguments;
     bool m_forceAlwaysUserScalable { false };
     WebCore::FloatSize m_viewportConfigurationMinimumLayoutSize;
index d41fe92..d09bb3e 100644 (file)
@@ -400,6 +400,7 @@ messages -> WebPageProxy {
     OverflowScrollDidEndScroll()
     ShowInspectorHighlight(struct WebCore::Highlight highlight)
     HideInspectorHighlight()
+    AssistedNodeInformationCallback(struct WebKit::AssistedNodeInformation information, WebKit::CallbackID callbackID)
 
     ShowInspectorIndication()
     HideInspectorIndication()
index 29381ca..4171efb 100644 (file)
@@ -717,6 +717,7 @@ static WKDragSessionContext *ensureLocalDragSessionContext(id <UIDragSession> se
     }
     
     _inputViewUpdateDeferrer = nullptr;
+    _assistedNodeInformation = { };
 }
 
 - (void)_removeDefaultGestureRecognizers
@@ -4032,7 +4033,7 @@ static bool isAssistableInputType(InputType type)
 #if ENABLE(EXTRA_ZOOM_MODE)
     [self presentFocusedFormControlViewController:NO];
     if (!_isChangingFocus)
-        [self presentViewControllerForAssistedNode:_assistedNodeInformation];
+        [self presentViewControllerForCurrentAssistedNode];
 #else
     [self reloadInputViews];
 #endif
@@ -4101,6 +4102,22 @@ static bool isAssistableInputType(InputType type)
     [_webView didEndFormControlInteraction];
 }
 
+- (void)updateCurrentAssistedNodeInformation:(Function<void(bool didUpdate)>&&)callback
+{
+    WeakObjCPtr<WKContentView> weakSelf { self };
+    auto identifierBeforeUpdate = _assistedNodeInformation.assistedNodeIdentifier;
+    _page->requestAssistedNodeInformation([callback = WTFMove(callback), identifierBeforeUpdate, weakSelf] (auto& info, auto error) {
+        if (!weakSelf || error != CallbackBase::Error::None || info.assistedNodeIdentifier != identifierBeforeUpdate) {
+            // If the assisted node may have changed in the meantime, don't overwrite assisted node information.
+            callback(false);
+            return;
+        }
+
+        weakSelf.get()->_assistedNodeInformation = info;
+        callback(true);
+    });
+}
+
 #if ENABLE(EXTRA_ZOOM_MODE)
 
 - (void)dismissAllInputViewControllers
@@ -4207,9 +4224,11 @@ static bool isAssistableInputType(InputType type)
     [_focusedFormControlViewController presentViewController:_numberPadViewController.get() animated:animated completion:nil];
 }
 
-- (void)presentViewControllerForAssistedNode:(const AssistedNodeInformation&)info
+- (void)presentViewControllerForCurrentAssistedNode
 {
-    switch (info.elementType) {
+    [self dismissAllInputViewControllers];
+
+    switch (_assistedNodeInformation.elementType) {
     case InputType::Number:
     case InputType::NumberPad:
     case InputType::Phone:
@@ -4253,7 +4272,6 @@ static bool isAssistableInputType(InputType type)
 
 - (void)textInputController:(WKTextFormControlViewController *)controller didCommitText:(NSString *)text
 {
-    // FIXME: Update cached AssistedNodeInformation state in the UI process.
     _page->setTextAsync(text);
 
     if (![self actionNameForFocusedFormControlController:_focusedFormControlViewController.get()] && !_assistedNodeInformation.hasNextNode && !_assistedNodeInformation.hasPreviousNode) {
@@ -4265,6 +4283,10 @@ static bool isAssistableInputType(InputType type)
 
     [_focusedFormControlViewController show:NO];
     [self dismissAllInputViewControllers];
+    [self updateCurrentAssistedNodeInformation:[weakSelf = WeakObjCPtr<WKContentView>(self)] (bool didUpdate) {
+        if (didUpdate)
+            [weakSelf.get()->_focusedFormControlViewController reloadData:YES];
+    }];
 }
 
 - (void)textInputControllerDidRequestDismissal:(WKTextFormControlViewController *)controller
@@ -4285,7 +4307,10 @@ static bool isAssistableInputType(InputType type)
 
 - (void)focusedFormControlControllerDidBeginEditing:(WKFocusedFormControlViewController *)controller
 {
-    [self presentViewControllerForAssistedNode:_assistedNodeInformation];
+    [self updateCurrentAssistedNodeInformation:[weakSelf = WeakObjCPtr<WKContentView>(self)] (bool didUpdate) {
+        if (didUpdate)
+            [weakSelf presentViewControllerForCurrentAssistedNode];
+    }];
 }
 
 - (CGRect)highlightedRectForFocusedFormControlController:(WKFocusedFormControlViewController *)controller inCoordinateSpace:(id <UICoordinateSpace>)coordinateSpace
index 96a8bfe..ca6d8d2 100644 (file)
@@ -192,6 +192,28 @@ void WebPageProxy::selectionRectsCallback(const Vector<WebCore::SelectionRect>&
     callback->performCallbackWithReturnValue(selectionRects);
 }
 
+void WebPageProxy::assistedNodeInformationCallback(const AssistedNodeInformation& info, CallbackID callbackID)
+{
+    auto callback = m_callbacks.take<AssistedNodeInformationCallback>(callbackID);
+    if (!callback) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    callback->performCallbackWithReturnValue(info);
+}
+
+void WebPageProxy::requestAssistedNodeInformation(Function<void(const AssistedNodeInformation&, CallbackBase::Error)>&& callback)
+{
+    if (!isValid()) {
+        callback({ }, CallbackBase::Error::OwnerWasInvalidated);
+        return;
+    }
+
+    auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
+    m_process->send(Messages::WebPage::RequestAssistedNodeInformation(callbackID), m_pageID);
+}
+
 void WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdate)
 {
     if (!isValid())
@@ -397,10 +419,9 @@ void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction&
         didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
     }
 
-    if (m_hasDeferredStartAssistingNode) {
+    if (m_deferredNodeAssistanceArguments) {
         m_pageClient.startAssistingNode(m_deferredNodeAssistanceArguments->m_nodeInformation, m_deferredNodeAssistanceArguments->m_userIsInteracting, m_deferredNodeAssistanceArguments->m_blurPreviousNode,
             m_deferredNodeAssistanceArguments->m_changingActivityState, m_deferredNodeAssistanceArguments->m_userData.get());
-        m_hasDeferredStartAssistingNode = false;
         m_deferredNodeAssistanceArguments = nullptr;
     }
 }
@@ -915,7 +936,6 @@ void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information
     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
     if (m_editorState.isMissingPostLayoutData) {
         m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject });
-        m_hasDeferredStartAssistingNode = true;
         return;
     }
 
@@ -924,10 +944,7 @@ void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information
 
 void WebPageProxy::stopAssistingNode()
 {
-    if (m_hasDeferredStartAssistingNode) {
-        m_hasDeferredStartAssistingNode = false;
-        m_deferredNodeAssistanceArguments = nullptr;
-    }
+    m_deferredNodeAssistanceArguments = nullptr;
     m_pageClient.stopAssistingNode();
 }
 
index eff4a0a..0c1aa9e 100644 (file)
@@ -4909,6 +4909,7 @@ void WebPage::elementDidFocus(WebCore::Node* node)
         m_isAssistingNodeDueToUserInteraction |= m_userIsInteracting;
 
 #if PLATFORM(IOS)
+        ++m_currentAssistedNodeIdentifier;
         AssistedNodeInformation information;
         getAssistedNodeInformation(information);
         RefPtr<API::Object> userData;
index bdb303c..a16c6ae 100644 (file)
@@ -568,6 +568,7 @@ public:
     void inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint&);
 
     void blurAssistedNode();
+    void requestAssistedNodeInformation(CallbackID);
     void selectWithGesture(const WebCore::IntPoint&, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, CallbackID);
     void updateSelectionWithTouches(const WebCore::IntPoint&, uint32_t touches, bool baseIsStart, CallbackID);
 #if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
@@ -1631,6 +1632,7 @@ private:
     RefPtr<WebCore::Node> m_pendingSyntheticClickNode;
     WebCore::FloatPoint m_pendingSyntheticClickLocation;
     WebCore::FloatRect m_previousExposedContentRect;
+    uint64_t m_currentAssistedNodeIdentifier { 0 };
 #endif
 
     WebCore::Timer m_layerVolatilityTimer;
index 1f13512..3171b40 100644 (file)
@@ -104,6 +104,7 @@ messages -> WebPage LegacyReceiver {
     StoreSelectionForAccessibility(bool shouldStore)
     StartAutoscrollAtPosition(WebCore::FloatPoint positionInWindow)
     CancelAutoscroll()
+    RequestAssistedNodeInformation(WebKit::CallbackID callbackID)
 #endif
 
     SetControlledByAutomation(bool controlled)
index aaf25cb..db139a9 100644 (file)
@@ -656,6 +656,15 @@ void WebPage::handleTap(const IntPoint& point, uint64_t lastLayerTreeTransaction
         handleSyntheticClick(nodeRespondingToClick, adjustedPoint);
 }
 
+void WebPage::requestAssistedNodeInformation(WebKit::CallbackID callbackID)
+{
+    AssistedNodeInformation info;
+    if (m_assistedNode)
+        getAssistedNodeInformation(info);
+
+    send(Messages::WebPageProxy::AssistedNodeInformationCallback(info, callbackID));
+}
+
 #if ENABLE(DATA_INTERACTION)
 void WebPage::requestStartDataInteraction(const IntPoint& clientPosition, const IntPoint& globalPosition)
 {
@@ -2738,6 +2747,7 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
     information.allowsUserScalingIgnoringAlwaysScalable = m_viewportConfiguration.allowsUserScalingIgnoringAlwaysScalable();
     information.hasNextNode = hasAssistableElement(m_assistedNode.get(), *m_page, true);
     information.hasPreviousNode = hasAssistableElement(m_assistedNode.get(), *m_page, false);
+    information.assistedNodeIdentifier = m_currentAssistedNodeIdentifier;
 
     if (is<HTMLSelectElement>(*m_assistedNode)) {
         HTMLSelectElement& element = downcast<HTMLSelectElement>(*m_assistedNode);