[iOS] Expose SPI to access the current sentence boundary and selection state
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / ios / WebPageIOS.mm
index 57807c6..c74a636 100644 (file)
@@ -29,7 +29,6 @@
 #if PLATFORM(IOS_FAMILY)
 
 #import "AccessibilityIOS.h"
-#import "AssistedNodeInformation.h"
 #import "DataReference.h"
 #import "DrawingArea.h"
 #import "EditingRange.h"
 #import <WebCore/HTMLFormElement.h>
 #import <WebCore/HTMLImageElement.h>
 #import <WebCore/HTMLInputElement.h>
+#import <WebCore/HTMLLabelElement.h>
 #import <WebCore/HTMLOptGroupElement.h>
 #import <WebCore/HTMLOptionElement.h>
 #import <WebCore/HTMLParserIdioms.h>
 #import <WebCore/HTMLSelectElement.h>
+#import <WebCore/HTMLSummaryElement.h>
 #import <WebCore/HTMLTextAreaElement.h>
 #import <WebCore/HTMLTextFormControlElement.h>
 #import <WebCore/HistoryItem.h>
@@ -198,7 +199,11 @@ void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePost
     // have a composition or are using a hardware keyboard then we send the full editor state
     // immediately so that the UIProcess can update UI, including the position of the caret.
     bool needsLayout = !frame.view() || frame.view()->needsLayout();
-    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No && needsLayout && ![UIKeyboard isInHardwareKeyboardMode] && !frame.editor().hasComposition()) {
+    bool requiresPostLayoutData = frame.editor().hasComposition();
+#if !PLATFORM(IOSMAC)
+    requiresPostLayoutData |= [UIKeyboard isInHardwareKeyboardMode];
+#endif
+    if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No && needsLayout && !requiresPostLayoutData) {
         result.isMissingPostLayoutData = true;
         return;
     }
@@ -235,12 +240,13 @@ void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePost
         // FIXME: We should disallow replace when the string contains only CJ characters.
         postLayoutData.isReplaceAllowed = result.isContentEditable && !result.isInPasswordField && !selectedText.isAllSpecialCharacters<isHTMLSpace>();
     }
+    postLayoutData.atStartOfSentence = frame.selection().selectionAtSentenceStart();
     postLayoutData.insideFixedPosition = startNodeIsInsideFixedPosition || endNodeIsInsideFixedPosition;
     if (!selection.isNone()) {
-        if (m_assistedNode && m_assistedNode->renderer()) {
-            postLayoutData.selectionClipRect = view->contentsToRootView(m_assistedNode->renderer()->absoluteBoundingBoxRect());
-            postLayoutData.caretColor = m_assistedNode->renderer()->style().caretColor();
-            postLayoutData.elementIsTransparent = m_assistedNode->renderer()->isTransparentRespectingParentFrames();
+        if (m_focusedElement && m_focusedElement->renderer()) {
+            postLayoutData.focusedElementRect = view->contentsToRootView(m_focusedElement->renderer()->absoluteBoundingBoxRect());
+            postLayoutData.caretColor = m_focusedElement->renderer()->style().caretColor();
+            postLayoutData.elementIsTransparentOrFullyClipped = m_focusedElement->renderer()->isTransparentOrFullyClippedRespectingParentFrames();
         }
         computeEditableRootHasContentAndPlainText(selection, postLayoutData);
     }
@@ -337,7 +343,7 @@ void WebPage::restorePageState(const HistoryItem& historyItem)
         float boundedScale = std::min<float>(m_viewportConfiguration.maximumScale(), std::max<float>(m_viewportConfiguration.minimumScale(), historyItem.pageScaleFactor()));
         scalePage(boundedScale, IntPoint());
 
-        std::optional<FloatPoint> scrollPosition;
+        Optional<FloatPoint> scrollPosition;
         if (historyItem.shouldRestoreScrollPosition()) {
             m_drawingArea->setExposedContentRect(historyItem.exposedContentRect());
             scrollPosition = FloatPoint(historyItem.scrollPosition());
@@ -350,7 +356,7 @@ void WebPage::restorePageState(const HistoryItem& historyItem)
 
         double newScale = scaleAfterViewportWidthChange(historyItem.pageScaleFactor(), !historyItem.scaleIsInitial(), m_viewportConfiguration, currentMinimumLayoutSizeInScrollViewCoordinates.width(), newContentSize, oldContentSize, visibleHorizontalFraction);
 
-        std::optional<FloatPoint> newCenter;
+        Optional<FloatPoint> newCenter;
         if (historyItem.shouldRestoreScrollPosition()) {
             if (!oldContentSize.isEmpty() && !newContentSize.isEmpty() && newContentSize != oldContentSize)
                 newCenter = relativeCenterAfterContentSizeChange(historyItem.unobscuredContentRect(), oldContentSize, newContentSize);
@@ -413,21 +419,6 @@ void WebPage::sendComplexTextInputToPlugin(uint64_t, const String&)
     notImplemented();
 }
 
-void WebPage::performDictionaryLookupAtLocation(const FloatPoint&)
-{
-    notImplemented();
-}
-
-void WebPage::performDictionaryLookupForSelection(Frame&, const VisibleSelection&, TextIndicatorPresentationTransition)
-{
-    notImplemented();
-}
-
-void WebPage::performDictionaryLookupForRange(Frame&, Range&, NSDictionary *, TextIndicatorPresentationTransition)
-{
-    notImplemented();
-}
-
 bool WebPage::performNonEditingBehaviorForSelector(const String&, WebCore::KeyboardEvent*)
 {
     notImplemented();
@@ -546,11 +537,14 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F
     IntPoint roundedAdjustedPoint = roundedIntPoint(location);
     Frame& mainframe = m_page->mainFrame();
 
-    WKBeginObservingContentChanges(true);
+    LOG_WITH_STREAM(ContentObservation, stream << "handleSyntheticClick: node(" << nodeRespondingToClick << ") " << location);
+    WKStartObservingContentChanges();
+    WKStartObservingDOMTimerScheduling();
 
     mainframe.eventHandler().mouseMoved(PlatformMouseEvent(roundedAdjustedPoint, roundedAdjustedPoint, NoButton, PlatformEvent::MouseMoved, 0, false, false, false, false, WallTime::now(), WebCore::ForceAtClick, WebCore::NoTap));
     mainframe.document()->updateStyleIfNeeded();
 
+    WKStopObservingDOMTimerScheduling();
     WKStopObservingContentChanges();
 
     m_pendingSyntheticClickNode = nullptr;
@@ -562,13 +556,16 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F
     switch (WKObservedContentChange()) {
     case WKContentVisibilityChange:
         // The move event caused new contents to appear. Don't send the click event.
+        LOG(ContentObservation, "handleSyntheticClick: Observed meaningful visible change -> hover.");
         return;
     case WKContentIndeterminateChange:
         // Wait for callback to completePendingSyntheticClickForContentChangeObserver() to decide whether to send the click event.
         m_pendingSyntheticClickNode = nodeRespondingToClick;
         m_pendingSyntheticClickLocation = location;
+        LOG(ContentObservation, "handleSyntheticClick: Observed some change, but can't decide it yet -> wait.");
         return;
     case WKContentNoChange:
+        LOG(ContentObservation, "handleSyntheticClick: No change was observed -> click.");
         completeSyntheticClick(nodeRespondingToClick, location, WebCore::OneFingerTap);
         return;
     }
@@ -577,11 +574,15 @@ void WebPage::handleSyntheticClick(Node* nodeRespondingToClick, const WebCore::F
 
 void WebPage::completePendingSyntheticClickForContentChangeObserver()
 {
+    LOG_WITH_STREAM(ContentObservation, stream << "completePendingSyntheticClickForContentChangeObserver: pending target node(" << m_pendingSyntheticClickNode << ")");
     if (!m_pendingSyntheticClickNode)
         return;
     // Only dispatch the click if the document didn't get changed by any timers started by the move event.
-    if (WKObservedContentChange() == WKContentNoChange)
+    if (WKObservedContentChange() == WKContentNoChange) {
+        LOG(ContentObservation, "No chage was observed -> click.");
         completeSyntheticClick(m_pendingSyntheticClickNode.get(), m_pendingSyntheticClickLocation, WebCore::OneFingerTap);
+    } else
+        LOG(ContentObservation, "Observed meaningful visible change -> hover.");
 
     m_pendingSyntheticClickNode = nullptr;
     m_pendingSyntheticClickLocation = FloatPoint();
@@ -616,7 +617,7 @@ void WebPage::completeSyntheticClick(Node* nodeRespondingToClick, const WebCore:
     // If the node has been focused by JavaScript without user interaction, the
     // keyboard is not on screen.
     if (newFocusedElement && newFocusedElement == oldFocusedElement)
-        elementDidFocus(newFocusedElement.get());
+        elementDidRefocus(*newFocusedElement);
 
     if (!tapWasHandled || !nodeRespondingToClick || !nodeRespondingToClick->isElementNode())
         send(Messages::WebPageProxy::DidNotHandleTapAsClick(roundedIntPoint(location)));
@@ -644,13 +645,13 @@ void WebPage::handleTap(const IntPoint& point, uint64_t lastLayerTreeTransaction
         handleSyntheticClick(nodeRespondingToClick, adjustedPoint);
 }
 
-void WebPage::requestAssistedNodeInformation(WebKit::CallbackID callbackID)
+void WebPage::requestFocusedElementInformation(WebKit::CallbackID callbackID)
 {
-    AssistedNodeInformation info;
-    if (m_assistedNode)
-        getAssistedNodeInformation(info);
+    FocusedElementInformation info;
+    if (m_focusedElement)
+        getFocusedElementInformation(info);
 
-    send(Messages::WebPageProxy::AssistedNodeInformationCallback(info, callbackID));
+    send(Messages::WebPageProxy::FocusedElementInformationCallback(info, callbackID));
 }
 
 #if ENABLE(DATA_INTERACTION)
@@ -675,7 +676,7 @@ void WebPage::requestAdditionalItemsForDragSession(const IntPoint& clientPositio
 
 void WebPage::didConcludeEditDataInteraction()
 {
-    std::optional<TextIndicatorData> textIndicatorData;
+    Optional<TextIndicatorData> textIndicatorData;
 
     static auto defaultEditDataInteractionTextIndicatorOptions = TextIndicatorOptionIncludeSnapshotOfAllVisibleContentWithoutSelection | TextIndicatorOptionExpandClipBeyondVisibleRect | TextIndicatorOptionPaintAllContent | TextIndicatorOptionIncludeMarginIfRangeMatchesSelection | TextIndicatorOptionPaintBackgrounds | TextIndicatorOptionComputeEstimatedBackgroundColor| TextIndicatorOptionUseSelectionRectForSizing | TextIndicatorOptionIncludeSnapshotWithSelectionHighlight;
     auto& frame = m_page->focusController().focusedOrMainFrame();
@@ -727,7 +728,8 @@ void WebPage::sendTapHighlightForNodeIfNecessary(uint64_t requestID, Node* node)
         if (is<RenderBox>(*renderer))
             borderRadii = downcast<RenderBox>(*renderer).borderRadii();
 
-        send(Messages::WebPageProxy::DidGetTapHighlightGeometries(requestID, highlightColor, quads, roundedIntSize(borderRadii.topLeft()), roundedIntSize(borderRadii.topRight()), roundedIntSize(borderRadii.bottomLeft()), roundedIntSize(borderRadii.bottomRight())));
+        bool nodeHasBuiltInClickHandling = is<HTMLFormControlElement>(*node) || is<HTMLAnchorElement>(*node) || is<HTMLLabelElement>(*node) || is<HTMLSummaryElement>(*node) || node->isLink();
+        send(Messages::WebPageProxy::DidGetTapHighlightGeometries(requestID, highlightColor, quads, roundedIntSize(borderRadii.topLeft()), roundedIntSize(borderRadii.topRight()), roundedIntSize(borderRadii.bottomLeft()), roundedIntSize(borderRadii.bottomRight()), nodeHasBuiltInClickHandling));
     }
 #else
     UNUSED_PARAM(requestID);
@@ -754,6 +756,38 @@ void WebPage::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t
         completeSyntheticClick(nodeRespondingToClick, adjustedPoint, WebCore::TwoFingerTap);
 }
 
+void WebPage::handleStylusSingleTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID)
+{
+    SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
+
+    auto& frame = m_page->focusController().focusedOrMainFrame();
+
+    auto pointInDocument = frame.view()->rootViewToContents(point);
+    HitTestResult hitTest = frame.eventHandler().hitTestResultAtPoint(pointInDocument, HitTestRequest::ReadOnly | HitTestRequest::Active);
+
+    Node* node = hitTest.innerNonSharedNode();
+    if (!node)
+        return;
+    auto renderer = node->renderer();
+    if (!renderer)
+        return;
+
+    if (renderer->isReplaced())
+        return;
+
+    VisiblePosition position = renderer->positionForPoint(hitTest.localPoint(), nullptr);
+    if (position.isNull())
+        position = firstPositionInOrBeforeNode(node);
+
+    if (position.isNull())
+        return;
+
+    auto range = Range::create(*frame.document(), position, position);
+    frame.selection().setSelectedRange(range.ptr(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
+    auto image = frame.editor().insertEditableImage();
+    frame.document()->setFocusedElement(image.get());
+}
+
 void WebPage::potentialTapAtPosition(uint64_t requestID, const WebCore::FloatPoint& position)
 {
     m_potentialTapNode = m_page->mainFrame().nodeRespondingToClickEvents(position, m_potentialTapLocation, m_potentialTapSecurityOrigin.get());
@@ -843,29 +877,31 @@ void WebPage::inspectorNodeSearchEndedAtPosition(const FloatPoint& position)
         node->inspect();
 }
 
-void WebPage::blurAssistedNode()
+void WebPage::blurFocusedElement()
 {
-    if (is<Element>(m_assistedNode.get()))
-        downcast<Element>(*m_assistedNode).blur();
+    if (!m_focusedElement)
+        return;
+
+    m_focusedElement->blur();
 }
 
-void WebPage::setAssistedNodeValue(const String& value)
+void WebPage::setFocusedElementValue(const String& value)
 {
     // FIXME: should also handle the case of HTMLSelectElement.
-    if (is<HTMLInputElement>(m_assistedNode.get()))
-        downcast<HTMLInputElement>(*m_assistedNode).setValue(value, DispatchInputAndChangeEvent);
+    if (is<HTMLInputElement>(m_focusedElement.get()))
+        downcast<HTMLInputElement>(*m_focusedElement).setValue(value, DispatchInputAndChangeEvent);
 }
 
-void WebPage::setAssistedNodeValueAsNumber(double value)
+void WebPage::setFocusedElementValueAsNumber(double value)
 {
-    if (is<HTMLInputElement>(m_assistedNode.get()))
-        downcast<HTMLInputElement>(*m_assistedNode).setValueAsNumber(value, DispatchInputAndChangeEvent);
+    if (is<HTMLInputElement>(m_focusedElement.get()))
+        downcast<HTMLInputElement>(*m_focusedElement).setValueAsNumber(value, DispatchInputAndChangeEvent);
 }
 
-void WebPage::setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
+void WebPage::setFocusedElementSelectedIndex(uint32_t index, bool allowMultipleSelection)
 {
-    if (is<HTMLSelectElement>(m_assistedNode.get()))
-        downcast<HTMLSelectElement>(*m_assistedNode).optionSelectedByUser(index, true, allowMultipleSelection);
+    if (is<HTMLSelectElement>(m_focusedElement.get()))
+        downcast<HTMLSelectElement>(*m_focusedElement).optionSelectedByUser(index, true, allowMultipleSelection);
 }
 
 void WebPage::showInspectorHighlight(const WebCore::Highlight& highlight)
@@ -904,13 +940,13 @@ void WebPage::setForceAlwaysUserScalable(bool userScalable)
     m_viewportConfiguration.setForceAlwaysUserScalable(userScalable);
 }
 
-static FloatQuad innerFrameQuad(const Frame& frame, const Node& assistedNode)
+static FloatQuad innerFrameQuad(const Frame& frame, const Element& focusedElement)
 {
     frame.document()->updateLayoutIgnorePendingStylesheets();
     RenderElement* renderer = nullptr;
-    if (assistedNode.hasTagName(HTMLNames::textareaTag) || assistedNode.hasTagName(HTMLNames::inputTag) || assistedNode.hasTagName(HTMLNames::selectTag))
-        renderer = downcast<RenderElement>(assistedNode.renderer());
-    else if (Element* rootEditableElement = assistedNode.rootEditableElement())
+    if (focusedElement.hasTagName(HTMLNames::textareaTag) || focusedElement.hasTagName(HTMLNames::inputTag) || focusedElement.hasTagName(HTMLNames::selectTag))
+        renderer = focusedElement.renderer();
+    else if (auto* rootEditableElement = focusedElement.rootEditableElement())
         renderer = rootEditableElement->renderer();
     
     if (!renderer)
@@ -926,11 +962,11 @@ static FloatQuad innerFrameQuad(const Frame& frame, const Node& assistedNode)
     return FloatQuad(boundingBox);
 }
 
-static IntPoint constrainPoint(const IntPoint& point, const Frame& frame, const Node& assistedNode)
+static IntPoint constrainPoint(const IntPoint& point, const Frame& frame, const Element& focusedElement)
 {
-    ASSERT(&assistedNode.document() == frame.document());
+    ASSERT(&focusedElement.document() == frame.document());
     const int DEFAULT_CONSTRAIN_INSET = 2;
-    IntRect innerFrame = innerFrameQuad(frame, assistedNode).enclosingBoundingBox();
+    IntRect innerFrame = innerFrameQuad(frame, focusedElement).enclosingBoundingBox();
     IntPoint constrainedPoint = point;
 
     int minX = innerFrame.x() + DEFAULT_CONSTRAIN_INSET;
@@ -1058,10 +1094,10 @@ RefPtr<Range> WebPage::rangeForWebSelectionAtPosition(const IntPoint& point, con
     return range->collapsed() ? nullptr : range;
 }
 
-void WebPage::selectWithGesture(const IntPoint& point, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::selectWithGesture(const IntPoint& point, uint32_t granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
 
     if (position.isNull()) {
         send(Messages::WebPageProxy::GestureCallback(point, gestureType, gestureState, 0, callbackID));
@@ -1431,8 +1467,8 @@ void WebPage::moveSelectionByOffset(int32_t offset, CallbackID callbackID)
     
 void WebPage::startAutoscrollAtPosition(const WebCore::FloatPoint& positionInWindow)
 {
-    if (m_assistedNode && m_assistedNode->renderer())
-        m_page->mainFrame().eventHandler().startSelectionAutoscroll(m_assistedNode->renderer(), positionInWindow);
+    if (m_focusedElement && m_focusedElement->renderer())
+        m_page->mainFrame().eventHandler().startSelectionAutoscroll(m_focusedElement->renderer(), positionInWindow);
     else {
         Frame& frame = m_page->focusController().focusedOrMainFrame();
         VisibleSelection selection = frame.selection().selection();
@@ -1532,27 +1568,27 @@ void WebPage::getRectsAtSelectionOffsetWithText(int32_t offset, const String& te
     send(Messages::WebPageProxy::SelectionRectsCallback(selectionRects, callbackID));
 }
 
-VisiblePosition WebPage::visiblePositionInFocusedNodeForPoint(const Frame& frame, const IntPoint& point, bool isInteractingWithAssistedNode)
+VisiblePosition WebPage::visiblePositionInFocusedNodeForPoint(const Frame& frame, const IntPoint& point, bool isInteractingWithFocusedElement)
 {
     IntPoint adjustedPoint(frame.view()->rootViewToContents(point));
-    IntPoint constrainedPoint = m_assistedNode && isInteractingWithAssistedNode ? constrainPoint(adjustedPoint, frame, *m_assistedNode) : adjustedPoint;
+    IntPoint constrainedPoint = m_focusedElement && isInteractingWithFocusedElement ? constrainPoint(adjustedPoint, frame, *m_focusedElement) : adjustedPoint;
     return frame.visiblePositionForPoint(constrainedPoint);
 }
 
-void WebPage::selectPositionAtPoint(const WebCore::IntPoint& point, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::selectPositionAtPoint(const WebCore::IntPoint& point, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
     
     if (position.isNotNull())
         frame.selection().setSelectedRange(Range::create(*frame.document(), position, position).ptr(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
     send(Messages::WebPageProxy::VoidCallback(callbackID));
 }
 
-void WebPage::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint& point, uint32_t granularity, uint32_t direction, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint& point, uint32_t granularity, uint32_t direction, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
 
     if (position.isNotNull()) {
         position = positionOfNextBoundaryOfGranularity(position, static_cast<WebCore::TextGranularity>(granularity), static_cast<SelectionDirection>(direction));
@@ -1576,9 +1612,9 @@ void WebPage::moveSelectionAtBoundaryWithDirection(uint32_t granularity, uint32_
     send(Messages::WebPageProxy::VoidCallback(callbackID));
 }
 
-RefPtr<Range> WebPage::rangeForGranularityAtPoint(Frame& frame, const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithAssistedNode)
+RefPtr<Range> WebPage::rangeForGranularityAtPoint(Frame& frame, const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithFocusedElement)
 {
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
 
     RefPtr<Range> range;
     switch (static_cast<WebCore::TextGranularity>(granularity)) {
@@ -1606,11 +1642,11 @@ static inline bool rectIsTooBigForSelection(const IntRect& blockRect, const Fram
     return blockRect.height() > frame.view()->unobscuredContentRect().height() * factor;
 }
 
-void WebPage::selectTextWithGranularityAtPoint(const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::selectTextWithGranularityAtPoint(const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    RefPtr<Range> range = rangeForGranularityAtPoint(frame, point, granularity, isInteractingWithAssistedNode);
-    if (!isInteractingWithAssistedNode) {
+    RefPtr<Range> range = rangeForGranularityAtPoint(frame, point, granularity, isInteractingWithFocusedElement);
+    if (!isInteractingWithFocusedElement) {
         m_blockSelectionDesiredSize.setWidth(blockSelectionStartWidth);
         m_blockSelectionDesiredSize.setHeight(blockSelectionStartHeight);
         m_currentBlockSelection = nullptr;
@@ -1618,7 +1654,7 @@ void WebPage::selectTextWithGranularityAtPoint(const WebCore::IntPoint& point, u
         if (renderer && renderer->style().preserveNewline())
             m_blockRectForTextSelection = renderer->absoluteBoundingBoxRect(true);
         else {
-            auto paragraphRange = enclosingTextUnitOfGranularity(visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode), ParagraphGranularity, DirectionForward);
+            auto paragraphRange = enclosingTextUnitOfGranularity(visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement), ParagraphGranularity, DirectionForward);
             if (paragraphRange && !paragraphRange->collapsed())
                 m_blockRectForTextSelection = selectionBoxForRange(paragraphRange.get());
         }
@@ -1639,11 +1675,11 @@ void WebPage::beginSelectionInDirection(uint32_t direction, CallbackID callbackI
     send(Messages::WebPageProxy::UnsignedCallback(m_selectionAnchor == Start, callbackID));
 }
 
-void WebPage::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint& point, uint32_t granularity, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
-    RefPtr<Range> newRange = rangeForGranularityAtPoint(frame, point, granularity, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
+    RefPtr<Range> newRange = rangeForGranularityAtPoint(frame, point, granularity, isInteractingWithFocusedElement);
     
     if (position.isNull() || !m_initialSelection || !newRange) {
         send(Messages::WebPageProxy::UnsignedCallback(false, callbackID));
@@ -1668,10 +1704,10 @@ void WebPage::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint&
     send(Messages::WebPageProxy::UnsignedCallback(selectionStart == m_initialSelection->startPosition(), callbackID));
 }
 
-void WebPage::updateSelectionWithExtentPoint(const WebCore::IntPoint& point, bool isInteractingWithAssistedNode, CallbackID callbackID)
+void WebPage::updateSelectionWithExtentPoint(const WebCore::IntPoint& point, bool isInteractingWithFocusedElement, CallbackID callbackID)
 {
     auto& frame = m_page->focusController().focusedOrMainFrame();
-    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithAssistedNode);
+    VisiblePosition position = visiblePositionInFocusedNodeForPoint(frame, point, isInteractingWithFocusedElement);
 
     if (position.isNull()) {
         send(Messages::WebPageProxy::UnsignedCallback(false, callbackID));
@@ -1789,14 +1825,14 @@ void WebPage::replaceDictatedText(const String& oldText, const String& newText)
         position = position.previous();
     if (position.isNull())
         position = startOfDocument(static_cast<Node*>(frame.document()->documentElement()));
-    RefPtr<Range> range = Range::create(*frame.document(), position, frame.selection().selection().start());
+    auto range = Range::create(*frame.document(), position, frame.selection().selection().start());
 
-    if (plainTextReplacingNoBreakSpace(range.get()) != oldText)
+    if (plainTextReplacingNoBreakSpace(range.ptr()) != oldText)
         return;
 
     // We don't want to notify the client that the selection has changed until we are done inserting the new text.
     frame.editor().setIgnoreSelectionChanges(true);
-    frame.selection().setSelectedRange(range.get(), UPSTREAM, WebCore::FrameSelection::ShouldCloseTyping::Yes);
+    frame.selection().setSelectedRange(range.ptr(), UPSTREAM, WebCore::FrameSelection::ShouldCloseTyping::Yes);
     frame.editor().insertText(newText, 0);
     frame.editor().setIgnoreSelectionChanges(false);
 }
@@ -2034,6 +2070,8 @@ static inline bool isAssistableElement(Element& node)
         return true;
     if (is<HTMLTextAreaElement>(node))
         return true;
+    if (is<HTMLImageElement>(node) && downcast<HTMLImageElement>(node).hasEditableImageAttribute())
+        return true;
     if (is<HTMLInputElement>(node)) {
         HTMLInputElement& inputElement = downcast<HTMLInputElement>(node);
         // FIXME: This laundry list of types is not a good way to factor this. Need a suitable function on HTMLInputElement itself.
@@ -2053,15 +2091,15 @@ void WebPage::getPositionInformation(const InteractionInformationRequest& reques
     FloatPoint adjustedPoint;
     Node* hitNode = m_page->mainFrame().nodeRespondingToClickEvents(request.point, adjustedPoint);
 
-    info.nodeAtPositionIsAssistedNode = (hitNode == m_assistedNode);
-    if (m_assistedNode) {
+    info.nodeAtPositionIsFocusedElement = hitNode == m_focusedElement;
+    if (m_focusedElement) {
         const Frame& frame = m_page->focusController().focusedOrMainFrame();
         if (frame.editor().hasComposition()) {
             const uint32_t kHitAreaWidth = 66;
             const uint32_t kHitAreaHeight = 66;
             FrameView& view = *frame.view();
             IntPoint adjustedPoint(view.rootViewToContents(request.point));
-            IntPoint constrainedPoint = m_assistedNode ? constrainPoint(adjustedPoint, frame, *m_assistedNode) : adjustedPoint;
+            IntPoint constrainedPoint = m_focusedElement ? constrainPoint(adjustedPoint, frame, *m_focusedElement) : adjustedPoint;
             VisiblePosition position = frame.visiblePositionForPoint(constrainedPoint);
 
             RefPtr<Range> compositionRange = frame.editor().compositionRange();
@@ -2103,17 +2141,15 @@ void WebPage::getPositionInformation(const InteractionInformationRequest& reques
                     }
 
                     if (request.includeLinkIndicator) {
-                        RefPtr<Range> linkRange = rangeOfContents(*linkElement);
-                        if (linkRange) {
-                            float deviceScaleFactor = corePage()->deviceScaleFactor();
-                            const float marginInPoints = 4;
+                        auto linkRange = rangeOfContents(*linkElement);
+                        float deviceScaleFactor = corePage()->deviceScaleFactor();
+                        const float marginInPoints = 4;
 
-                            RefPtr<TextIndicator> textIndicator = TextIndicator::createWithRange(*linkRange, TextIndicatorOptionTightlyFitContent | TextIndicatorOptionRespectTextColor | TextIndicatorOptionPaintBackgrounds | TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges |
-                                TextIndicatorOptionIncludeMarginIfRangeMatchesSelection, TextIndicatorPresentationTransition::None, FloatSize(marginInPoints * deviceScaleFactor, marginInPoints * deviceScaleFactor));
+                        auto textIndicator = TextIndicator::createWithRange(linkRange.get(), TextIndicatorOptionTightlyFitContent | TextIndicatorOptionRespectTextColor | TextIndicatorOptionPaintBackgrounds | TextIndicatorOptionUseBoundingRectAndPaintAllContentForComplexRanges |
+                            TextIndicatorOptionIncludeMarginIfRangeMatchesSelection, TextIndicatorPresentationTransition::None, FloatSize(marginInPoints * deviceScaleFactor, marginInPoints * deviceScaleFactor));
 
-                            if (textIndicator)
-                                info.linkIndicator = textIndicator->data();
-                        }
+                        if (textIndicator)
+                            info.linkIndicator = textIndicator->data();
                     }
 
 #if ENABLE(DATA_DETECTION)
@@ -2123,7 +2159,7 @@ void WebPage::getPositionInformation(const InteractionInformationRequest& reques
                         info.dataDetectorIdentifier = DataDetection::dataDetectorIdentifier(*element);
                         info.dataDetectorResults = element->document().frame()->dataDetectionResults();
                         if (DataDetection::requiresExtendedContext(*element)) {
-                            RefPtr<Range> linkRange = Range::create(element->document());
+                            auto linkRange = Range::create(element->document());
                             linkRange->selectNodeContents(*element);
                             info.textBefore = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->startPosition(), dataDetectionExtendedContextLength, DirectionBackward).get(), TextIteratorDefaultBehavior, true);
                             info.textAfter = plainTextReplacingNoBreakSpace(rangeExpandedByCharactersInDirectionAtWordBoundary(linkRange->endPosition(), dataDetectionExtendedContextLength, DirectionForward).get(), TextIteratorDefaultBehavior, true);
@@ -2148,7 +2184,7 @@ void WebPage::getPositionInformation(const InteractionInformationRequest& reques
                                     // FIXME: Only select ExtendedColor on images known to need wide gamut
                                     ShareableBitmap::Configuration bitmapConfiguration;
                                     bitmapConfiguration.colorSpace.cgColorSpace = screenColorSpace(m_page->mainFrame().view());
-                                    if (RefPtr<ShareableBitmap> sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), bitmapConfiguration)) {
+                                    if (auto sharedBitmap = ShareableBitmap::createShareable(IntSize(bitmapSize), bitmapConfiguration)) {
                                         auto graphicsContext = sharedBitmap->createGraphicsContext();
                                         graphicsContext->drawImage(*image, FloatRect(0, 0, bitmapSize.width(), bitmapSize.height()));
                                         info.image = sharedBitmap;
@@ -2303,9 +2339,9 @@ static inline Element* nextAssistableElement(Node* startNode, Page& page, bool i
     return nextElement;
 }
 
-void WebPage::focusNextAssistedNode(bool isForward, CallbackID callbackID)
+void WebPage::focusNextFocusedElement(bool isForward, CallbackID callbackID)
 {
-    Element* nextElement = nextAssistableElement(m_assistedNode.get(), *m_page, isForward);
+    Element* nextElement = nextAssistableElement(m_focusedElement.get(), *m_page, isForward);
     m_userIsInteracting = true;
     if (nextElement)
         nextElement->focus();
@@ -2326,38 +2362,29 @@ static IntRect elementRectInRootViewCoordinates(const Node& node, const Frame& f
     return view->contentsToRootView(renderer->absoluteBoundingBoxRect());
 }
 
-void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
+void WebPage::getFocusedElementInformation(FocusedElementInformation& information)
 {
     layoutIfNeeded();
 
-    // FIXME: information.selectionRect should be set to the actual selection rect, but when this is called at focus time
-    // we don't have a selection yet. Using the last interaction location is a reasonable approximation for now.
-    information.selectionRect = IntRect(m_lastInteractionLocation, IntSize(1, 1));
+    information.lastInteractionLocation = m_lastInteractionLocation;
 
-    if (RenderObject* renderer = m_assistedNode->renderer()) {
-        Frame& elementFrame = m_page->focusController().focusedOrMainFrame();
-        information.elementRect = elementRectInRootViewCoordinates(*m_assistedNode, elementFrame);
+    if (auto* renderer = m_focusedElement->renderer()) {
+        auto& elementFrame = m_page->focusController().focusedOrMainFrame();
+        information.elementRect = elementRectInRootViewCoordinates(*m_focusedElement, elementFrame);
         information.nodeFontSize = renderer->style().fontDescription().computedSize();
-        information.elementIsTransparent = renderer->isTransparentRespectingParentFrames();
+        information.elementIsTransparentOrFullyClipped = renderer->isTransparentOrFullyClippedRespectingParentFrames();
 
         bool inFixed = false;
         renderer->localToContainerPoint(FloatPoint(), nullptr, UseTransforms, &inFixed);
         information.insideFixedPosition = inFixed;
         information.isRTL = renderer->style().direction() == TextDirection::RTL;
 
-        FrameView* frameView = elementFrame.view();
+        auto* frameView = elementFrame.view();
         if (inFixed && elementFrame.isMainFrame() && !frameView->frame().settings().visualViewportEnabled()) {
             IntRect currentFixedPositionRect = frameView->customFixedPositionLayoutRect();
             frameView->setCustomFixedPositionLayoutRect(frameView->renderView()->documentRect());
             information.elementRect = frameView->contentsToRootView(renderer->absoluteBoundingBoxRect());
             frameView->setCustomFixedPositionLayoutRect(currentFixedPositionRect);
-            
-            if (!information.elementRect.contains(m_lastInteractionLocation))
-                information.selectionRect.setLocation(information.elementRect.location());
-        } else {
-            // Don't use the selection rect if interaction was outside the element rect.
-            if (!information.elementRect.contains(m_lastInteractionLocation))
-                information.selectionRect = IntRect();
         }
     } else
         information.elementRect = IntRect();
@@ -2367,20 +2394,20 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
     information.maximumScaleFactorIgnoringAlwaysScalable = maximumPageScaleFactorIgnoringAlwaysScalable();
     information.allowsUserScaling = m_viewportConfiguration.allowsUserScaling();
     information.allowsUserScalingIgnoringAlwaysScalable = m_viewportConfiguration.allowsUserScalingIgnoringAlwaysScalable();
-    if (auto* nextElement = nextAssistableElement(m_assistedNode.get(), *m_page, true)) {
+    if (auto* nextElement = nextAssistableElement(m_focusedElement.get(), *m_page, true)) {
         if (auto* frame = nextElement->document().frame())
             information.nextNodeRect = elementRectInRootViewCoordinates(*nextElement, *frame);
         information.hasNextNode = true;
     }
-    if (auto* previousElement = nextAssistableElement(m_assistedNode.get(), *m_page, false)) {
+    if (auto* previousElement = nextAssistableElement(m_focusedElement.get(), *m_page, false)) {
         if (auto* frame = previousElement->document().frame())
             information.previousNodeRect = elementRectInRootViewCoordinates(*previousElement, *frame);
         information.hasPreviousNode = true;
     }
-    information.assistedNodeIdentifier = m_currentAssistedNodeIdentifier;
+    information.focusedElementIdentifier = m_currentFocusedElementIdentifier;
 
-    if (is<LabelableElement>(*m_assistedNode)) {
-        auto labels = downcast<LabelableElement>(*m_assistedNode).labels();
+    if (is<LabelableElement>(*m_focusedElement)) {
+        auto labels = downcast<LabelableElement>(*m_focusedElement).labels();
         Vector<Ref<Element>> associatedLabels;
         for (unsigned index = 0; index < labels->length(); ++index) {
             if (is<Element>(labels->item(index)) && labels->item(index)->renderer())
@@ -2395,14 +2422,11 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
         }
     }
 
-    if (is<Element>(m_assistedNode.get())) {
-        auto& element = downcast<Element>(*m_assistedNode);
-        information.title = element.title();
-        information.ariaLabel = element.attributeWithoutSynchronization(HTMLNames::aria_labelAttr);
-    }
+    information.title = m_focusedElement->title();
+    information.ariaLabel = m_focusedElement->attributeWithoutSynchronization(HTMLNames::aria_labelAttr);
 
-    if (is<HTMLSelectElement>(*m_assistedNode)) {
-        HTMLSelectElement& element = downcast<HTMLSelectElement>(*m_assistedNode);
+    if (is<HTMLSelectElement>(*m_focusedElement)) {
+        HTMLSelectElement& element = downcast<HTMLSelectElement>(*m_focusedElement);
         information.elementType = InputType::Select;
         const Vector<HTMLElement*>& items = element.listItems();
         size_t count = items.size();
@@ -2423,8 +2447,8 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
         }
         information.selectedIndex = element.selectedIndex();
         information.isMultiSelect = element.multiple();
-    } else if (is<HTMLTextAreaElement>(*m_assistedNode)) {
-        HTMLTextAreaElement& element = downcast<HTMLTextAreaElement>(*m_assistedNode);
+    } else if (is<HTMLTextAreaElement>(*m_focusedElement)) {
+        HTMLTextAreaElement& element = downcast<HTMLTextAreaElement>(*m_focusedElement);
         information.autocapitalizeType = element.autocapitalizeType();
         information.isAutocorrect = element.shouldAutocorrect();
         information.elementType = InputType::TextArea;
@@ -2433,14 +2457,14 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
         information.autofillFieldName = WebCore::toAutofillFieldName(element.autofillData().fieldName);
         information.placeholder = element.attributeWithoutSynchronization(HTMLNames::placeholderAttr);
         information.inputMode = element.canonicalInputMode();
-    } else if (is<HTMLInputElement>(*m_assistedNode)) {
-        HTMLInputElement& element = downcast<HTMLInputElement>(*m_assistedNode);
+    } else if (is<HTMLInputElement>(*m_focusedElement)) {
+        HTMLInputElement& element = downcast<HTMLInputElement>(*m_focusedElement);
         HTMLFormElement* form = element.form();
         if (form)
             information.formAction = form->getURLAttribute(WebCore::HTMLNames::actionAttr);
         if (auto autofillElements = WebCore::AutofillElements::computeAutofillElements(element)) {
             information.acceptsAutofilledLoginCredentials = true;
-            information.isAutofillableUsernameField = autofillElements->username() == m_assistedNode;
+            information.isAutofillableUsernameField = autofillElements->username() == m_focusedElement;
         }
         information.representingPageURL = element.document().urlForBindings();
         information.autocapitalizeType = element.autocapitalizeType();
@@ -2498,10 +2522,13 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
         information.value = element.value();
         information.valueAsNumber = element.valueAsNumber();
         information.autofillFieldName = WebCore::toAutofillFieldName(element.autofillData().fieldName);
-    } else if (m_assistedNode->hasEditableStyle()) {
+    } else if (is<HTMLImageElement>(*m_focusedElement) && downcast<HTMLImageElement>(*m_focusedElement).hasEditableImageAttribute()) {
+        information.elementType = InputType::Drawing;
+        information.embeddedViewID = downcast<HTMLImageElement>(*m_focusedElement).editableImageViewID();
+    } else if (m_focusedElement->hasEditableStyle()) {
         information.elementType = InputType::ContentEditable;
-        if (is<HTMLElement>(*m_assistedNode)) {
-            auto& assistedElement = downcast<HTMLElement>(*m_assistedNode);
+        if (is<HTMLElement>(*m_focusedElement)) {
+            auto& assistedElement = downcast<HTMLElement>(*m_focusedElement);
             information.isAutocorrect = assistedElement.shouldAutocorrect();
             information.autocapitalizeType = assistedElement.autocapitalizeType();
             information.inputMode = assistedElement.canonicalInputMode();
@@ -2515,8 +2542,8 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
 
 void WebPage::autofillLoginCredentials(const String& username, const String& password)
 {
-    if (is<HTMLInputElement>(m_assistedNode.get())) {
-        if (auto autofillElements = AutofillElements::computeAutofillElements(downcast<HTMLInputElement>(*m_assistedNode)))
+    if (is<HTMLInputElement>(m_focusedElement.get())) {
+        if (auto autofillElements = AutofillElements::computeAutofillElements(downcast<HTMLInputElement>(*m_focusedElement)))
             autofillElements->autofill(username, password);
     }
 }
@@ -2528,15 +2555,15 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
     return WTF::areEssentiallyEqual(a, b);
 }
 
-void WebPage::setViewportConfigurationViewLayoutSize(const FloatSize& size, double scaleFactor)
+void WebPage::setViewportConfigurationViewLayoutSize(const FloatSize& size, double scaleFactor, double minimumEffectiveDeviceWidth)
 {
-    LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_pageID << " setViewportConfigurationViewLayoutSize " << size << " scaleFactor " << scaleFactor);
+    LOG_WITH_STREAM(VisibleRects, stream << "WebPage " << m_pageID << " setViewportConfigurationViewLayoutSize " << size << " scaleFactor " << scaleFactor << " minimumEffectiveDeviceWidth " << minimumEffectiveDeviceWidth);
 
     ZoomToInitialScale shouldZoomToInitialScale = ZoomToInitialScale::No;
     if (m_viewportConfiguration.layoutSizeScaleFactor() != scaleFactor && areEssentiallyEqualAsFloat(m_viewportConfiguration.initialScale(), pageScaleFactor()))
         shouldZoomToInitialScale = ZoomToInitialScale::Yes;
 
-    if (m_viewportConfiguration.setViewLayoutSize(size, scaleFactor))
+    if (m_viewportConfiguration.setViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth))
         viewportConfigurationChanged(shouldZoomToInitialScale);
 }
 
@@ -2554,7 +2581,7 @@ void WebPage::setDeviceOrientation(int32_t deviceOrientation)
     m_page->mainFrame().orientationChanged();
 }
 
-void WebPage::setOverrideViewportArguments(const std::optional<WebCore::ViewportArguments>& arguments)
+void WebPage::setOverrideViewportArguments(const Optional<WebCore::ViewportArguments>& arguments)
 {
     if (auto* document = m_page->mainFrame().document())
         document->setOverrideViewportArguments(arguments);
@@ -2848,7 +2875,7 @@ void WebPage::applicationDidEnterBackground(bool isSuspendedUnderLock)
     [[NSNotificationCenter defaultCenter] postNotificationName:WebUIApplicationDidEnterBackgroundNotification object:nil userInfo:@{@"isSuspendedUnderLock": [NSNumber numberWithBool:isSuspendedUnderLock]}];
 
     m_isSuspendedUnderLock = isSuspendedUnderLock;
-    setLayerTreeStateIsFrozen(true);
+    freezeLayerTree(LayerTreeFreezeReason::BackgroundApplication);
 
     if (m_page)
         m_page->applicationDidEnterBackground();
@@ -2863,7 +2890,7 @@ void WebPage::applicationWillEnterForeground(bool isSuspendedUnderLock)
 {
     m_isSuspendedUnderLock = false;
     cancelMarkLayersVolatile();
-    setLayerTreeStateIsFrozen(false);
+    unfreezeLayerTree(LayerTreeFreezeReason::BackgroundApplication);
 
     [[NSNotificationCenter defaultCenter] postNotificationName:WebUIApplicationWillEnterForegroundNotification object:nil userInfo:@{@"isSuspendedUnderLock": @(isSuspendedUnderLock)}];
 
@@ -2889,11 +2916,11 @@ static inline void adjustVelocityDataForBoundedScale(double& horizontalVelocity,
         scaleChangeRate = 0;
 }
 
-std::optional<float> WebPage::scaleFromUIProcess(const VisibleContentRectUpdateInfo& visibleContentRectUpdateInfo) const
+Optional<float> WebPage::scaleFromUIProcess(const VisibleContentRectUpdateInfo& visibleContentRectUpdateInfo) const
 {
     auto transactionIDForLastScaleFromUIProcess = visibleContentRectUpdateInfo.lastLayerTreeTransactionID();
     if (m_lastTransactionIDWithScaleChange > transactionIDForLastScaleFromUIProcess)
-        return std::nullopt;
+        return WTF::nullopt;
 
     float scaleFromUIProcess = visibleContentRectUpdateInfo.scale();
     float currentScale = m_page->pageScaleFactor();
@@ -2907,7 +2934,7 @@ std::optional<float> WebPage::scaleFromUIProcess(const VisibleContentRectUpdateI
     
     scaleFromUIProcess = std::min<float>(m_viewportConfiguration.maximumScale(), std::max<float>(m_viewportConfiguration.minimumScale(), scaleFromUIProcess));
     if (areEssentiallyEqualAsFloat(currentScale, scaleFromUIProcess))
-        return std::nullopt;
+        return WTF::nullopt;
 
     return scaleFromUIProcess;
 }
@@ -2956,7 +2983,7 @@ void WebPage::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visi
             m_oldestNonStableUpdateVisibleContentRectsTimestamp = oldestTimestamp;
     }
 
-    float scaleToUse = scaleFromUIProcess.value_or(m_page->pageScaleFactor());
+    float scaleToUse = scaleFromUIProcess.valueOr(m_page->pageScaleFactor());
     FloatRect exposedContentRect = visibleContentRectUpdateInfo.exposedContentRect();
     FloatRect adjustedExposedContentRect = adjustExposedRectForNewScale(exposedContentRect, visibleContentRectUpdateInfo.scale(), scaleToUse);
     m_drawingArea->setExposedContentRect(adjustedExposedContentRect);
@@ -3005,7 +3032,7 @@ void WebPage::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visi
             if (visibleContentRectUpdateInfo.unobscuredContentRect() != visibleContentRectUpdateInfo.unobscuredContentRectRespectingInputViewBounds())
                 frameView.setVisualViewportOverrideRect(LayoutRect(visibleContentRectUpdateInfo.unobscuredContentRectRespectingInputViewBounds()));
             else
-                frameView.setVisualViewportOverrideRect(std::nullopt);
+                frameView.setVisualViewportOverrideRect(WTF::nullopt);
 
             LOG_WITH_STREAM(VisibleRects, stream << "WebPage::updateVisibleContentRects - setLayoutViewportOverrideRect " << visibleContentRectUpdateInfo.customFixedPositionRect());
             frameView.setLayoutViewportOverrideRect(LayoutRect(visibleContentRectUpdateInfo.customFixedPositionRect()));
@@ -3095,6 +3122,11 @@ void WebPage::hardwareKeyboardAvailabilityChanged()
         focusedFrame->eventHandler().capsLockStateMayHaveChanged();
 }
 
+void WebPage::updateStringForFind(const String& findString)
+{
+    send(Messages::WebPageProxy::UpdateStringForFind(findString));
+}
+
 #if USE(QUICK_LOOK)
 void WebPage::didReceivePasswordForQuickLookDocument(const String& password)
 {