[meta][WebKit] Remove using namespace WebCore and WebKit in the global scope for...
[WebKit-https.git] / Source / WebKit / UIProcess / ios / WKContentViewInteraction.mm
index 603af17..026f1f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #import "config.h"
 #import "WKContentViewInteraction.h"
 
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
 
 #import "APIUIClient.h"
+#import "EditableImageController.h"
 #import "EditingRange.h"
 #import "InputViewUpdateDeferrer.h"
 #import "Logging.h"
@@ -46,6 +47,7 @@
 #import "WKFormInputControl.h"
 #import "WKFormSelectControl.h"
 #import "WKImagePreviewViewController.h"
+#import "WKInkPickerControl.h"
 #import "WKInspectorNodeSearchGestureRecognizer.h"
 #import "WKNSURLExtras.h"
 #import "WKPreviewActionItemIdentifiers.h"
@@ -56,6 +58,7 @@
 #import "WKTextInputListViewController.h"
 #import "WKTimePickerViewController.h"
 #import "WKUIDelegatePrivate.h"
+#import "WKWebEvent.h"
 #import "WKWebViewConfiguration.h"
 #import "WKWebViewConfigurationPrivate.h"
 #import "WKWebViewInternal.h"
@@ -75,6 +78,7 @@
 #import <WebCore/Color.h>
 #import <WebCore/DataDetection.h>
 #import <WebCore/FloatQuad.h>
+#import <WebCore/FontAttributeChanges.h>
 #import <WebCore/InputMode.h>
 #import <WebCore/LocalizedStrings.h>
 #import <WebCore/NotImplemented.h>
@@ -87,8 +91,8 @@
 #import <WebCore/ShareData.h>
 #import <WebCore/TextIndicator.h>
 #import <WebCore/VisibleSelection.h>
-#import <WebCore/WebCoreNSURLExtras.h>
 #import <WebCore/WebEvent.h>
+#import <WebCore/WritingDirection.h>
 #import <WebKit/WebSelectionRect.h> // FIXME: WK2 should not include WebKit headers!
 #import <pal/spi/cg/CoreGraphicsSPI.h>
 #import <pal/spi/cocoa/DataDetectorsCoreSPI.h>
 #import <wtf/SetForScope.h>
 #import <wtf/SoftLinking.h>
 #import <wtf/WeakObjCPtr.h>
+#import <wtf/cocoa/NSURLExtras.h>
 #import <wtf/text/TextStream.h>
 
 #if ENABLE(DRAG_SUPPORT)
 #if PLATFORM(IOSMAC)
 #import "NativeWebMouseEvent.h"
 #import <UIKit/UIHoverGestureRecognizer.h>
+#import <UIKit/_UILookupGestureRecognizer.h>
 #import <pal/spi/ios/GraphicsServicesSPI.h>
 #endif
 
 #import "WKFormColorControl.h"
 #endif
 
-@interface UIEvent(UIEventInternal)
-@property (nonatomic, assign) UIKeyboardInputFlags _inputFlags;
-@end
-
-@interface WKWebEvent : WebEvent
-@property (nonatomic, retain) UIEvent *uiEvent;
-@end
-
-@implementation WKWebEvent
+#if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/WKPlatformFileUploadPanel.mm>)
+#import <WebKitAdditions/WKPlatformFileUploadPanel.mm>
+#endif
 
-- (void)dealloc
-{
-    [_uiEvent release];
-    [super dealloc];
-}
+#if PLATFORM(WATCHOS)
 
+@interface WKContentView (WatchSupport) <WKFocusedFormControlViewDelegate, WKSelectMenuListViewControllerDelegate, WKTextInputListViewControllerDelegate>
 @end
 
-#if PLATFORM(WATCHOS)
+#endif
 
-@interface WKContentView (WatchSupport) <WKFocusedFormControlViewDelegate, WKSelectMenuListViewControllerDelegate, WKTextInputListViewControllerDelegate>
+#if PLATFORM(IOS_FAMILY)
+
+@interface UIKeyboardImpl (Staging)
+- (BOOL)handleKeyCommandForCurrentEvent;
 @end
 
 #endif
 
+namespace WebKit {
 using namespace WebCore;
 using namespace WebKit;
 
-namespace WebKit {
-
 WKSelectionDrawingInfo::WKSelectionDrawingInfo()
     : type(SelectionType::None)
 {
@@ -282,13 +281,14 @@ const CGFloat minimumTapHighlightRadius = 2.0;
 @protocol UISelectionInteractionAssistant;
 
 @interface WKFocusedElementInfo : NSObject <_WKFocusedElementInfo>
-- (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject;
+- (instancetype)initWithAssistedNodeInformation:(const WebKit::AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject;
 @end
 
 @implementation WKFormInputSession {
     WeakObjCPtr<WKContentView> _contentView;
     RetainPtr<WKFocusedElementInfo> _focusedElementInfo;
     RetainPtr<UIView> _customInputView;
+    RetainPtr<UIView> _customInputAccessoryView;
     RetainPtr<NSArray<UITextSuggestion *>> _suggestions;
     BOOL _accessoryViewShouldNotShow;
     BOOL _forceSecureTextEntry;
@@ -379,6 +379,20 @@ const CGFloat minimumTapHighlightRadius = 2.0;
     [_contentView reloadInputViews];
 }
 
+- (UIView *)customInputAccessoryView
+{
+    return _customInputAccessoryView.get();
+}
+
+- (void)setCustomInputAccessoryView:(UIView *)customInputAccessoryView
+{
+    if (_customInputAccessoryView == customInputAccessoryView)
+        return;
+
+    _customInputAccessoryView = customInputAccessoryView;
+    [_contentView reloadInputViews];
+}
+
 - (void)endEditing
 {
     if ([_customInputView conformsToProtocol:@protocol(WKFormControl)])
@@ -392,15 +406,11 @@ const CGFloat minimumTapHighlightRadius = 2.0;
 
 - (void)setSuggestions:(NSArray<UITextSuggestion *> *)suggestions
 {
-    // Suggestions that come from a <datalist> should not be overwritten by other clients.
-#if ENABLE(DATALIST_ELEMENT)
-    if ([_contentView assistedNodeInformation].hasSuggestions && ![suggestions.firstObject isKindOfClass:[WKDataListTextSuggestion class]])
+    if (suggestions == _suggestions || [suggestions isEqualToArray:_suggestions.get()])
         return;
-#endif
 
-    id <UITextInputSuggestionDelegate> suggestionDelegate = (id <UITextInputSuggestionDelegate>)[_contentView inputDelegate];
     _suggestions = adoptNS([suggestions copy]);
-    [suggestionDelegate setSuggestions:suggestions];
+    [_contentView updateTextSuggestionsForInputDelegate];
 }
 
 - (BOOL)requiresStrongPasswordAssistance
@@ -431,7 +441,7 @@ const CGFloat minimumTapHighlightRadius = 2.0;
     RetainPtr<NSString> _label;
 }
 
-- (instancetype)initWithAssistedNodeInformation:(const AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject
+- (instancetype)initWithAssistedNodeInformation:(const WebKit::AssistedNodeInformation&)information isUserInitiated:(BOOL)isUserInitiated userObject:(NSObject <NSSecureCoding> *)userObject
 {
     if (!(self = [super init]))
         return nil;
@@ -488,6 +498,9 @@ const CGFloat minimumTapHighlightRadius = 2.0;
     case WebKit::InputType::Select:
         _type = WKInputTypeSelect;
         break;
+    case WebKit::InputType::Drawing:
+        _type = WKInputTypeDrawing;
+        break;
 #if ENABLE(INPUT_TYPE_COLOR)
     case WebKit::InputType::Color:
         _type = WKInputTypeColor;
@@ -598,7 +611,7 @@ static WKDragSessionContext *ensureLocalDragSessionContext(id <UIDragSession> se
 
 static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeInformation)
 {
-    return (assistedNodeInformation.elementType != InputType::None);
+    return (assistedNodeInformation.elementType != WebKit::InputType::None);
 }
 
 - (WKFormInputSession *)_formInputSession
@@ -626,6 +639,9 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
 
 - (void)setupInteraction
 {
+    if (_hasSetUpInteractions)
+        return;
+
     if (!_interactionViewsContainerView) {
         _interactionViewsContainerView = adoptNS([[UIView alloc] init]);
         [_interactionViewsContainerView layer].name = @"InteractionViewsContainer";
@@ -634,7 +650,8 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
         [self.superview addSubview:_interactionViewsContainerView.get()];
     }
 
-    _keyboardScrollingAnimator = adoptNS([[WKKeyboardScrollingAnimator alloc] initWithScrollable:self]);
+    _keyboardScrollingAnimator = adoptNS([[WKKeyboardScrollViewAnimator alloc] initWithScrollView:_webView.scrollView]);
+    [_keyboardScrollingAnimator setDelegate:self];
 
     [self.layer addObserver:self forKeyPath:@"transform" options:NSKeyValueObservingOptionInitial context:nil];
 
@@ -646,6 +663,11 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     _hoverGestureRecognizer = adoptNS([[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(_hoverGestureRecognizerChanged:)]);
     [_hoverGestureRecognizer setDelegate:self];
     [self addGestureRecognizer:_hoverGestureRecognizer.get()];
+    
+    _lookupGestureRecognizer = adoptNS([[_UILookupGestureRecognizer alloc] initWithTarget:self action:@selector(_lookupGestureRecognized:)]);
+    [_lookupGestureRecognizer setDelegate:self];
+    [self addGestureRecognizer:_lookupGestureRecognizer.get()];
+    
 #endif
 
     _singleTapGestureRecognizer = adoptNS([[WKSyntheticClickTapGestureRecognizer alloc] initWithTarget:self action:@selector(_singleTapCommited:)]);
@@ -688,6 +710,12 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     [_twoFingerSingleTapGestureRecognizer setDelegate:self];
     [self addGestureRecognizer:_twoFingerSingleTapGestureRecognizer.get()];
 
+    _stylusSingleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_stylusSingleTapRecognized:)]);
+    [_stylusSingleTapGestureRecognizer setNumberOfTapsRequired:1];
+    [_stylusSingleTapGestureRecognizer setDelegate:self];
+    [_stylusSingleTapGestureRecognizer setAllowedTouchTypes:@[ @(UITouchTypePencil) ]];
+    [self addGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
+
 #if HAVE(LINK_PREVIEW)
     [self _registerPreview];
 #endif
@@ -696,11 +724,11 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     _showingTextStyleOptions = NO;
 
     // FIXME: This should be called when we get notified that loading has completed.
-    [self useSelectionAssistantWithGranularity:_webView._selectionGranularity];
+    [self setUpTextSelectionAssistant];
     
     _actionSheetAssistant = adoptNS([[WKActionSheetAssistant alloc] initWithView:self]);
     [_actionSheetAssistant setDelegate:self];
-    _smartMagnificationController = std::make_unique<SmartMagnificationController>(self);
+    _smartMagnificationController = std::make_unique<WebKit::SmartMagnificationController>(self);
     _isExpectingFastSingleTapCommit = NO;
     _potentialTapInProgress = NO;
     _isDoubleTapPending = NO;
@@ -708,11 +736,20 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     _needsDeferredEndScrollingSelectionUpdate = NO;
     _isChangingFocus = NO;
     _isBlurringFocusedNode = NO;
+
+#if ENABLE(DATALIST_ELEMENT)
+    _dataListTextSuggestionsInputView = nil;
+    _dataListTextSuggestions = nil;
+#endif
+
+    _hasSetUpInteractions = YES;
 }
 
 - (void)cleanupInteraction
 {
-    _webSelectionAssistant = nil;
+    if (!_hasSetUpInteractions)
+        return;
+
     _textSelectionAssistant = nil;
     
     [_actionSheetAssistant cleanupSheet];
@@ -741,6 +778,9 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
 #if PLATFORM(IOSMAC)
     [_hoverGestureRecognizer setDelegate:nil];
     [self removeGestureRecognizer:_hoverGestureRecognizer.get()];
+    
+    [_lookupGestureRecognizer setDelegate:nil];
+    [self removeGestureRecognizer:_lookupGestureRecognizer.get()];
 #endif
 
     [_singleTapGestureRecognizer setDelegate:nil];
@@ -766,6 +806,9 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     [_twoFingerSingleTapGestureRecognizer setDelegate:nil];
     [self removeGestureRecognizer:_twoFingerSingleTapGestureRecognizer.get()];
 
+    [_stylusSingleTapGestureRecognizer setDelegate:nil];
+    [self removeGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
+
     _layerTreeTransactionIdAtLastTouchStart = 0;
 
 #if ENABLE(DATA_INTERACTION)
@@ -803,6 +846,14 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     
     [_keyboardScrollingAnimator invalidate];
     _keyboardScrollingAnimator = nil;
+
+#if ENABLE(DATALIST_ELEMENT)
+    _dataListTextSuggestionsInputView = nil;
+    _dataListTextSuggestions = nil;
+#endif
+
+    _hasSetUpInteractions = NO;
+    _suppressSelectionAssistantReasons = { };
 }
 
 - (void)_removeDefaultGestureRecognizers
@@ -814,8 +865,10 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     [self removeGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
     [self removeGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
     [self removeGestureRecognizer:_twoFingerSingleTapGestureRecognizer.get()];
+    [self removeGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
 #if PLATFORM(IOSMAC)
     [self removeGestureRecognizer:_hoverGestureRecognizer.get()];
+    [self removeGestureRecognizer:_lookupGestureRecognizer.get()];
 #endif
 }
 
@@ -828,8 +881,10 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     [self addGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
     [self addGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
     [self addGestureRecognizer:_twoFingerSingleTapGestureRecognizer.get()];
+    [self addGestureRecognizer:_stylusSingleTapGestureRecognizer.get()];
 #if PLATFORM(IOSMAC)
     [self addGestureRecognizer:_hoverGestureRecognizer.get()];
+    [self addGestureRecognizer:_lookupGestureRecognizer.get()];
 #endif
 }
 
@@ -921,7 +976,7 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     return [super hitTest:point withEvent:event];
 }
 
-- (const InteractionInformationAtPosition&)positionInformation
+- (const WebKit::InteractionInformationAtPosition&)positionInformation
 {
     return _positionInformation;
 }
@@ -964,6 +1019,15 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     return YES;
 }
 
+- (void)_endEditing
+{
+    [_inputPeripheral endEditing];
+    [_formInputSession endEditing];
+#if ENABLE(DATALIST_ELEMENT)
+    [_dataListTextSuggestionsInputView controlEndEditing];
+#endif
+}
+
 - (BOOL)canBecomeFirstResponder
 {
     return _becomingFirstResponder;
@@ -994,6 +1058,9 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
         didBecomeFirstResponder = [super becomeFirstResponder];
     }
 
+    if (didBecomeFirstResponder)
+        _page->activityStateDidChange(WebCore::ActivityState::IsFocused);
+
     if (didBecomeFirstResponder && [self canShowNonEmptySelectionView])
         [_textSelectionAssistant activateSelection];
 
@@ -1013,20 +1080,20 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     _resigningFirstResponder = YES;
     if (!_webView._retainingActiveFocusedState) {
         // We need to complete the editing operation before we blur the element.
-        [_inputPeripheral endEditing];
-        [_formInputSession endEditing];
-
+        [self _endEditing];
         _page->blurAssistedNode();
     }
 
     [self _cancelInteraction];
-    [_webSelectionAssistant resignedFirstResponder];
     [_textSelectionAssistant deactivateSelection];
     
     _inputViewUpdateDeferrer = nullptr;
 
     bool superDidResign = [super resignFirstResponder];
 
+    if (superDidResign)
+        _page->activityStateDidChange(WebCore::ActivityState::IsFocused);
+
     _resigningFirstResponder = NO;
 
     return superDidResign;
@@ -1041,10 +1108,10 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
 
     _lastInteractionLocation = lastTouchEvent->locationInDocumentCoordinates;
     if (lastTouchEvent->type == UIWebTouchEventTouchBegin)
-        _layerTreeTransactionIdAtLastTouchStart = downcast<RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID();
+        _layerTreeTransactionIdAtLastTouchStart = downcast<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page->drawingArea()).lastCommittedLayerTreeTransactionID();
 
 #if ENABLE(TOUCH_EVENTS)
-    NativeWebTouchEvent nativeWebTouchEvent(lastTouchEvent);
+    WebKit::NativeWebTouchEvent nativeWebTouchEvent(lastTouchEvent);
     nativeWebTouchEvent.setCanPreventNativeGestures(!_canSendTouchEventsAsynchronously || [gestureRecognizer isDefaultPrevented]);
 
     if (_canSendTouchEventsAsynchronously)
@@ -1077,7 +1144,7 @@ static inline bool hasAssistedNode(WebKit::AssistedNodeInformation assistedNodeI
     }
 }
 
-static FloatQuad inflateQuad(const FloatQuad& quad, float inflateSize)
+static WebCore::FloatQuad inflateQuad(const WebCore::FloatQuad& quad, float inflateSize)
 {
     // We sort the output points like this (as expected by the highlight view):
     //  p2------p3
@@ -1085,7 +1152,7 @@ static FloatQuad inflateQuad(const FloatQuad& quad, float inflateSize)
     //  p1------p4
 
     // 1) Sort the points horizontally.
-    FloatPoint points[4] = { quad.p1(), quad.p4(), quad.p2(), quad.p3() };
+    WebCore::FloatPoint points[4] = { quad.p1(), quad.p4(), quad.p2(), quad.p3() };
     if (points[0].x() > points[1].x())
         std::swap(points[0], points[1]);
     if (points[2].x() > points[3].x())
@@ -1111,7 +1178,7 @@ static FloatQuad inflateQuad(const FloatQuad& quad, float inflateSize)
     points[2].move(inflateSize, -inflateSize);
     points[3].move(inflateSize, inflateSize);
 
-    return FloatQuad(points[1], points[0], points[2], points[3]);
+    return WebCore::FloatQuad(points[1], points[0], points[2], points[3]);
 }
 
 #if ENABLE(TOUCH_EVENTS)
@@ -1126,16 +1193,6 @@ static FloatQuad inflateQuad(const FloatQuad& quad, float inflateSize)
 }
 #endif
 
-static inline bool highlightedQuadsAreSmallerThanRect(const Vector<FloatQuad>& quads, const FloatRect& rect)
-{
-    for (size_t i = 0; i < quads.size(); ++i) {
-        FloatRect boundingBox = quads[i].boundingBox();
-        if (boundingBox.width() > rect.width() || boundingBox.height() > rect.height())
-            return false;
-    }
-    return true;
-}
-
 static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius, CGFloat borderRadiusScale)
 {
     return [NSValue valueWithCGSize:CGSizeMake((borderRadius.width() * borderRadiusScale) + minimumTapHighlightRadius, (borderRadius.height() * borderRadiusScale) + minimumTapHighlightRadius)];
@@ -1158,9 +1215,9 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
     const size_t quadCount = highlightedQuads.size();
     RetainPtr<NSMutableArray> rects = adoptNS([[NSMutableArray alloc] initWithCapacity:static_cast<const NSUInteger>(quadCount)]);
     for (size_t i = 0; i < quadCount; ++i) {
-        const FloatQuad& quad = highlightedQuads[i];
+        const WebCore::FloatQuad& quad = highlightedQuads[i];
         if (quad.isRectilinear()) {
-            FloatRect boundingBox = quad.boundingBox();
+            WebCore::FloatRect boundingBox = quad.boundingBox();
             boundingBox.scale(selfScale);
             boundingBox.inflate(minimumTapHighlightRadius);
             CGRect pixelAlignedRect = static_cast<CGRect>(encloseRectToDevicePixels(boundingBox, deviceScaleFactor));
@@ -1177,9 +1234,9 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
     else {
         RetainPtr<NSMutableArray> quads = adoptNS([[NSMutableArray alloc] initWithCapacity:static_cast<const NSUInteger>(quadCount)]);
         for (size_t i = 0; i < quadCount; ++i) {
-            FloatQuad quad = highlightedQuads[i];
+            WebCore::FloatQuad quad = highlightedQuads[i];
             quad.scale(selfScale);
-            FloatQuad extendedQuad = inflateQuad(quad, minimumTapHighlightRadius);
+            WebCore::FloatQuad extendedQuad = inflateQuad(quad, minimumTapHighlightRadius);
             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p1()]];
             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p2()]];
             [quads addObject:[NSValue valueWithCGPoint:extendedQuad.p3()]];
@@ -1198,7 +1255,19 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
 
 - (void)_showTapHighlight
 {
-    if (!highlightedQuadsAreSmallerThanRect(_tapHighlightInformation.quads, _page->unobscuredContentRect()) && !_showDebugTapHighlightsForFastClicking)
+    auto shouldPaintTapHighlight = [&](const WebCore::FloatRect& rect) {
+        static const float highlightPaintThreshold = 0.3; // 30%
+        float highlightArea = 0;
+        for (auto highlightQuad : _tapHighlightInformation.quads) {
+            auto boundingBox = highlightQuad.boundingBox();
+            highlightArea += boundingBox.area(); 
+            if (boundingBox.width() > (rect.width() * highlightPaintThreshold) || boundingBox.height() > (rect.height() * highlightPaintThreshold))
+                return false;
+        }
+        return highlightArea < rect.area() * highlightPaintThreshold;
+    };
+
+    if (!shouldPaintTapHighlight(_page->unobscuredContentRect()) && !_showDebugTapHighlightsForFastClicking)
         return;
 
     if (!_highlightView) {
@@ -1271,7 +1340,6 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
 
 - (void)_scrollingNodeScrollingWillBegin
 {
-    [_webSelectionAssistant willStartScrollingOverflow];
     [_textSelectionAssistant willStartScrollingOverflow];    
 }
 
@@ -1284,7 +1352,6 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
         return;
     }
     [self _updateChangedSelection];
-    [_webSelectionAssistant didEndScrollingOverflow];
     [_textSelectionAssistant didEndScrollingOverflow];
 }
 
@@ -1292,18 +1359,19 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
 {
     // FIXME: We should add the logic to handle keyboard visibility during focus redirects.
     switch (_assistedNodeInformation.elementType) {
-    case InputType::None:
+    case WebKit::InputType::None:
         return NO;
-    case InputType::Select:
+    case WebKit::InputType::Select:
 #if ENABLE(INPUT_TYPE_COLOR)
-    case InputType::Color:
+    case WebKit::InputType::Color:
 #endif
+    case WebKit::InputType::Date:
+    case WebKit::InputType::Month:
+    case WebKit::InputType::DateTimeLocal:
+    case WebKit::InputType::Time:
         return !currentUserInterfaceIdiomIsPad();
-    case InputType::Date:
-    case InputType::Month:
-    case InputType::DateTimeLocal:
-    case InputType::Time:
-        return !currentUserInterfaceIdiomIsPad();
+    case WebKit::InputType::Drawing:
+        return YES;
     default:
         return !_assistedNodeInformation.isReadOnly;
     }
@@ -1317,16 +1385,18 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
 
 - (void)_displayFormNodeInputView
 {
-    // In case user scaling is force enabled, do not use that scaling when zooming in with an input field.
-    // Zooming above the page's default scale factor should only happen when the user performs it.
-    [self _zoomToFocusRect:_assistedNodeInformation.elementRect
-        selectionRect:_didAccessoryTabInitiateFocus ? IntRect() : _assistedNodeInformation.selectionRect
-        insideFixed:_assistedNodeInformation.insideFixedPosition
-        fontSize:_assistedNodeInformation.nodeFontSize
-        minimumScale:_assistedNodeInformation.minimumScaleFactor
-        maximumScale:_assistedNodeInformation.maximumScaleFactorIgnoringAlwaysScalable
-        allowScaling:_assistedNodeInformation.allowsUserScalingIgnoringAlwaysScalable && !currentUserInterfaceIdiomIsPad()
-        forceScroll:(_assistedNodeInformation.inputMode == InputMode::None) ? !currentUserInterfaceIdiomIsPad() : [self requiresAccessoryView]];
+    if (!_suppressSelectionAssistantReasons.contains(WebKit::FocusedElementIsTransparent)) {
+        // In case user scaling is force enabled, do not use that scaling when zooming in with an input field.
+        // Zooming above the page's default scale factor should only happen when the user performs it.
+        [self _zoomToFocusRect:_assistedNodeInformation.elementRect
+            selectionRect:_didAccessoryTabInitiateFocus ? WebCore::IntRect() : _assistedNodeInformation.selectionRect
+            insideFixed:_assistedNodeInformation.insideFixedPosition
+            fontSize:_assistedNodeInformation.nodeFontSize
+            minimumScale:_assistedNodeInformation.minimumScaleFactor
+            maximumScale:_assistedNodeInformation.maximumScaleFactorIgnoringAlwaysScalable
+            allowScaling:_assistedNodeInformation.allowsUserScalingIgnoringAlwaysScalable && !currentUserInterfaceIdiomIsPad()
+            forceScroll:(_assistedNodeInformation.inputMode == WebCore::InputMode::None) ? !currentUserInterfaceIdiomIsPad() : [self requiresAccessoryView]];
+    }
 
     _didAccessoryTabInitiateFocus = NO;
     [self _ensureFormAccessoryView];
@@ -1338,19 +1408,27 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
     if (!hasAssistedNode(_assistedNodeInformation))
         return nil;
 
-    if (_assistedNodeInformation.inputMode == InputMode::None)
+    if (_assistedNodeInformation.inputMode == WebCore::InputMode::None)
         return [[UIView new] autorelease];
 
     if (!_inputPeripheral) {
         switch (_assistedNodeInformation.elementType) {
-        case InputType::Select:
+        case WebKit::InputType::Select:
             _inputPeripheral = adoptNS([[WKFormSelectControl alloc] initWithView:self]);
             break;
 #if ENABLE(INPUT_TYPE_COLOR)
-        case InputType::Color:
+        case WebKit::InputType::Color:
             _inputPeripheral = adoptNS([[WKFormColorControl alloc] initWithView:self]);
             break;
 #endif
+        case WebKit::InputType::Drawing:
+#if HAVE(PENCILKIT)
+            _inputPeripheral = adoptNS([[WKInkPickerControl alloc] initWithDrawingView:_page->editableImageController().editableImage(_assistedNodeInformation.embeddedViewID)->drawingView.get()]);
+            break;
+#else
+            ASSERT_NOT_REACHED();
+            return [[UIView new] autorelease];
+#endif
         default:
             _inputPeripheral = adoptNS([[WKFormInputControl alloc] initWithView:self]);
             break;
@@ -1358,7 +1436,15 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
     } else
         [self _displayFormNodeInputView];
 
-    return [_formInputSession customInputView] ?: [_inputPeripheral assistantView];
+    if (UIView *customInputView = [_formInputSession customInputView])
+        return customInputView;
+
+#if ENABLE(DATALIST_ELEMENT)
+    if (_dataListTextSuggestionsInputView)
+        return _dataListTextSuggestionsInputView.get();
+#endif
+
+    return [_inputPeripheral assistantView];
 }
 
 - (CGRect)_selectionClipRect
@@ -1388,7 +1474,7 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
         return YES;
 #endif
     
-    if ((preventingGestureRecognizer == _textSelectionAssistant.get().loupeGesture || isForcePressGesture || [_webSelectionAssistant isSelectionGestureRecognizer:preventingGestureRecognizer]) && (preventedGestureRecognizer == _highlightLongPressGestureRecognizer || preventedGestureRecognizer == _longPressGestureRecognizer))
+    if ((preventingGestureRecognizer == _textSelectionAssistant.get().loupeGesture || isForcePressGesture) && (preventedGestureRecognizer == _highlightLongPressGestureRecognizer || preventedGestureRecognizer == _longPressGestureRecognizer))
         return NO;
 
     return YES;
@@ -1404,8 +1490,6 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _longPressGestureRecognizer.get()))
         return YES;
 
-    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _webSelectionAssistant.get().selectionLongPressRecognizer))
-        return YES;
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
 #if PLATFORM(IOSMAC)
     if (isSamePair(gestureRecognizer, otherGestureRecognizer, _textSelectionAssistant.get().loupeGesture, _textSelectionAssistant.get().forcePressGesture))
@@ -1416,6 +1500,10 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 
     if ([gestureRecognizer isKindOfClass:[UIHoverGestureRecognizer class]] || [otherGestureRecognizer isKindOfClass:[UIHoverGestureRecognizer class]])
         return YES;
+    
+    if (([gestureRecognizer isKindOfClass:[_UILookupGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) || ([otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] && [gestureRecognizer isKindOfClass:[_UILookupGestureRecognizer class]]))
+        return YES;
+
 #endif
     if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _textSelectionAssistant.get().forcePressGesture))
         return YES;
@@ -1471,7 +1559,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     [_actionSheetAssistant showDataDetectorsSheet];
 }
 
-- (SEL)_actionForLongPressFromPositionInformation:(const InteractionInformationAtPosition&)positionInformation
+- (SEL)_actionForLongPressFromPositionInformation:(const WebKit::InteractionInformationAtPosition&)positionInformation
 {
     if (!_webView.configuration._longPressActionsEnabled)
         return nil;
@@ -1484,7 +1572,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 
     if (positionInformation.isLink) {
 #if ENABLE(DATA_DETECTION)
-        if (DataDetection::canBePresentedByDataDetectors(positionInformation.url))
+        if (WebCore::DataDetection::canBePresentedByDataDetectors(positionInformation.url))
             return @selector(_showDataDetectorsSheet);
 #endif
         return @selector(_showLinkSheet);
@@ -1500,12 +1588,12 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     return [self _actionForLongPressFromPositionInformation:_positionInformation];
 }
 
-- (InteractionInformationAtPosition)currentPositionInformation
+- (WebKit::InteractionInformationAtPosition)currentPositionInformation
 {
     return _positionInformation;
 }
 
-- (void)doAfterPositionInformationUpdate:(void (^)(InteractionInformationAtPosition))action forRequest:(InteractionInformationRequest)request
+- (void)doAfterPositionInformationUpdate:(void (^)(WebKit::InteractionInformationAtPosition))action forRequest:(WebKit::InteractionInformationRequest)request
 {
     if ([self _currentPositionInformationIsValidForRequest:request]) {
         // If the most recent position information is already valid, invoke the given action block immediately.
@@ -1550,17 +1638,17 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     _page->requestPositionInformation(request);
 }
 
-- (BOOL)_currentPositionInformationIsValidForRequest:(const InteractionInformationRequest&)request
+- (BOOL)_currentPositionInformationIsValidForRequest:(const WebKit::InteractionInformationRequest&)request
 {
     return _hasValidPositionInformation && _positionInformation.request.isValidForRequest(request);
 }
 
-- (BOOL)_hasValidOutstandingPositionInformationRequest:(const InteractionInformationRequest&)request
+- (BOOL)_hasValidOutstandingPositionInformationRequest:(const WebKit::InteractionInformationRequest&)request
 {
     return _outstandingPositionInformationRequest && _outstandingPositionInformationRequest->isValidForRequest(request);
 }
 
-- (BOOL)_currentPositionInformationIsApproximatelyValidForRequest:(const InteractionInformationRequest&)request
+- (BOOL)_currentPositionInformationIsApproximatelyValidForRequest:(const WebKit::InteractionInformationRequest&)request
 {
     return _hasValidPositionInformation && _positionInformation.request.isApproximatelyValidForRequest(request);
 }
@@ -1609,9 +1697,6 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (_textSelectionAssistant) {
         for (WKTextSelectionRect *selectionRect in [_textSelectionAssistant valueForKeyPath:@"selectionView.selection.selectionRects"])
             [textSelectionRects addObject:[NSValue valueWithCGRect:selectionRect.webRect.rect]];
-    } else if (_webSelectionAssistant) {
-        for (WebSelectionRect *selectionRect in [_webSelectionAssistant valueForKeyPath:@"selectionView.selectionRects"])
-            [textSelectionRects addObject:[NSValue valueWithCGRect:selectionRect.rect]];
     }
 
     return textSelectionRects;
@@ -1629,7 +1714,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
         if (hasAssistedNode(_assistedNodeInformation)) {
             // Request information about the position with sync message.
             // If the assisted node is the same, prevent the gesture.
-            if (![self ensurePositionInformationIsUpToDate:InteractionInformationRequest(roundedIntPoint(point))])
+            if (![self ensurePositionInformationIsUpToDate:WebKit::InteractionInformationRequest(WebCore::roundedIntPoint(point))])
                 return NO;
             if (_positionInformation.nodeAtPositionIsAssistedNode)
                 return NO;
@@ -1648,7 +1733,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
         // We still have no idea about what is at the location.
         // Send an async message to find out.
         _hasValidPositionInformation = NO;
-        InteractionInformationRequest request(roundedIntPoint(point));
+        WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
 
         // If 3D Touch is enabled, asynchronously collect snapshots in the hopes that
         // they'll arrive before we have to synchronously request them in
@@ -1667,7 +1752,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
         // Use the information retrieved with one of the previous calls
         // to gestureRecognizerShouldBegin.
         // Force a sync call if not ready yet.
-        InteractionInformationRequest request(roundedIntPoint(point));
+        WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
         if (![self ensurePositionInformationIsUpToDate:request])
             return NO;
 
@@ -1706,7 +1791,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 
 - (BOOL)canShowNonEmptySelectionView
 {
-    if (self.suppressAssistantSelectionView)
+    if (_suppressSelectionAssistantReasons)
         return NO;
 
     auto& state = _page->editorState();
@@ -1718,10 +1803,13 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (!_webView.configuration._textInteractionGesturesEnabled)
         return NO;
 
+    if (_suppressSelectionAssistantReasons)
+        return NO;
+
     if (_inspectorNodeSearchEnabled)
         return NO;
 
-    InteractionInformationRequest request(roundedIntPoint(point));
+    WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
     if (![self ensurePositionInformationIsUpToDate:request])
         return NO;
 
@@ -1741,7 +1829,10 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (!_webView.configuration._textInteractionGesturesEnabled)
         return NO;
 
-    InteractionInformationRequest request(roundedIntPoint(point));
+    if (_suppressSelectionAssistantReasons)
+        return NO;
+
+    WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
     if (![self ensurePositionInformationIsUpToDate:request])
         return NO;
     return _positionInformation.isNearMarkedText;
@@ -1752,7 +1843,10 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     if (!_webView.configuration._textInteractionGesturesEnabled)
         return NO;
 
-    InteractionInformationRequest request(roundedIntPoint(point));
+    if (_suppressSelectionAssistantReasons)
+        return NO;
+
+    WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
     if (![self ensurePositionInformationIsUpToDate:request])
         return NO;
 
@@ -1796,7 +1890,7 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
         const WebCore::SelectionRect& coreRect = selectionRects[i];
         WebSelectionRect *webRect = [WebSelectionRect selectionRect];
         webRect.rect = coreRect.rect();
-        webRect.writingDirection = coreRect.direction() == TextDirection::LTR ? WKWritingDirectionLeftToRight : WKWritingDirectionRightToLeft;
+        webRect.writingDirection = coreRect.direction() == WebCore::TextDirection::LTR ? WKWritingDirectionLeftToRight : WKWritingDirectionRightToLeft;
         webRect.isLineBreak = coreRect.isLineBreak();
         webRect.isFirstOnLine = coreRect.isFirstOnLine();
         webRect.isLastOnLine = coreRect.isLastOnLine();
@@ -1853,7 +1947,16 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
 {
     _isTapHighlightIDValid = YES;
     _isExpectingFastSingleTapCommit = YES;
-    _page->handleTwoFingerTapAtPoint(roundedIntPoint(gestureRecognizer.centroid), ++_latestTapID);
+    _page->handleTwoFingerTapAtPoint(WebCore::roundedIntPoint(gestureRecognizer.centroid), ++_latestTapID);
+}
+
+- (void)_stylusSingleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
+{
+    if (!_webView._stylusTapGestureShouldCreateEditableImage)
+        return;
+
+    ASSERT(gestureRecognizer == _stylusSingleTapGestureRecognizer);
+    _page->handleStylusSingleTapAtPoint(WebCore::roundedIntPoint(gestureRecognizer.location), ++_latestTapID);
 }
 
 - (void)_longPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
@@ -1945,15 +2048,10 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 
     if (![self isFirstResponder]) {
         if (!_inputViewUpdateDeferrer)
-            _inputViewUpdateDeferrer = std::make_unique<InputViewUpdateDeferrer>();
+            _inputViewUpdateDeferrer = std::make_unique<WebKit::InputViewUpdateDeferrer>();
         [self becomeFirstResponder];
     }
 
-    if (_webSelectionAssistant && ![_webSelectionAssistant shouldHandleSingleTapAtPoint:gestureRecognizer.location]) {
-        [self _singleTapDidReset:gestureRecognizer];
-        return;
-    }
-
     ASSERT(_potentialTapInProgress);
 
     // We don't want to clear the selection if it is in editable content.
@@ -2009,7 +2107,7 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 {
     if (![self isFirstResponder]) {
         if (!_inputViewUpdateDeferrer)
-            _inputViewUpdateDeferrer = std::make_unique<InputViewUpdateDeferrer>();
+            _inputViewUpdateDeferrer = std::make_unique<WebKit::InputViewUpdateDeferrer>();
         [self becomeFirstResponder];
     }
 
@@ -2017,14 +2115,12 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     _page->handleTap(location, _layerTreeTransactionIdAtLastTouchStart);
 }
 
-- (void)useSelectionAssistantWithGranularity:(WKSelectionGranularity)selectionGranularity
+- (void)setUpTextSelectionAssistant
 {
-    _webSelectionAssistant = nil;
-
     if (!_textSelectionAssistant)
         _textSelectionAssistant = adoptNS([[UIWKTextInteractionAssistant alloc] initWithView:self]);
     else {
-        // Reset the gesture recognizers in case editibility has changed.
+        // Reset the gesture recognizers in case editability has changed.
         [_textSelectionAssistant setGestureRecognizers];
     }
 }
@@ -2035,11 +2131,11 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     _page->clearSelection();
 }
 
-- (void)_positionInformationDidChange:(const InteractionInformationAtPosition&)info
+- (void)_positionInformationDidChange:(const WebKit::InteractionInformationAtPosition&)info
 {
     _outstandingPositionInformationRequest = std::nullopt;
 
-    InteractionInformationAtPosition newInfo = info;
+    WebKit::InteractionInformationAtPosition newInfo = info;
     newInfo.mergeCompatibleOptionalInformation(_positionInformation);
 
     _positionInformation = newInfo;
@@ -2051,7 +2147,6 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 
 - (void)_willStartScrollingOrZooming
 {
-    [_webSelectionAssistant willStartScrollingOrZoomingPage];
     [_textSelectionAssistant willStartScrollingOverflow];
     _page->setIsScrollingOrZooming(true);
 
@@ -2064,13 +2159,14 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 {
     _page->hideValidationMessage();
 
+    [_keyboardScrollingAnimator willStartInteractiveScroll];
+
     _canSendTouchEventsAsynchronously = YES;
 }
 
 - (void)_didEndScrollingOrZooming
 {
     if (!_needsDeferredEndScrollingSelectionUpdate) {
-        [_webSelectionAssistant didEndScrollingOrZoomingPage];
         [_textSelectionAssistant didEndScrollingOverflow];
     }
     _page->setIsScrollingOrZooming(false);
@@ -2085,36 +2181,51 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     if ([_formInputSession accessoryViewShouldNotShow])
         return NO;
 
-    if (_assistedNodeInformation.inputMode == InputMode::None)
+    if ([_formInputSession customInputAccessoryView])
+        return YES;
+
+    if (_assistedNodeInformation.inputMode == WebCore::InputMode::None)
         return NO;
 
     switch (_assistedNodeInformation.elementType) {
-    case InputType::None:
+    case WebKit::InputType::None:
         return NO;
-    case InputType::Text:
-    case InputType::Password:
-    case InputType::Search:
-    case InputType::Email:
-    case InputType::URL:
-    case InputType::Phone:
-    case InputType::Number:
-    case InputType::NumberPad:
-    case InputType::ContentEditable:
-    case InputType::TextArea:
-    case InputType::Select:
-    case InputType::Date:
-    case InputType::DateTime:
-    case InputType::DateTimeLocal:
-    case InputType::Month:
-    case InputType::Week:
-    case InputType::Time:
+    case WebKit::InputType::Text:
+    case WebKit::InputType::Password:
+    case WebKit::InputType::Search:
+    case WebKit::InputType::Email:
+    case WebKit::InputType::URL:
+    case WebKit::InputType::Phone:
+    case WebKit::InputType::Number:
+    case WebKit::InputType::NumberPad:
+    case WebKit::InputType::ContentEditable:
+    case WebKit::InputType::TextArea:
+    case WebKit::InputType::Select:
+    case WebKit::InputType::Date:
+    case WebKit::InputType::DateTime:
+    case WebKit::InputType::DateTimeLocal:
+    case WebKit::InputType::Month:
+    case WebKit:: InputType::Week:
+    case WebKit::InputType::Time:
 #if ENABLE(INPUT_TYPE_COLOR)
-    case InputType::Color:
+    case WebKit::InputType::Color:
 #endif
         return !currentUserInterfaceIdiomIsPad();
+    case WebKit::InputType::Drawing:
+        return YES;
     }
 }
 
+- (UITextInputAssistantItem *)inputAssistantItem
+{
+    return [_webView inputAssistantItem];
+}
+
+- (UITextInputAssistantItem *)inputAssistantItemForWebView
+{
+    return [super inputAssistantItem];
+}
+
 - (void)_ensureFormAccessoryView
 {
     if (_formAccessoryView)
@@ -2129,7 +2240,7 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     if (![self requiresAccessoryView])
         return nil;
 
-    return self.formAccessoryView;
+    return [_formInputSession customInputAccessoryView] ?: self.formAccessoryView;
 }
 
 - (NSArray *)supportedPasteboardTypesForCurrentSelection
@@ -2145,7 +2256,7 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
         [plainTextTypes addObjectsFromArray:UIPasteboardTypeListString];
 
         richTypes = [[NSMutableArray alloc] init];
-        [richTypes addObject:WebArchivePboardType];
+        [richTypes addObject:WebCore::WebArchivePboardType];
         [richTypes addObjectsFromArray:UIPasteboardTypeListImage];
         [richTypes addObjectsFromArray:plainTextTypes];
     }
@@ -2160,16 +2271,15 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     }
 
 FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW)
-
-FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
+FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW)
 
 #undef FORWARD_ACTION_TO_WKWEBVIEW
 
 - (void)_lookupForWebView:(id)sender
 {
     RetainPtr<WKContentView> view = self;
-    _page->getSelectionContext([view](const String& selectedText, const String& textBefore, const String& textAfter, CallbackBase::Error error) {
-        if (error != CallbackBase::Error::None)
+    _page->getSelectionContext([view](const String& selectedText, const String& textBefore, const String& textAfter, WebKit::CallbackBase::Error error) {
+        if (error != WebKit::CallbackBase::Error::None)
             return;
         if (!selectedText)
             return;
@@ -2187,16 +2297,14 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
         if (auto textSelectionAssistant = view->_textSelectionAssistant)
             [textSelectionAssistant lookup:selectionContext withRange:selectedRangeInContext fromRect:presentationRect];
-        else
-            [view->_webSelectionAssistant lookup:selectionContext withRange:selectedRangeInContext fromRect:presentationRect];
     });
 }
 
 - (void)_shareForWebView:(id)sender
 {
     RetainPtr<WKContentView> view = self;
-    _page->getSelectionOrContentsAsString([view](const String& string, CallbackBase::Error error) {
-        if (error != CallbackBase::Error::None)
+    _page->getSelectionOrContentsAsString([view](const String& string, WebKit::CallbackBase::Error error) {
+        if (error != WebKit::CallbackBase::Error::None)
             return;
         if (!string)
             return;
@@ -2205,8 +2313,6 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
         if (view->_textSelectionAssistant)
             [view->_textSelectionAssistant showShareSheetFor:string fromRect:presentationRect];
-        else if (view->_webSelectionAssistant)
-            [view->_webSelectionAssistant showShareSheetFor:string fromRect:presentationRect];
     });
 }
 
@@ -2214,8 +2320,6 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 {
     if (_textSelectionAssistant)
         [_textSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState().postLayoutData().selectionRects[0].rect()];
-    else if (_webSelectionAssistant)
-        [_webSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState().postLayoutData().selectionRects[0].rect()];
 }
 
 - (NSString *)selectedText
@@ -2223,6 +2327,11 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     return (NSString *)_page->editorState().postLayoutData().wordAtSelection;
 }
 
+- (void)makeTextWritingDirectionNaturalForWebView:(id)sender
+{
+    _page->executeEditCommand("makeTextWritingDirectionNatural"_s);
+}
+
 - (BOOL)isReplaceAllowed
 {
     return _page->editorState().postLayoutData().isReplaceAllowed;
@@ -2257,6 +2366,95 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     [[UIKeyboardImpl sharedInstance] replaceText:sender];
 }
 
+#define WEBCORE_COMMAND_FOR_WEBVIEW(command) \
+    - (void)_ ## command ## ForWebView:(id)sender { _page->executeEditCommand(#command ## _s); } \
+    - (void)command ## ForWebView:(id)sender { [self _ ## command ## ForWebView:sender]; }
+WEBCORE_COMMAND_FOR_WEBVIEW(insertOrderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(insertUnorderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(insertNestedOrderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(insertNestedUnorderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(indent);
+WEBCORE_COMMAND_FOR_WEBVIEW(outdent);
+WEBCORE_COMMAND_FOR_WEBVIEW(alignLeft);
+WEBCORE_COMMAND_FOR_WEBVIEW(alignRight);
+WEBCORE_COMMAND_FOR_WEBVIEW(alignCenter);
+WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
+WEBCORE_COMMAND_FOR_WEBVIEW(pasteAndMatchStyle);
+#undef WEBCORE_COMMAND_FOR_WEBVIEW
+
+- (void)_increaseListLevelForWebView:(id)sender
+{
+    _page->increaseListLevel();
+}
+
+- (void)_decreaseListLevelForWebView:(id)sender
+{
+    _page->decreaseListLevel();
+}
+
+- (void)_changeListTypeForWebView:(id)sender
+{
+    _page->changeListType();
+}
+
+- (void)_toggleStrikeThroughForWebView:(id)sender
+{
+    _page->executeEditCommand("StrikeThrough"_s);
+}
+
+- (void)increaseSizeForWebView:(id)sender
+{
+    _page->executeEditCommand("FontSizeDelta"_s, "1"_s);
+}
+
+- (void)decreaseSizeForWebView:(id)sender
+{
+    _page->executeEditCommand("FontSizeDelta"_s, "-1"_s);
+}
+
+- (void)_setFontForWebView:(UIFont *)font sender:(id)sender
+{
+    WebCore::FontChanges changes;
+    changes.setFontFamily(font.familyName);
+    changes.setFontName(font.fontName);
+    changes.setFontSize(font.pointSize);
+    changes.setBold(font.traits & UIFontTraitBold);
+    changes.setItalic(font.traits & UIFontTraitItalic);
+    _page->changeFont(WTFMove(changes));
+}
+
+- (void)_setFontSizeForWebView:(CGFloat)fontSize sender:(id)sender
+{
+    WebCore::FontChanges changes;
+    changes.setFontSize(fontSize);
+    _page->changeFont(WTFMove(changes));
+}
+
+- (void)_setTextColorForWebView:(UIColor *)color sender:(id)sender
+{
+    _page->executeEditCommand("ForeColor"_s, WebCore::Color(color.CGColor).serialized());
+}
+
+- (void)toggleStrikeThroughForWebView:(id)sender
+{
+    [self _toggleStrikeThroughForWebView:sender];
+}
+
+- (void)setFontForWebView:(UIFont *)font sender:(id)sender
+{
+    [self _setFontForWebView:font sender:sender];
+}
+
+- (void)setFontSizeForWebView:(CGFloat)fontSize sender:(id)sender
+{
+    [self _setFontSizeForWebView:fontSize sender:sender];
+}
+
+- (void)setTextColorForWebView:(UIColor *)color sender:(id)sender
+{
+    [self _setTextColorForWebView:color sender:sender];
+}
+
 - (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
 {
     if (!position || !_page->editorState().isContentRichlyEditable)
@@ -2266,9 +2464,9 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
     auto typingAttributes = _page->editorState().postLayoutData().typingAttributes;
     CTFontSymbolicTraits symbolicTraits = 0;
-    if (typingAttributes & AttributeBold)
+    if (typingAttributes & WebKit::AttributeBold)
         symbolicTraits |= kCTFontBoldTrait;
-    if (typingAttributes & AttributeItalics)
+    if (typingAttributes & WebKit::AttributeItalics)
         symbolicTraits |= kCTFontTraitItalic;
 
     // We chose a random font family and size.
@@ -2282,7 +2480,7 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     if (font)
         [result setObject:(id)font.get() forKey:NSFontAttributeName];
     
-    if (typingAttributes & AttributeUnderline)
+    if (typingAttributes & WebKit::AttributeUnderline)
         [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
 
     return result;
@@ -2290,15 +2488,41 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
 - (UIColor *)insertionPointColor
 {
-    if (!_webView.configuration._textInteractionGesturesEnabled)
-        return [UIColor clearColor];
+    return [self.textInputTraits insertionPointColor];
+}
 
-    if (!_page->editorState().isMissingPostLayoutData) {
-        WebCore::Color caretColor = _page->editorState().postLayoutData().caretColor;
-        if (caretColor.isValid())
-            return [UIColor colorWithCGColor:cachedCGColor(caretColor)];
-    }
-    return [UIColor insertionPointColor];
+- (UIColor *)selectionBarColor
+{
+    return [self.textInputTraits selectionBarColor];
+}
+
+- (UIColor *)selectionHighlightColor
+{
+    return [self.textInputTraits selectionHighlightColor];
+}
+
+- (void)_updateInteractionTintColor
+{
+    UIColor *tintColor = ^{
+        if (!_webView.configuration._textInteractionGesturesEnabled)
+            return [UIColor clearColor];
+
+        if (!_page->editorState().isMissingPostLayoutData) {
+            WebCore::Color caretColor = _page->editorState().postLayoutData().caretColor;
+            if (caretColor.isValid())
+                return [UIColor colorWithCGColor:cachedCGColor(caretColor)];
+        }
+        
+        return [self _inheritedInteractionTintColor];    
+    }();
+
+    [_traits _setColorsToMatchTintColor:tintColor];
+}
+
+- (void)tintColorDidChange
+{
+    [super tintColorDidChange];
+    [self _updateInteractionTintColor];
 }
 
 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
@@ -2308,20 +2532,35 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
 - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender
 {
-    if (action == @selector(_arrowKey:))
-        return [self isFirstResponder];
-        
+    if (action == @selector(_nextAccessoryTab:))
+        return hasAssistedNode(_assistedNodeInformation) && _assistedNodeInformation.hasNextNode;
+    if (action == @selector(_previousAccessoryTab:))
+        return hasAssistedNode(_assistedNodeInformation) && _assistedNodeInformation.hasPreviousNode;
+
     auto editorState = _page->editorState();
     if (action == @selector(_showTextStyleOptions:))
         return editorState.isContentRichlyEditable && editorState.selectionIsRange && !_showingTextStyleOptions;
     if (_showingTextStyleOptions)
         return (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:));
-    if (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:))
+    // FIXME: Some of the following checks should be removed once internal clients move to the underscore-prefixed versions.
+    if (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:) || action == @selector(_toggleStrikeThrough:)
+        || action == @selector(_alignLeft:) || action == @selector(_alignRight:) || action == @selector(_alignCenter:) || action == @selector(_alignJustified:)
+        || action == @selector(_setTextColor:sender:) || action == @selector(_setFont:sender:) || action == @selector(_setFontSize:sender:)
+        || action == @selector(_insertOrderedList:) || action == @selector(_insertUnorderedList:) || action == @selector(_insertNestedOrderedList:) || action == @selector(_insertNestedUnorderedList:)
+        || action == @selector(_increaseListLevel:) || action == @selector(_decreaseListLevel:) || action == @selector(_changeListType:) || action == @selector(_indent:) || action == @selector(_outdent:)
+        || action == @selector(increaseSize:) || action == @selector(decreaseSize:)
+        || action == @selector(toggleStrikeThrough:) || action == @selector(insertOrderedList:) || action == @selector(insertUnorderedList:) || action == @selector(indent:) || action == @selector(outdent:)
+        || action == @selector(alignLeft:) || action == @selector(alignRight:) || action == @selector(alignCenter:) || action == @selector(alignJustified:)
+        || action == @selector(setTextColor:sender:) || action == @selector(setFont:sender:) || action == @selector(setFontSize:sender:)
+        || action == @selector(makeTextWritingDirectionNatural:)) {
+        // FIXME: This should be more nuanced in the future, rather than returning YES for all richly editable areas. For instance, outdent: should be disabled when the selection is already
+        // at the outermost indentation level.
         return editorState.isContentRichlyEditable;
+    }
     if (action == @selector(cut:))
         return !editorState.isInPasswordField && editorState.isContentEditable && editorState.selectionIsRange;
     
-    if (action == @selector(paste:)) {
+    if (action == @selector(paste:) || action == @selector(_pasteAsQuotation:) || action == @selector(_pasteAndMatchStyle:) || action == @selector(pasteAndMatchStyle:)) {
         if (editorState.selectionIsNone || !editorState.isContentEditable)
             return NO;
         UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
@@ -2334,10 +2573,10 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
         if (focusedDocumentOrigin.isEmpty())
             return NO;
 
-        NSArray *allCustomPasteboardData = [pasteboard dataForPasteboardType:@(PasteboardCustomData::cocoaType()) inItemSet:indices];
+        NSArray *allCustomPasteboardData = [pasteboard dataForPasteboardType:@(WebCore::PasteboardCustomData::cocoaType()) inItemSet:indices];
         for (NSData *data in allCustomPasteboardData) {
-            auto buffer = SharedBuffer::create(data);
-            if (PasteboardCustomData::fromSharedBuffer(buffer.get()).origin == focusedDocumentOrigin)
+            auto buffer = WebCore::SharedBuffer::create(data);
+            if (WebCore::PasteboardCustomData::fromSharedBuffer(buffer.get()).origin == focusedDocumentOrigin)
                 return YES;
         }
         return NO;
@@ -2473,7 +2712,7 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 {
     [_textSelectionAssistant selectWord];
     // We cannot use selectWord command, because we want to be able to select the word even when it is the last in the paragraph.
-    _page->extendSelection(WordGranularity);
+    _page->extendSelection(WebCore::WordGranularity);
 }
 
 - (void)selectAllForWebView:(id)sender
@@ -2517,8 +2756,6 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     CGRect presentationRect = _page->editorState().postLayoutData().selectionRects[0].rect();
     if (_textSelectionAssistant)
         [_textSelectionAssistant showDictionaryFor:text fromRect:presentationRect];
-    else
-        [_webSelectionAssistant showDictionaryFor:text fromRect:presentationRect];
 }
 
 - (void)_defineForWebView:(id)sender
@@ -2555,7 +2792,7 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 - (void)_accessibilityRetrieveRectsEnclosingSelectionOffset:(NSInteger)offset withGranularity:(UITextGranularity)granularity
 {
     RetainPtr<WKContentView> view = self;
-    _page->requestRectsForGranularityWithSelectionOffset(toWKTextGranularity(granularity), offset , [view, offset, granularity](const Vector<WebCore::SelectionRect>& selectionRects, CallbackBase::Error error) {
+    _page->requestRectsForGranularityWithSelectionOffset(toWKTextGranularity(granularity), offset , [view, offset, granularity](const Vector<WebCore::SelectionRect>& selectionRects, WebKit::CallbackBase::Error error) {
         if (error != WebKit::CallbackBase::Error::None)
             return;
         if ([view respondsToSelector:@selector(_accessibilityDidGetSelectionRects:withGranularity:atOffset:)])
@@ -2568,10 +2805,10 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     [self _accessibilityRetrieveRectsAtSelectionOffset:offset withText:text completionHandler:nil];
 }
 
-- (void)_accessibilityRetrieveRectsAtSelectionOffset:(NSInteger)offset withText:(NSString *)text completionHandler:(void (^)(const Vector<SelectionRect>& rects))completionHandler
+- (void)_accessibilityRetrieveRectsAtSelectionOffset:(NSInteger)offset withText:(NSString *)text completionHandler:(void (^)(const Vector<WebCore::SelectionRect>& rects))completionHandler
 {
     RetainPtr<WKContentView> view = self;
-    _page->requestRectsAtSelectionOffsetWithText(offset, text, [view, offset, capturedCompletionHandler = makeBlockPtr(completionHandler)](const Vector<SelectionRect>& selectionRects, CallbackBase::Error error) {
+    _page->requestRectsAtSelectionOffsetWithText(offset, text, [view, offset, capturedCompletionHandler = makeBlockPtr(completionHandler)](const Vector<WebCore::SelectionRect>& selectionRects, WebKit::CallbackBase::Error error) {
         if (capturedCompletionHandler)
             capturedCompletionHandler(selectionRects);
 
@@ -2594,160 +2831,160 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
 
 // UIWKInteractionViewProtocol
 
-static inline GestureType toGestureType(UIWKGestureType gestureType)
+static inline WebKit::GestureType toGestureType(UIWKGestureType gestureType)
 {
     switch (gestureType) {
     case UIWKGestureLoupe:
-        return GestureType::Loupe;
+        return WebKit::GestureType::Loupe;
     case UIWKGestureOneFingerTap:
-        return GestureType::OneFingerTap;
+        return WebKit::GestureType::OneFingerTap;
     case UIWKGestureTapAndAHalf:
-        return GestureType::TapAndAHalf;
+        return WebKit::GestureType::TapAndAHalf;
     case UIWKGestureDoubleTap:
-        return GestureType::DoubleTap;
+        return WebKit::GestureType::DoubleTap;
     case UIWKGestureTapAndHalf:
-        return GestureType::TapAndHalf;
+        return WebKit::GestureType::TapAndHalf;
     case UIWKGestureDoubleTapInUneditable:
-        return GestureType::DoubleTapInUneditable;
+        return WebKit::GestureType::DoubleTapInUneditable;
     case UIWKGestureOneFingerTapInUneditable:
-        return GestureType::OneFingerTapInUneditable;
+        return WebKit::GestureType::OneFingerTapInUneditable;
     case UIWKGestureOneFingerTapSelectsAll:
-        return GestureType::OneFingerTapSelectsAll;
+        return WebKit::GestureType::OneFingerTapSelectsAll;
     case UIWKGestureOneFingerDoubleTap:
-        return GestureType::OneFingerDoubleTap;
+        return WebKit::GestureType::OneFingerDoubleTap;
     case UIWKGestureOneFingerTripleTap:
-        return GestureType::OneFingerTripleTap;
+        return WebKit::GestureType::OneFingerTripleTap;
     case UIWKGestureTwoFingerSingleTap:
-        return GestureType::TwoFingerSingleTap;
+        return WebKit::GestureType::TwoFingerSingleTap;
     case UIWKGestureTwoFingerRangedSelectGesture:
-        return GestureType::TwoFingerRangedSelectGesture;
+        return WebKit::GestureType::TwoFingerRangedSelectGesture;
     case UIWKGestureTapOnLinkWithGesture:
-        return GestureType::TapOnLinkWithGesture;
+        return WebKit::GestureType::TapOnLinkWithGesture;
     case UIWKGestureMakeWebSelection:
-        return GestureType::MakeWebSelection;
+        return WebKit::GestureType::MakeWebSelection;
     case UIWKGesturePhraseBoundary:
-        return GestureType::PhraseBoundary;
+        return WebKit::GestureType::PhraseBoundary;
     }
     ASSERT_NOT_REACHED();
-    return GestureType::Loupe;
+    return WebKit::GestureType::Loupe;
 }
 
-static inline UIWKGestureType toUIWKGestureType(GestureType gestureType)
+static inline UIWKGestureType toUIWKGestureType(WebKit::GestureType gestureType)
 {
     switch (gestureType) {
-    case GestureType::Loupe:
+    case WebKit::GestureType::Loupe:
         return UIWKGestureLoupe;
-    case GestureType::OneFingerTap:
+    case WebKit::GestureType::OneFingerTap:
         return UIWKGestureOneFingerTap;
-    case GestureType::TapAndAHalf:
+    case WebKit::GestureType::TapAndAHalf:
         return UIWKGestureTapAndAHalf;
-    case GestureType::DoubleTap:
+    case WebKit::GestureType::DoubleTap:
         return UIWKGestureDoubleTap;
-    case GestureType::TapAndHalf:
+    case WebKit::GestureType::TapAndHalf:
         return UIWKGestureTapAndHalf;
-    case GestureType::DoubleTapInUneditable:
+    case WebKit::GestureType::DoubleTapInUneditable:
         return UIWKGestureDoubleTapInUneditable;
-    case GestureType::OneFingerTapInUneditable:
+    case WebKit::GestureType::OneFingerTapInUneditable:
         return UIWKGestureOneFingerTapInUneditable;
-    case GestureType::OneFingerTapSelectsAll:
+    case WebKit::GestureType::OneFingerTapSelectsAll:
         return UIWKGestureOneFingerTapSelectsAll;
-    case GestureType::OneFingerDoubleTap:
+    case WebKit::GestureType::OneFingerDoubleTap:
         return UIWKGestureOneFingerDoubleTap;
-    case GestureType::OneFingerTripleTap:
+    case WebKit::GestureType::OneFingerTripleTap:
         return UIWKGestureOneFingerTripleTap;
-    case GestureType::TwoFingerSingleTap:
+    case WebKit::GestureType::TwoFingerSingleTap:
         return UIWKGestureTwoFingerSingleTap;
-    case GestureType::TwoFingerRangedSelectGesture:
+    case WebKit::GestureType::TwoFingerRangedSelectGesture:
         return UIWKGestureTwoFingerRangedSelectGesture;
-    case GestureType::TapOnLinkWithGesture:
+    case WebKit::GestureType::TapOnLinkWithGesture:
         return UIWKGestureTapOnLinkWithGesture;
-    case GestureType::MakeWebSelection:
+    case WebKit::GestureType::MakeWebSelection:
         return UIWKGestureMakeWebSelection;
-    case GestureType::PhraseBoundary:
+    case WebKit::GestureType::PhraseBoundary:
         return UIWKGesturePhraseBoundary;
     }
 }
 
-static inline SelectionTouch toSelectionTouch(UIWKSelectionTouch touch)
+static inline WebKit::SelectionTouch toSelectionTouch(UIWKSelectionTouch touch)
 {
     switch (touch) {
     case UIWKSelectionTouchStarted:
-        return SelectionTouch::Started;
+        return WebKit::SelectionTouch::Started;
     case UIWKSelectionTouchMoved:
-        return SelectionTouch::Moved;
+        return WebKit::SelectionTouch::Moved;
     case UIWKSelectionTouchEnded:
-        return SelectionTouch::Ended;
+        return WebKit::SelectionTouch::Ended;
     case UIWKSelectionTouchEndedMovingForward:
-        return SelectionTouch::EndedMovingForward;
+        return WebKit::SelectionTouch::EndedMovingForward;
     case UIWKSelectionTouchEndedMovingBackward:
-        return SelectionTouch::EndedMovingBackward;
+        return WebKit::SelectionTouch::EndedMovingBackward;
     case UIWKSelectionTouchEndedNotMoving:
-        return SelectionTouch::EndedNotMoving;
+        return WebKit::SelectionTouch::EndedNotMoving;
     }
     ASSERT_NOT_REACHED();
-    return SelectionTouch::Ended;
+    return WebKit::SelectionTouch::Ended;
 }
 
-static inline UIWKSelectionTouch toUIWKSelectionTouch(SelectionTouch touch)
+static inline UIWKSelectionTouch toUIWKSelectionTouch(WebKit::SelectionTouch touch)
 {
     switch (touch) {
-    case SelectionTouch::Started:
+    case WebKit::SelectionTouch::Started:
         return UIWKSelectionTouchStarted;
-    case SelectionTouch::Moved:
+    case WebKit::SelectionTouch::Moved:
         return UIWKSelectionTouchMoved;
-    case SelectionTouch::Ended:
+    case WebKit::SelectionTouch::Ended:
         return UIWKSelectionTouchEnded;
-    case SelectionTouch::EndedMovingForward:
+    case WebKit::SelectionTouch::EndedMovingForward:
         return UIWKSelectionTouchEndedMovingForward;
-    case SelectionTouch::EndedMovingBackward:
+    case WebKit::SelectionTouch::EndedMovingBackward:
         return UIWKSelectionTouchEndedMovingBackward;
-    case SelectionTouch::EndedNotMoving:
+    case WebKit::SelectionTouch::EndedNotMoving:
         return UIWKSelectionTouchEndedNotMoving;
     }
 }
 
-static inline GestureRecognizerState toGestureRecognizerState(UIGestureRecognizerState state)
+static inline WebKit::GestureRecognizerState toGestureRecognizerState(UIGestureRecognizerState state)
 {
     switch (state) {
     case UIGestureRecognizerStatePossible:
-        return GestureRecognizerState::Possible;
+        return WebKit::GestureRecognizerState::Possible;
     case UIGestureRecognizerStateBegan:
-        return GestureRecognizerState::Began;
+        return WebKit::GestureRecognizerState::Began;
     case UIGestureRecognizerStateChanged:
-        return GestureRecognizerState::Changed;
+        return WebKit::GestureRecognizerState::Changed;
     case UIGestureRecognizerStateCancelled:
-        return GestureRecognizerState::Cancelled;
+        return WebKit::GestureRecognizerState::Cancelled;
     case UIGestureRecognizerStateEnded:
-        return GestureRecognizerState::Ended;
+        return WebKit::GestureRecognizerState::Ended;
     case UIGestureRecognizerStateFailed:
-        return GestureRecognizerState::Failed;
+        return WebKit::GestureRecognizerState::Failed;
     }
 }
 
-static inline UIGestureRecognizerState toUIGestureRecognizerState(GestureRecognizerState state)
+static inline UIGestureRecognizerState toUIGestureRecognizerState(WebKit::GestureRecognizerState state)
 {
     switch (state) {
-    case GestureRecognizerState::Possible:
+    case WebKit::GestureRecognizerState::Possible:
         return UIGestureRecognizerStatePossible;
-    case GestureRecognizerState::Began:
+    case WebKit::GestureRecognizerState::Began:
         return UIGestureRecognizerStateBegan;
-    case GestureRecognizerState::Changed:
+    case WebKit::GestureRecognizerState::Changed:
         return UIGestureRecognizerStateChanged;
-    case GestureRecognizerState::Cancelled:
+    case WebKit::GestureRecognizerState::Cancelled:
         return UIGestureRecognizerStateCancelled;
-    case GestureRecognizerState::Ended:
+    case WebKit::GestureRecognizerState::Ended:
         return UIGestureRecognizerStateEnded;
-    case GestureRecognizerState::Failed:
+    case WebKit::GestureRecognizerState::Failed:
         return UIGestureRecognizerStateFailed;
     }
 }
 
-static inline UIWKSelectionFlags toUIWKSelectionFlags(SelectionFlags flags)
+static inline UIWKSelectionFlags toUIWKSelectionFlags(WebKit::SelectionFlags flags)
 {
     NSInteger uiFlags = UIWKNone;
-    if (flags & WordIsNearTap)
+    if (flags & WebKit::WordIsNearTap)
         uiFlags |= UIWKWordIsNearTap;
-    if (flags & PhraseBoundaryChanged)
+    if (flags & WebKit::PhraseBoundaryChanged)
         uiFlags |= UIWKPhraseBoundaryChanged;
 
     return static_cast<UIWKSelectionFlags>(uiFlags);
@@ -2757,17 +2994,17 @@ static inline WebCore::TextGranularity toWKTextGranularity(UITextGranularity gra
 {
     switch (granularity) {
     case UITextGranularityCharacter:
-        return CharacterGranularity;
+        return WebCore::CharacterGranularity;
     case UITextGranularityWord:
-        return WordGranularity;
+        return WebCore::WordGranularity;
     case UITextGranularitySentence:
-        return SentenceGranularity;
+        return WebCore::SentenceGranularity;
     case UITextGranularityParagraph:
-        return ParagraphGranularity;
+        return WebCore::ParagraphGranularity;
     case UITextGranularityLine:
-        return LineGranularity;
+        return WebCore::LineGranularity;
     case UITextGranularityDocument:
-        return DocumentGranularity;
+        return WebCore::DocumentGranularity;
     }
 }
 
@@ -2776,14 +3013,14 @@ static inline WebCore::SelectionDirection toWKSelectionDirection(UITextDirection
     switch (direction) {
     case UITextLayoutDirectionDown:
     case UITextLayoutDirectionRight:
-        return DirectionRight;
+        return WebCore::DirectionRight;
     case UITextLayoutDirectionUp:
     case UITextLayoutDirectionLeft:
-        return DirectionLeft;
+        return WebCore::DirectionLeft;
     default:
         // UITextDirection is not an enum, but we only want to accept values from UITextLayoutDirection.
         ASSERT_NOT_REACHED();
-        return DirectionRight;
+        return WebCore::DirectionRight;
     }
 }
 
@@ -2793,10 +3030,7 @@ static void selectionChangedWithGesture(WKContentView *view, const WebCore::IntP
         ASSERT_NOT_REACHED();
         return;
     }
-    if ([view webSelectionAssistant])
-        [(UIWKSelectionAssistant *)[view webSelectionAssistant] selectionChangedWithGestureAt:(CGPoint)point withGesture:toUIWKGestureType((GestureType)gestureType) withState:toUIGestureRecognizerState(static_cast<GestureRecognizerState>(gestureState)) withFlags:(toUIWKSelectionFlags((SelectionFlags)flags))];
-    else
-        [(UIWKTextInteractionAssistant *)[view interactionAssistant] selectionChangedWithGestureAt:(CGPoint)point withGesture:toUIWKGestureType((GestureType)gestureType) withState:toUIGestureRecognizerState(static_cast<GestureRecognizerState>(gestureState)) withFlags:(toUIWKSelectionFlags((SelectionFlags)flags))];
+    [(UIWKTextInteractionAssistant *)[view interactionAssistant] selectionChangedWithGestureAt:(CGPoint)point withGesture:toUIWKGestureType((WebKit::GestureType)gestureType) withState:toUIGestureRecognizerState(static_cast<WebKit::GestureRecognizerState>(gestureState)) withFlags:(toUIWKSelectionFlags((WebKit::SelectionFlags)flags))];
 }
 
 static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoint& point, uint32_t touch, uint32_t flags, WebKit::CallbackBase::Error error)
@@ -2805,10 +3039,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
         ASSERT_NOT_REACHED();
         return;
     }
-    if ([view webSelectionAssistant])
-        [(UIWKSelectionAssistant *)[view webSelectionAssistant] selectionChangedWithTouchAt:(CGPoint)point withSelectionTouch:toUIWKSelectionTouch((SelectionTouch)touch) withFlags:static_cast<UIWKSelectionFlags>(flags)];
-    else
-        [(UIWKTextInteractionAssistant *)[view interactionAssistant] selectionChangedWithTouchAt:(CGPoint)point withSelectionTouch:toUIWKSelectionTouch((SelectionTouch)touch) withFlags:static_cast<UIWKSelectionFlags>(flags)];
+    [(UIWKTextInteractionAssistant *)[view interactionAssistant] selectionChangedWithTouchAt:(CGPoint)point withSelectionTouch:toUIWKSelectionTouch((WebKit::SelectionTouch)touch) withFlags:static_cast<UIWKSelectionFlags>(flags)];
 }
 
 - (BOOL)_isInteractingWithAssistedNode
@@ -2824,20 +3055,13 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 - (void)changeSelectionWithGestureAt:(CGPoint)point withGesture:(UIWKGestureType)gestureType withState:(UIGestureRecognizerState)state withFlags:(UIWKSelectionFlags)flags
 {
     _usingGestureForSelection = YES;
-    _page->selectWithGesture(WebCore::IntPoint(point), CharacterGranularity, static_cast<uint32_t>(toGestureType(gestureType)), static_cast<uint32_t>(toGestureRecognizerState(state)), [self _isInteractingWithAssistedNode], [self, state, flags](const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t innerFlags, WebKit::CallbackBase::Error error) {
+    _page->selectWithGesture(WebCore::IntPoint(point), WebCore::CharacterGranularity, static_cast<uint32_t>(toGestureType(gestureType)), static_cast<uint32_t>(toGestureRecognizerState(state)), [self _isInteractingWithAssistedNode], [self, state, flags](const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t innerFlags, WebKit::CallbackBase::Error error) {
         selectionChangedWithGesture(self, point, gestureType, gestureState, flags | innerFlags, error);
         if (state == UIGestureRecognizerStateEnded || state == UIGestureRecognizerStateCancelled)
             _usingGestureForSelection = NO;
     });
 }
 
-#if __IPHONE_OS_VERSION_MAX_ALLOWED < 120000
-- (void)changeSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch baseIsStart:(BOOL)baseIsStart
-{
-    [self changeSelectionWithTouchAt:point withSelectionTouch:touch baseIsStart:baseIsStart withFlags:UIWKNone];
-}
-#endif
-
 - (void)changeSelectionWithTouchAt:(CGPoint)point withSelectionTouch:(UIWKSelectionTouch)touch baseIsStart:(BOOL)baseIsStart withFlags:(UIWKSelectionFlags)flags
 {
     _usingGestureForSelection = YES;
@@ -2870,7 +3094,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
     });
 }
 
-- (const WKAutoCorrectionData&)autocorrectionData
+- (const WebKit::WKAutoCorrectionData&)autocorrectionData
 {
     return _autocorrectionData;
 }
@@ -2885,7 +3109,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 
     RetainPtr<WKContentView> view = self;
     _autocorrectionData.autocorrectionHandler = [completionHandler copy];
-    _page->requestAutocorrectionData(input, [view](const Vector<FloatRect>& rects, const String& fontName, double fontSize, uint64_t traits, WebKit::CallbackBase::Error) {
+    _page->requestAutocorrectionData(input, [view](const Vector<WebCore::FloatRect>& rects, const String& fontName, double fontSize, uint64_t traits, WebKit::CallbackBase::Error) {
         CGRect firstRect = CGRectZero;
         CGRect lastRect = CGRectZero;
         if (rects.size()) {
@@ -3086,61 +3310,29 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 
 - (NSArray *)keyCommands
 {
-    static NSArray* nonEditableKeyCommands = [@[
-       [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:0 action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:0 action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:0 action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:0 action:@selector(_arrowKey:)],
-       
-       [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierCommand action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierCommand action:@selector(_arrowKey:)],
-       
-       [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierShift action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierShift action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:UIKeyModifierShift action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:UIKeyModifierShift action:@selector(_arrowKey:)],
-       
-       [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:UIKeyModifierAlternate action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:UIKeyModifierAlternate action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:UIKeyModifierAlternate action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:UIKeyModifierAlternate action:@selector(_arrowKey:)],
-       
-       [UIKeyCommand keyCommandWithInput:@" " modifierFlags:0 action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:@" " modifierFlags:UIKeyModifierShift action:@selector(_arrowKey:)],
-       
-       [UIKeyCommand keyCommandWithInput:UIKeyInputPageDown modifierFlags:0 action:@selector(_arrowKey:)],
-       [UIKeyCommand keyCommandWithInput:UIKeyInputPageDown modifierFlags:0 action:@selector(_arrowKey:)],
-    ] retain];
+    if (!_page->editorState().isContentEditable)
+        return nil;
 
     static NSArray* editableKeyCommands = [@[
-       [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(_nextAccessoryTab:)],
-       [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(_prevAccessoryTab:)]
+        [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(_nextAccessoryTab:)],
+        [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(_previousAccessoryTab:)]
     ] retain];
-    
-    return (_page->editorState().isContentEditable) ? editableKeyCommands : nonEditableKeyCommands;
+    return editableKeyCommands;
 }
 
-- (void)_arrowKeyForWebView:(id)sender
-{
-    UIKeyCommand* command = sender;
-    [self handleKeyEvent:command._triggeringEvent];
-}
-
-- (void)_nextAccessoryTab:(id)sender
+- (void)_nextAccessoryTabForWebView:(id)sender
 {
     [self accessoryTab:YES];
 }
 
-- (void)_prevAccessoryTab:(id)sender
+- (void)_previousAccessoryTabForWebView:(id)sender
 {
     [self accessoryTab:NO];
 }
 
 - (void)accessoryTab:(BOOL)isNext
 {
-    [_formInputSession endEditing];
-
-    [_inputPeripheral endEditing];
+    [self _endEditing];
     _inputPeripheral = nil;
 
     _didAccessoryTabInitiateFocus = YES; // Will be cleared in either -_displayFormNodeInputView or -cleanupInteraction.
@@ -3157,7 +3349,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
     auto completionHandlerCopy = Block_copy(completionHandler);
     RetainPtr<WKContentView> view = self;
     _page->setInitialFocus(selectingForward, false, WebKit::WebKeyboardEvent(), [view, completionHandlerCopy](WebKit::CallbackBase::Error) {
-        BOOL didBecomeFirstResponder = view->_assistedNodeInformation.elementType != InputType::None && [view becomeFirstResponder];
+        BOOL didBecomeFirstResponder = view->_assistedNodeInformation.elementType != WebKit::InputType::None && [view becomeFirstResponder];
         completionHandlerCopy(didBecomeFirstResponder);
         Block_release(completionHandlerCopy);
     });
@@ -3208,10 +3400,10 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
         [_formAccessoryView setClearVisible:NO];
     else {
         switch (_assistedNodeInformation.elementType) {
-        case InputType::Date:
-        case InputType::Month:
-        case InputType::DateTimeLocal:
-        case InputType::Time:
+        case WebKit::InputType::Date:
+        case WebKit::InputType::Month:
+        case WebKit::InputType::DateTimeLocal:
+        case WebKit::InputType::Time:
             [_formAccessoryView setClearVisible:YES];
             break;
         default:
@@ -3277,8 +3469,8 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
         return nil;
     
     auto& postLayoutEditorStateData = _page->editorState().postLayoutData();
-    FloatRect startRect = postLayoutEditorStateData.caretRectAtStart;
-    FloatRect endRect = postLayoutEditorStateData.caretRectAtEnd;
+    WebCore::FloatRect startRect = postLayoutEditorStateData.caretRectAtStart;
+    WebCore::FloatRect endRect = postLayoutEditorStateData.caretRectAtEnd;
     double inverseScale = [self inverseScale];
     // We want to keep the original caret width, while the height scales with
     // the content taking orientation into account.
@@ -3357,7 +3549,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 - (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
 {
     _markedText = markedText;
-    _page->setCompositionAsync(markedText, Vector<WebCore::CompositionUnderline>(), selectedRange, EditingRange());
+    _page->setCompositionAsync(markedText, Vector<WebCore::CompositionUnderline>(), selectedRange, WebKit::EditingRange());
 }
 
 - (void)unmarkText
@@ -3416,13 +3608,33 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
     return nil;
 }
 
-- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+- (NSWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+{
+    return NSWritingDirectionLeftToRight;
+}
+
+static WebKit::WritingDirection coreWritingDirection(NSWritingDirection direction)
 {
-    return UITextWritingDirectionLeftToRight;
+    switch (direction) {
+    case NSWritingDirectionNatural:
+        return WebCore::WritingDirection::Natural;
+    case NSWritingDirectionLeftToRight:
+        return WebCore::WritingDirection::LeftToRight;
+    case NSWritingDirectionRightToLeft:
+        return WebCore::WritingDirection::RightToLeft;
+    default:
+        ASSERT_NOT_REACHED();
+        return WebCore::WritingDirection::Natural;
+    }
 }
 
-- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
+- (void)setBaseWritingDirection:(NSWritingDirection)direction forRange:(UITextRange *)range
 {
+    if (range && ![range isEqual:self.selectedTextRange]) {
+        // We currently only support changing the base writing direction at the selection.
+        return;
+    }
+    _page->setBaseWritingDirection(coreWritingDirection(direction));
 }
 
 - (CGRect)firstRectForRange:(UITextRange *)range
@@ -3434,7 +3646,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 - (UITextPosition *)closestPositionToPoint:(CGPoint)point
 {
 #if PLATFORM(IOSMAC)
-    InteractionInformationRequest request(roundedIntPoint(point));
+    WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(point));
     [self requestAsynchronousPositionInformationUpdate:request];
     if ([self _currentPositionInformationIsApproximatelyValidForRequest:request] && _positionInformation.isSelectable)
         return [WKTextPosition textPositionWithRect:_positionInformation.caretRect];
@@ -3460,7 +3672,7 @@ static void selectionChangedWithTouch(WKContentView *view, const WebCore::IntPoi
 // Inserts the given string, replacing any selected or marked text.
 - (void)insertText:(NSString *)aStringValue
 {
-    _page->insertTextAsync(aStringValue, EditingRange());
+    _page->insertTextAsync(aStringValue, WebKit::EditingRange());
 }
 
 - (BOOL)hasText
@@ -3580,13 +3792,13 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     if (!_traits)
         _traits = adoptNS([[UITextInputTraits alloc] init]);
 
-    [_traits setSecureTextEntry:_assistedNodeInformation.elementType == InputType::Password || [_formInputSession forceSecureTextEntry]];
-    [_traits setShortcutConversionType:_assistedNodeInformation.elementType == InputType::Password ? UITextShortcutConversionTypeNo : UITextShortcutConversionTypeDefault];
+    [_traits setSecureTextEntry:_assistedNodeInformation.elementType == WebKit::InputType::Password || [_formInputSession forceSecureTextEntry]];
+    [_traits setShortcutConversionType:_assistedNodeInformation.elementType == WebKit::InputType::Password ? UITextShortcutConversionTypeNo : UITextShortcutConversionTypeDefault];
 
     if (!_assistedNodeInformation.formAction.isEmpty())
-        [_traits setReturnKeyType:(_assistedNodeInformation.elementType == InputType::Search) ? UIReturnKeySearch : UIReturnKeyGo];
+        [_traits setReturnKeyType:(_assistedNodeInformation.elementType == WebKit::InputType::Search) ? UIReturnKeySearch : UIReturnKeyGo];
 
-    if (_assistedNodeInformation.elementType == InputType::Password || _assistedNodeInformation.elementType == InputType::Email || _assistedNodeInformation.elementType == InputType::URL || _assistedNodeInformation.formAction.contains("login")) {
+    if (_assistedNodeInformation.elementType == WebKit::InputType::Password || _assistedNodeInformation.elementType == WebKit::InputType::Email || _assistedNodeInformation.elementType == WebKit::InputType::URL || _assistedNodeInformation.formAction.contains("login")) {
         [_traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
         [_traits setAutocorrectionType:UITextAutocorrectionTypeNo];
     } else {
@@ -3595,69 +3807,72 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     }
 
     switch (_assistedNodeInformation.inputMode) {
-    case InputMode::Unspecified:
+    case WebCore::InputMode::Unspecified:
         switch (_assistedNodeInformation.elementType) {
-        case InputType::Phone:
+        case WebKit::InputType::Phone:
             [_traits setKeyboardType:UIKeyboardTypePhonePad];
             break;
-        case InputType::URL:
+        case WebKit::InputType::URL:
             [_traits setKeyboardType:UIKeyboardTypeURL];
             break;
-        case InputType::Email:
+        case WebKit::InputType::Email:
             [_traits setKeyboardType:UIKeyboardTypeEmailAddress];
             break;
-        case InputType::Number:
+        case WebKit::InputType::Number:
             [_traits setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
             break;
-        case InputType::NumberPad:
+        case WebKit::InputType::NumberPad:
             [_traits setKeyboardType:UIKeyboardTypeNumberPad];
             break;
-        case InputType::None:
-        case InputType::ContentEditable:
-        case InputType::Text:
-        case InputType::Password:
-        case InputType::TextArea:
-        case InputType::Search:
-        case InputType::Date:
-        case InputType::DateTime:
-        case InputType::DateTimeLocal:
-        case InputType::Month:
-        case InputType::Week:
-        case InputType::Time:
-        case InputType::Select:
+        case WebKit::InputType::None:
+        case WebKit::InputType::ContentEditable:
+        case WebKit::InputType::Text:
+        case WebKit::InputType::Password:
+        case WebKit::InputType::TextArea:
+        case WebKit::InputType::Search:
+        case WebKit::InputType::Date:
+        case WebKit::InputType::DateTime:
+        case WebKit::InputType::DateTimeLocal:
+        case WebKit::InputType::Month:
+        case WebKit::InputType::Week:
+        case WebKit::InputType::Time:
+        case WebKit::InputType::Select:
+        case WebKit::InputType::Drawing:
 #if ENABLE(INPUT_TYPE_COLOR)
-        case InputType::Color:
+        case WebKit::InputType::Color:
 #endif
             [_traits setKeyboardType:UIKeyboardTypeDefault];
         }
         break;
-    case InputMode::None:
+    case WebCore::InputMode::None:
         break;
-    case InputMode::Text:
+    case WebCore::InputMode::Text:
         [_traits setKeyboardType:UIKeyboardTypeDefault];
         break;
-    case InputMode::Telephone:
+    case WebCore::InputMode::Telephone:
         [_traits setKeyboardType:UIKeyboardTypePhonePad];
         break;
-    case InputMode::Url:
+    case WebCore::InputMode::Url:
         [_traits setKeyboardType:UIKeyboardTypeURL];
         break;
-    case InputMode::Email:
+    case WebCore::InputMode::Email:
         [_traits setKeyboardType:UIKeyboardTypeEmailAddress];
         break;
-    case InputMode::Numeric:
+    case WebCore::InputMode::Numeric:
         [_traits setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
         break;
-    case InputMode::Decimal:
+    case WebCore::InputMode::Decimal:
         [_traits setKeyboardType:UIKeyboardTypeDecimalPad];
         break;
-    case InputMode::Search:
+    case WebCore::InputMode::Search:
         [_traits setKeyboardType:UIKeyboardTypeWebSearch];
         break;
     }
 
     [_traits setTextContentType:contentTypeFromFieldName(_assistedNodeInformation.autofillFieldName)];
 
+    [self _updateInteractionTintColor];
+
     return _traits.get();
 }
 
@@ -3666,15 +3881,8 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     return _textSelectionAssistant.get();
 }
 
-- (UIWebSelectionAssistant *)webSelectionAssistant
-{
-    return _webSelectionAssistant.get();
-}
-
 - (id<UISelectionInteractionAssistant>)selectionInteractionAssistant
 {
-    if ([_webSelectionAssistant conformsToProtocol:@protocol(UISelectionInteractionAssistant)])
-        return (id<UISelectionInteractionAssistant>)_webSelectionAssistant.get();
     return nil;
 }
 
@@ -3725,9 +3933,11 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 
 - (void)_handleKeyUIEvent:(::UIEvent *)event
 {
+    bool isHardwareKeyboardEvent = !!event._hidEvent;
+
     // We only want to handle key event from the hardware keyboard when we are
     // first responder and we are not interacting with editable content.
-    if ([self isFirstResponder] && event._hidEvent && !_page->editorState().isContentEditable) {
+    if ([self isFirstResponder] && isHardwareKeyboardEvent && !_page->editorState().isContentEditable) {
         [self handleKeyEvent:event];
         return;
     }
@@ -3741,42 +3951,32 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     if (event == _uiEventBeingResent)
         return;
 
-    WKWebEvent *webEvent = [[[WKWebEvent alloc] initWithKeyEventType:(event._isKeyDown) ? WebEventKeyDown : WebEventKeyUp
-                                                           timeStamp:event.timestamp
-                                                          characters:event._modifiedInput
-                                         charactersIgnoringModifiers:event._unmodifiedInput
-                                                           modifiers:event._modifierFlags
-                                                         isRepeating:(event._inputFlags & kUIKeyboardInputRepeat)
-                                                           withFlags:event._inputFlags
-                                                             keyCode:0
-                                                            isTabKey:[event._modifiedInput isEqualToString:@"\t"]
-                                                        characterSet:WebEventCharacterSetUnicode] autorelease];
-    webEvent.uiEvent = event;
+    auto webEvent = adoptNS([[WKWebEvent alloc] initWithEvent:event]);
     
-    [self handleKeyWebEvent:webEvent];    
+    [self handleKeyWebEvent:webEvent.get()];
 }
 
 - (void)handleKeyWebEvent:(::WebEvent *)theEvent
 {
-    if ([_keyboardScrollingAnimator handleKeyEvent:theEvent])
-        return;
-
-    _page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent));
+    _page->handleKeyboardEvent(WebKit::NativeWebKeyboardEvent(theEvent));
 }
 
 - (void)handleKeyWebEvent:(::WebEvent *)theEvent withCompletionHandler:(void (^)(::WebEvent *theEvent, BOOL wasHandled))completionHandler
 {
     _keyWebEventHandler = makeBlockPtr(completionHandler);
-    _page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent));
+    _page->handleKeyboardEvent(WebKit::NativeWebKeyboardEvent(theEvent));
 }
 
 - (void)_didHandleKeyEvent:(::WebEvent *)event eventWasHandled:(BOOL)eventWasHandled
 {
+    if (!(event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged))
+        [_keyboardScrollingAnimator handleKeyEvent:event];
+    
     if (auto handler = WTFMove(_keyWebEventHandler)) {
         handler(event, eventWasHandled);
         return;
     }
-        
+
     // If we aren't interacting with editable content, we still need to call [super _handleKeyUIEvent:]
     // so that keyboard repeat will work correctly. If we are interacting with editable content,
     // we already did so in _handleKeyUIEvent.
@@ -3803,9 +4003,11 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     static const unsigned kWebBackspaceKey = 0x0008;
     static const unsigned kWebReturnKey = 0x000D;
     static const unsigned kWebDeleteKey = 0x007F;
-    static const unsigned kWebDeleteForwardKey = 0xF728;
     static const unsigned kWebSpaceKey = 0x20;
 
+    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged)
+        return NO;
+
     BOOL contentEditable = _page->editorState().isContentEditable;
 
     if (!contentEditable && event.isTabKey)
@@ -3815,8 +4017,13 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
         return YES;
 
     UIKeyboardImpl *keyboard = [UIKeyboardImpl sharedInstance];
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
+    if (event.type == WebEventKeyDown && [keyboard respondsToSelector:@selector(handleKeyCommandForCurrentEvent)] && [keyboard handleKeyCommandForCurrentEvent])
+        return YES;
+#endif
+
     NSString *characters = event.characters;
-    
     if (!characters.length)
         return NO;
 
@@ -3845,10 +4052,6 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
         }
         break;
 
-    case kWebDeleteForwardKey:
-        _page->executeEditCommand("deleteForward"_s);
-        return YES;
-
     default:
         if (contentEditable && isCharEvent) {
             [keyboard addInputString:event.characters withFlags:event.keyboardFlags withInputManagerHint:event.inputManagerHint];
@@ -3860,34 +4063,39 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     return NO;
 }
 
-- (BOOL)isKeyboardScrollable
+- (BOOL)isScrollableForKeyboardScrollViewAnimator:(WKKeyboardScrollViewAnimator *)animator
 {
     if (_page->editorState().isContentEditable)
         return NO;
 
-    if (_assistedNodeInformation.elementType == InputType::Select)
+    if (_assistedNodeInformation.elementType == WebKit::InputType::Select)
         return NO;
 
     return YES;
 }
 
-- (CGFloat)distanceForScrollingIncrement:(ScrollingIncrement)increment
+- (CGFloat)keyboardScrollViewAnimator:(WKKeyboardScrollViewAnimator *)animator distanceForIncrement:(WebKit::ScrollingIncrement)increment
 {
     switch (increment) {
-    case ScrollingIncrement::Document:
-        return self.bounds.size.height;
-    case ScrollingIncrement::Page:
-        return WebCore::Scrollbar::pageStep(_page->unobscuredContentRect().height(), self.bounds.size.height);
-    case ScrollingIncrement::Line:
-        return WebCore::Scrollbar::pixelsPerLineStep();
+    case WebKit::ScrollingIncrement::Document:
+        return [self convertRect:self.bounds toView:_webView].size.height;
+    case WebKit::ScrollingIncrement::Page:
+        return [self convertSize:CGSizeMake(0, WebCore::Scrollbar::pageStep(_page->unobscuredContentRect().height(), self.bounds.size.height)) toView:_webView].height;
+    case WebKit::ScrollingIncrement::Line:
+        return [self convertSize:CGSizeMake(0, WebCore::Scrollbar::pixelsPerLineStep()) toView:_webView].height;
     }
     ASSERT_NOT_REACHED();
     return 0;
 }
 
-- (void)scrollByContentOffset:(WebCore::FloatPoint)offset animated:(BOOL)animated
+- (void)keyboardScrollViewAnimatorWillScroll:(WKKeyboardScrollViewAnimator *)animator
+{
+    [self willStartZoomOrScroll];
+}
+
+- (void)keyboardScrollViewAnimatorDidFinishScrolling:(WKKeyboardScrollViewAnimator *)animator
 {
-    [_webView _scrollByContentOffset:offset animated:animated];
+    [_webView _didFinishScrolling];
 }
 
 - (void)executeEditCommandWithCallback:(NSString *)commandName
@@ -3899,6 +4107,26 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     });
 }
 
+- (void)_deleteByWord
+{
+    [self executeEditCommandWithCallback:@"deleteWordBackward"];
+}
+
+- (void)_deleteToStartOfLine
+{
+    [self executeEditCommandWithCallback:@"deleteToBeginningOfLine"];
+}
+
+- (void)_deleteToEndOfLine
+{
+    [self executeEditCommandWithCallback:@"deleteToEndOfLine"];
+}
+
+- (void)_deleteForwardAndNotify:(BOOL)notify
+{
+    [self executeEditCommandWithCallback:@"deleteForward"];
+}
+
 - (UITextInputArrowKeyHistory *)_moveUp:(BOOL)extending withHistory:(UITextInputArrowKeyHistory *)history
 {
     [self executeEditCommandWithCallback:extending ? @"moveUpAndModifySelection" : @"moveUp"];
@@ -4091,9 +4319,9 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 
 - (void)_startAssistingKeyboard
 {
-    [self useSelectionAssistantWithGranularity:WKSelectionGranularityCharacter];
+    [self setUpTextSelectionAssistant];
     
-    if (self.isFirstResponder && !self.suppressAssistantSelectionView)
+    if (self.isFirstResponder && !_suppressSelectionAssistantReasons)
         [_textSelectionAssistant activateSelection];
 
 #if !PLATFORM(WATCHOS)
@@ -4103,17 +4331,18 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
 
 - (void)_stopAssistingKeyboard
 {
-    [self useSelectionAssistantWithGranularity:_webView._selectionGranularity];
+    self.inputDelegate = nil;
+    [self setUpTextSelectionAssistant];
     
     [_textSelectionAssistant deactivateSelection];
 }
 
-- (const AssistedNodeInformation&)assistedNodeInformation
+- (const WebKit::AssistedNodeInformation&)assistedNodeInformation
 {
     return _assistedNodeInformation;
 }
 
-- (Vector<OptionItem>&)assistedNodeSelectOptions
+- (Vector<WebKit::OptionItem>&)assistedNodeSelectOptions
 {
     return _assistedNodeInformation.selectOptions;
 }
@@ -4124,32 +4353,33 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     return _formAccessoryView.get();
 }
 
-static bool isAssistableInputType(InputType type)
+static bool isAssistableInputType(WebKit::InputType type)
 {
     switch (type) {
-    case InputType::ContentEditable:
-    case InputType::Text:
-    case InputType::Password:
-    case InputType::TextArea:
-    case InputType::Search:
-    case InputType::Email:
-    case InputType::URL:
-    case InputType::Phone:
-    case InputType::Number:
-    case InputType::NumberPad:
-    case InputType::Date:
-    case InputType::DateTime:
-    case InputType::DateTimeLocal:
-    case InputType::Month:
-    case InputType::Week:
-    case InputType::Time:
-    case InputType::Select:
+    case WebKit::InputType::ContentEditable:
+    case WebKit::InputType::Text:
+    case WebKit::InputType::Password:
+    case WebKit::InputType::TextArea:
+    case WebKit::InputType::Search:
+    case WebKit::InputType::Email:
+    case WebKit::InputType::URL:
+    case WebKit::InputType::Phone:
+    case WebKit::InputType::Number:
+    case WebKit::InputType::NumberPad:
+    case WebKit::InputType::Date:
+    case WebKit::InputType::DateTime:
+    case WebKit::InputType::DateTimeLocal:
+    case WebKit::InputType::Month:
+    case WebKit::InputType::Week:
+    case WebKit::InputType::Time:
+    case WebKit::InputType::Select:
+    case WebKit::InputType::Drawing:
 #if ENABLE(INPUT_TYPE_COLOR)
-    case InputType::Color:
+    case WebKit::InputType::Color:
 #endif
         return true;
 
-    case InputType::None:
+    case WebKit::InputType::None:
         return false;
     }
 
@@ -4157,7 +4387,7 @@ static bool isAssistableInputType(InputType type)
     return false;
 }
 
-- (void)_startAssistingNode:(const AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode changingActivityState:(BOOL)changingActivityState userObject:(NSObject <NSSecureCoding> *)userObject
+- (void)_startAssistingNode:(const WebKit::AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode changingActivityState:(BOOL)changingActivityState userObject:(NSObject <NSSecureCoding> *)userObject
 {
     SetForScope<BOOL> isChangingFocusForScope { _isChangingFocus, hasAssistedNode(_assistedNodeInformation) };
     _inputViewUpdateDeferrer = nullptr;
@@ -4178,6 +4408,11 @@ static bool isAssistableInputType(InputType type)
     if ([inputDelegate respondsToSelector:@selector(_webView:decidePolicyForFocusedElement:)])
         startInputSessionPolicy = [inputDelegate _webView:_webView decidePolicyForFocusedElement:focusedElementInfo.get()];
 
+    if (information.elementIsTransparent)
+        [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparent];
+    else
+        [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparent];
+
     switch (startInputSessionPolicy) {
     case _WKFocusStartsInputSessionPolicyAuto:
         // The default behavior is to allow node assistance if the user is interacting.
@@ -4187,6 +4422,7 @@ static bool isAssistableInputType(InputType type)
             || (_isChangingFocus && ![_focusedFormControlView isHidden])
 #else
             || _isChangingFocus
+            || [UIKeyboard isInHardwareKeyboardMode]
 #endif
 #if ENABLE(DRAG_SUPPORT)
             || _dragDropInteractionState.isPerformingDrop()
@@ -4251,13 +4487,13 @@ static bool isAssistableInputType(InputType type)
 #endif
     
     switch (information.elementType) {
-    case InputType::Select:
-    case InputType::DateTimeLocal:
-    case InputType::Time:
-    case InputType::Month:
-    case InputType::Date:
+    case WebKit::InputType::Select:
+    case WebKit::InputType::DateTimeLocal:
+    case WebKit::InputType::Time:
+    case WebKit::InputType::Month:
+    case WebKit::InputType::Date:
 #if ENABLE(INPUT_TYPE_COLOR)
-    case InputType::Color:
+    case WebKit::InputType::Color:
 #endif
         break;
     default:
@@ -4292,9 +4528,14 @@ static bool isAssistableInputType(InputType type)
     [_formInputSession invalidate];
     _formInputSession = nil;
 
+#if ENABLE(DATALIST_ELEMENT)
+    _dataListTextSuggestionsInputView = nil;
+    _dataListTextSuggestions = nil;
+#endif
+
     BOOL editableChanged = [self setIsEditable:NO];
 
-    _assistedNodeInformation.elementType = InputType::None;
+    _assistedNodeInformation.elementType = WebKit::InputType::None;
     _inputPeripheral = nil;
     _focusRequiresStrongPasswordAssistance = NO;
 
@@ -4302,8 +4543,6 @@ static bool isAssistableInputType(InputType type)
     [_formAccessoryView hideAutoFillButton];
     [self reloadInputViews];
     [self _updateAccessory];
-    // The name is misleading, but this actually clears the selection views and removes any selection.
-    [_webSelectionAssistant resignedFirstResponder];
 
 #if PLATFORM(WATCHOS)
     [self dismissAllInputViewControllers:YES];
@@ -4316,6 +4555,25 @@ static bool isAssistableInputType(InputType type)
         [_webView _scheduleVisibleContentRectUpdate];
 
     [_webView didEndFormControlInteraction];
+
+    [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparent];
+}
+
+- (void)_didReceiveEditorStateUpdateAfterFocus
+{
+    if (!_page->isEditable())
+        return;
+
+    auto& editorState = _page->editorState();
+    if (editorState.selectionIsNone || editorState.selectionIsRange)
+        return;
+
+    UIKeyboardImpl *keyboard = UIKeyboardImpl.activeInstance;
+    if (keyboard.delegate != self)
+        return;
+
+    // Synchronize the keyboard's writing direction with the newly received EditorState.
+    [keyboard setInitialDirection];
 }
 
 - (void)updateCurrentAssistedNodeInformation:(Function<void(bool didUpdate)>&&)callback
@@ -4323,7 +4581,7 @@ static bool isAssistableInputType(InputType type)
     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 (!weakSelf || error != WebKit::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;
@@ -4382,19 +4640,19 @@ static bool isAssistableInputType(InputType type)
     BOOL prefersModalPresentation = NO;
 
     switch (_assistedNodeInformation.elementType) {
-    case InputType::Select:
+    case WebKit::InputType::Select:
         _presentedFullScreenInputViewController = adoptNS([[WKSelectMenuListViewController alloc] initWithDelegate:self]);
         break;
-    case InputType::Time:
+    case WebKit::InputType::Time:
         // Time inputs are special, in that the only UI affordances for dismissal are push buttons rather than status bar chevrons.
         // As such, modal presentation and dismissal is preferred even if a navigation stack exists.
         prefersModalPresentation = YES;
         _presentedFullScreenInputViewController = adoptNS([[WKTimePickerViewController alloc] initWithDelegate:self]);
         break;
-    case InputType::Date:
+    case WebKit::InputType::Date:
         _presentedFullScreenInputViewController = adoptNS([[WKDatePickerViewController alloc] initWithDelegate:self]);
         break;
-    case InputType::None:
+    case WebKit::InputType::None:
         break;
     default:
         _presentedFullScreenInputViewController = adoptNS([[WKTextInputListViewController alloc] initWithDelegate:self]);
@@ -4513,17 +4771,17 @@ static bool isAssistableInputType(InputType type)
         return nil;
 
     switch (_assistedNodeInformation.elementType) {
-    case InputType::Select:
-    case InputType::Time:
-    case InputType::Date:
+    case WebKit::InputType::Select:
+    case WebKit::InputType::Time:
+    case WebKit::InputType::Date:
 #if ENABLE(INPUT_TYPE_COLOR)
-    case InputType::Color:
+    case WebKit::InputType::Color:
 #endif
         return nil;
-    case InputType::Search:
-        return formControlSearchButtonTitle();
+    case WebKit::InputType::Search:
+        return WebCore::formControlSearchButtonTitle();
     default:
-        return formControlGoButtonTitle();
+        return WebCore::formControlGoButtonTitle();
     }
 }
 
@@ -4638,7 +4896,7 @@ static bool isAssistableInputType(InputType type)
 
 - (void)selectWordForReplacement
 {
-    _page->extendSelection(WordGranularity);
+    _page->extendSelection(WebCore::WordGranularity);
 }
 
 - (void)_updateChangedSelection
@@ -4648,10 +4906,19 @@ static bool isAssistableInputType(InputType type)
 
 - (void)_updateChangedSelection:(BOOL)force
 {
-    if (!_selectionNeedsUpdate || _page->editorState().isMissingPostLayoutData)
+    auto& state = _page->editorState();
+    if (state.isMissingPostLayoutData)
         return;
 
-    WKSelectionDrawingInfo selectionDrawingInfo(_page->editorState());
+    auto& postLayoutData = state.postLayoutData();
+    if (hasAssistedNode(_assistedNodeInformation)) {
+        if (postLayoutData.elementIsTransparent)
+            [self _beginSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparent];
+        else
+            [self _stopSuppressingSelectionAssistantForReason:WebKit::FocusedElementIsTransparent];
+    }
+
+    WebKit::WKSelectionDrawingInfo selectionDrawingInfo(_page->editorState());
     if (force || selectionDrawingInfo != _lastSelectionDrawingInfo) {
         LOG_WITH_STREAM(Selection, stream << "_updateChangedSelection " << selectionDrawingInfo);
 
@@ -4662,26 +4929,19 @@ static bool isAssistableInputType(InputType type)
             _markedText = (_page->editorState().hasComposition) ? _page->editorState().markedText : String();
             if (!_showingTextStyleOptions)
                 [_textSelectionAssistant selectionChanged];
-        } else if (!_page->editorState().isContentEditable)
-            [_webSelectionAssistant selectionChanged];
+        }
 
         _selectionNeedsUpdate = NO;
         if (_shouldRestoreSelection) {
-            [_webSelectionAssistant didEndScrollingOverflow];
             [_textSelectionAssistant didEndScrollingOverflow];
             _shouldRestoreSelection = NO;
         }
     }
 
-    auto& state = _page->editorState();
-    if (!state.isMissingPostLayoutData && state.postLayoutData().isStableStateUpdate && _needsDeferredEndScrollingSelectionUpdate && _page->inStableState()) {
+    if (postLayoutData.isStableStateUpdate && _needsDeferredEndScrollingSelectionUpdate && _page->inStableState()) {
         [[self selectionInteractionAssistant] showSelectionCommands];
-        [_webSelectionAssistant didEndScrollingOrZoomingPage];
-#if !PLATFORM(IOSMAC)
-        [[_webSelectionAssistant selectionView] setHidden:NO];
-#endif
 
-        if (!self.suppressAssistantSelectionView)
+        if (!_suppressSelectionAssistantReasons)
             [_textSelectionAssistant activateSelection];
 
         [_textSelectionAssistant didEndScrollingOverflow];
@@ -4690,33 +4950,92 @@ static bool isAssistableInputType(InputType type)
     }
 }
 
-- (BOOL)suppressAssistantSelectionView
+- (BOOL)_shouldSuppressSelectionCommands
+{
+    return !!_suppressSelectionAssistantReasons;
+}
+
+- (void)_beginSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason
+{
+    bool wasSuppressingSelectionAssistant = !!_suppressSelectionAssistantReasons;
+    _suppressSelectionAssistantReasons.add(reason);
+
+    if (!wasSuppressingSelectionAssistant)
+        [_textSelectionAssistant deactivateSelection];
+}
+
+- (void)_stopSuppressingSelectionAssistantForReason:(WebKit::SuppressSelectionAssistantReason)reason
 {
-    return _suppressAssistantSelectionView;
+    bool wasSuppressingSelectionAssistant = !!_suppressSelectionAssistantReasons;
+    _suppressSelectionAssistantReasons.remove(reason);
+
+    if (wasSuppressingSelectionAssistant && !_suppressSelectionAssistantReasons)
+        [_textSelectionAssistant activateSelection];
 }
 
-- (void)setSuppressAssistantSelectionView:(BOOL)suppressAssistantSelectionView
+#if ENABLE(DATALIST_ELEMENT)
+
+- (UIView <WKFormControl> *)dataListTextSuggestionsInputView
 {
-    if (_suppressAssistantSelectionView == suppressAssistantSelectionView)
+    return _dataListTextSuggestionsInputView.get();
+}
+
+- (NSArray<UITextSuggestion *> *)dataListTextSuggestions
+{
+    return _dataListTextSuggestions.get();
+}
+
+- (void)setDataListTextSuggestionsInputView:(UIView <WKFormControl> *)suggestionsInputView
+{
+    if (_dataListTextSuggestionsInputView == suggestionsInputView)
         return;
 
-    _suppressAssistantSelectionView = suppressAssistantSelectionView;
-    if (!_textSelectionAssistant)
+    _dataListTextSuggestionsInputView = suggestionsInputView;
+
+    if (![_formInputSession customInputView])
+        [self reloadInputViews];
+}
+
+- (void)setDataListTextSuggestions:(NSArray<UITextSuggestion *> *)textSuggestions
+{
+    if (textSuggestions == _dataListTextSuggestions || [textSuggestions isEqualToArray:_dataListTextSuggestions.get()])
         return;
 
-    if (suppressAssistantSelectionView)
-        [_textSelectionAssistant deactivateSelection];
-    else
-        [_textSelectionAssistant activateSelection];
+    _dataListTextSuggestions = textSuggestions;
+
+    if (![_formInputSession suggestions].count)
+        [self updateTextSuggestionsForInputDelegate];
 }
 
-- (void)_showPlaybackTargetPicker:(BOOL)hasVideo fromRect:(const IntRect&)elementRect routeSharingPolicy:(WebCore::RouteSharingPolicy)routeSharingPolicy routingContextUID:(NSString *)routingContextUID
+#endif
+
+- (void)updateTextSuggestionsForInputDelegate
+{
+    // Text suggestions vended from clients take precedence over text suggestions from a focused form control with a datalist.
+    id <UITextInputSuggestionDelegate> inputDelegate = (id <UITextInputSuggestionDelegate>)self.inputDelegate;
+    NSArray<UITextSuggestion *> *formInputSessionSuggestions = [_formInputSession suggestions];
+    if (formInputSessionSuggestions.count) {
+        [inputDelegate setSuggestions:formInputSessionSuggestions];
+        return;
+    }
+
+#if ENABLE(DATALIST_ELEMENT)
+    if ([_dataListTextSuggestions count]) {
+        [inputDelegate setSuggestions:_dataListTextSuggestions.get()];
+        return;
+    }
+#endif
+
+    [inputDelegate setSuggestions:nil];
+}
+
+- (void)_showPlaybackTargetPicker:(BOOL)hasVideo fromRect:(const WebCore::IntRect&)elementRect routeSharingPolicy:(WebCore::RouteSharingPolicy)routeSharingPolicy routingContextUID:(NSString *)routingContextUID
 {
 #if ENABLE(AIRPLAY_PICKER)
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000 && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
     if (!_airPlayRoutePicker)
         _airPlayRoutePicker = adoptNS([[WKAirPlayRoutePicker alloc] init]);
-    [_airPlayRoutePicker showFromView:self routeSharingPolicy:routeSharingPolicy routingContextUID:routingContextUID];
+    [_airPlayRoutePicker showFromView:self routeSharingPolicy:routeSharingPolicy routingContextUID:routingContextUID hasVideo:hasVideo];
 #else
     if (!_airPlayRoutePicker)
         _airPlayRoutePicker = adoptNS([[WKAirPlayRoutePicker alloc] initWithView:self]);
@@ -4725,13 +5044,20 @@ static bool isAssistableInputType(InputType type)
 #endif
 }
 
-- (void)_showRunOpenPanel:(API::OpenPanelParameters*)parameters resultListener:(WebOpenPanelResultListenerProxy*)listener
+- (void)_showRunOpenPanel:(API::OpenPanelParameters*)parameters resultListener:(WebKit::WebOpenPanelResultListenerProxy*)listener
 {
     ASSERT(!_fileUploadPanel);
     if (_fileUploadPanel)
         return;
 
-    _fileUploadPanel = adoptNS([[WKFileUploadPanel alloc] initWithView:self]);
+    Class ownClass = self.class;
+    Class panelClass = nil;
+    if ([ownClass respondsToSelector:@selector(_fileUploadPanelClass)])
+        panelClass = [ownClass _fileUploadPanelClass];
+    if (!panelClass)
+        panelClass = [WKFileUploadPanel class];
+
+    _fileUploadPanel = adoptNS([[panelClass alloc] initWithView:self]);
     [_fileUploadPanel setDelegate:self];
     [_fileUploadPanel presentWithParameters:parameters resultListener:listener];
 }
@@ -4744,14 +5070,13 @@ static bool isAssistableInputType(InputType type)
     _fileUploadPanel = nil;
 }
 
-- (void)_showShareSheet:(const ShareDataWithParsedURL&)data completionHandler:(CompletionHandler<void(bool)>&&)completionHandler
+- (void)_showShareSheet:(const WebCore::ShareDataWithParsedURL&)data completionHandler:(CompletionHandler<void(bool)>&&)completionHandler
 {
 #if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
-    ASSERT(!_shareSheet);
     if (_shareSheet)
-        return;
+        [_shareSheet dismiss];
     
-    _shareSheet = adoptNS([[WKShareSheet alloc] initWithView:self]);
+    _shareSheet = adoptNS([[WKShareSheet alloc] initWithView:_webView]);
     [_shareSheet setDelegate:self];
     
     [_shareSheet presentWithParameters:data completionHandler:WTFMove(completionHandler)];
@@ -4824,7 +5149,7 @@ static bool isAssistableInputType(InputType type)
 
 - (std::optional<WebKit::InteractionInformationAtPosition>)positionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant
 {
-    InteractionInformationRequest request(_positionInformation.request.point);
+    WebKit::InteractionInformationRequest request(_positionInformation.request.point);
     request.includeSnapshot = true;
     request.includeLinkIndicator = assistant.needsLinkIndicator;
     if (![self ensurePositionInformationIsUpToDate:request])
@@ -4836,7 +5161,7 @@ static bool isAssistableInputType(InputType type)
 - (void)updatePositionInformationForActionSheetAssistant:(WKActionSheetAssistant *)assistant
 {
     _hasValidPositionInformation = NO;
-    InteractionInformationRequest request(_positionInformation.request.point);
+    WebKit::InteractionInformationRequest request(_positionInformation.request.point);
     request.includeSnapshot = true;
     request.includeLinkIndicator = assistant.needsLinkIndicator;
 
@@ -4856,9 +5181,7 @@ static bool isAssistableInputType(InputType type)
 - (void)actionSheetAssistant:(WKActionSheetAssistant *)assistant shareElementWithURL:(NSURL *)url rect:(CGRect)boundingRect
 {
     if (_textSelectionAssistant)
-        [_textSelectionAssistant showShareSheetFor:userVisibleString(url) fromRect:boundingRect];
-    else if (_webSelectionAssistant)
-        [_webSelectionAssistant showShareSheetFor:userVisibleString(url) fromRect:boundingRect];
+        [_textSelectionAssistant showShareSheetFor:WTF::userVisibleString(url) fromRect:boundingRect];
 }
 
 #if HAVE(APP_LINKS)
@@ -5000,9 +5323,9 @@ static BOOL shouldEnableDragInteractionForPolicy(_WKDragInteractionPolicy policy
     [self cleanUpDragSourceSessionState];
 }
 
-- (void)_startDrag:(RetainPtr<CGImageRef>)image item:(const DragItem&)item
+- (void)_startDrag:(RetainPtr<CGImageRef>)image item:(const WebCore::DragItem&)item
 {
-    ASSERT(item.sourceAction != DragSourceActionNone);
+    ASSERT(item.sourceAction != WebCore::DragSourceActionNone);
 
     if (item.promisedAttachmentInfo)
         [self _prepareToDragPromisedAttachment:item.promisedAttachmentInfo];
@@ -5028,7 +5351,7 @@ static BOOL shouldEnableDragInteractionForPolicy(_WKDragInteractionPolicy policy
     NSArray *dragItemsToAdd = [self _itemsForBeginningOrAddingToSessionWithRegistrationList:registrationList stagedDragSource:stagedDragSource];
 
     RELEASE_LOG(DragAndDrop, "Drag session: %p adding %tu items", _dragDropInteractionState.dragSession(), dragItemsToAdd.count);
-    _dragDropInteractionState.clearStagedDragSource(dragItemsToAdd.count ? DragDropInteractionState::DidBecomeActive::Yes : DragDropInteractionState::DidBecomeActive::No);
+    _dragDropInteractionState.clearStagedDragSource(dragItemsToAdd.count ? WebKit::DragDropInteractionState::DidBecomeActive::Yes : WebKit::DragDropInteractionState::DidBecomeActive::No);
 
     completion(dragItemsToAdd);
 
@@ -5046,12 +5369,12 @@ static BOOL shouldEnableDragInteractionForPolicy(_WKDragInteractionPolicy policy
         savedCompletionBlock();
 
     if (!_dragDropInteractionState.dragSession().items.count) {
-        auto positionForDragEnd = roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd());
+        auto positionForDragEnd = WebCore::roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd());
         [self cleanUpDragSourceSessionState];
         if (started) {
             // A client of the Objective C SPI or UIKit might have prevented the drag from beginning entirely in the UI process, in which case
             // we need to balance the `dragstart` event with a `dragend`.
-            _page->dragEnded(positionForDragEnd, positionForDragEnd, DragOperationNone);
+            _page->dragEnded(positionForDragEnd, positionForDragEnd, WebCore::DragOperationNone);
         }
     }
 }
@@ -5069,25 +5392,25 @@ static BOOL shouldEnableDragInteractionForPolicy(_WKDragInteractionPolicy policy
         *outGlobalPoint = locationInContentView;
 }
 
-static UIDropOperation dropOperationForWebCoreDragOperation(DragOperation operation)
+static UIDropOperation dropOperationForWebCoreDragOperation(WebCore::DragOperation operation)
 {
-    if (operation & DragOperationMove)
+    if (operation & WebCore::DragOperationMove)
         return UIDropOperationMove;
 
-    if (operation & DragOperationCopy)
+    if (operation & WebCore::DragOperationCopy)
         return UIDropOperationCopy;
 
     return UIDropOperationCancel;
 }
 
-- (DragData)dragDataForDropSession:(id <UIDropSession>)session dragDestinationAction:(WKDragDestinationAction)dragDestinationAction
+- (WebCore::DragData)dragDataForDropSession:(id <UIDropSession>)session dragDestinationAction:(WKDragDestinationAction)dragDestinationAction
 {
     CGPoint global;
     CGPoint client;
     [self computeClientAndGlobalPointsForDropSession:session outClientPoint:&client outGlobalPoint:&global];
 
-    DragOperation dragOperationMask = static_cast<DragOperation>(session.allowsMoveOperation ? DragOperationEvery : (DragOperationEvery & ~DragOperationMove));
-    return { session, roundedIntPoint(client), roundedIntPoint(global), dragOperationMask, DragApplicationNone, static_cast<DragDestinationAction>(dragDestinationAction) };
+    WebCore::DragOperation dragOperationMask = static_cast<WebCore::DragOperation>(session.allowsMoveOperation ? WebCore::DragOperationEvery : (WebCore::DragOperationEvery & ~WebCore::DragOperationMove));
+    return { session, WebCore::roundedIntPoint(client), WebCore::roundedIntPoint(global), dragOperationMask, WebCore::DragApplicationNone, static_cast<WebCore::DragDestinationAction>(dragDestinationAction) };
 }
 
 - (void)cleanUpDragSourceSessionState
@@ -5115,23 +5438,22 @@ static UIDropOperation dropOperationForWebCoreDragOperation(DragOperation operat
     _dragDropInteractionState = { };
 }
 
-static NSArray<UIItemProvider *> *extractItemProvidersFromDragItems(NSArray<UIDragItem *> *dragItems)
+static NSArray<NSItemProvider *> *extractItemProvidersFromDragItems(NSArray<UIDragItem *> *dragItems)
 {
-    NSMutableArray<UIItemProvider *> *providers = [NSMutableArray array];
+    NSMutableArray<NSItemProvider *> *providers = [NSMutableArray array];
     for (UIDragItem *item in dragItems) {
-        RetainPtr<UIItemProvider> provider = item.itemProvider;
-        if (provider)
-            [providers addObject:provider.get()];
+        if (NSItemProvider *provider = item.itemProvider)
+            [providers addObject:provider];
     }
     return providers;
 }
 
-static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDropSession> session)
+static NSArray<NSItemProvider *> *extractItemProvidersFromDropSession(id <UIDropSession> session)
 {
     return extractItemProvidersFromDragItems(session.items);
 }
 
-- (void)_didConcludeEditDataInteraction:(std::optional<TextIndicatorData>)data
+- (void)_didConcludeEditDataInteraction:(std::optional<WebCore::TextIndicatorData>)data
 {
     if (!data)
         return;
@@ -5158,7 +5480,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     } completion:^(BOOL completed) {
         [visibleContentViewSnapshot removeFromSuperview];
         [UIView animateWithDuration:0.25 animations:^() {
-            [protectedSelf setSuppressAssistantSelectionView:NO];
+            [protectedSelf _stopSuppressingSelectionAssistantForReason:WebKit::DropAnimationIsRunning];
             [unselectedContentSnapshot setAlpha:0];
         } completion:^(BOOL completed) {
             [unselectedContentSnapshot removeFromSuperview];
@@ -5175,13 +5497,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         [self.webViewUIDelegate _webView:_webView dataInteractionOperationWasHandled:handled forSession:dropSession itemProviders:[WebItemProviderPasteboard sharedInstance].itemProviders];
 
     if (!_isAnimatingConcludeEditDrag)
-        self.suppressAssistantSelectionView = NO;
+        [self _stopSuppressingSelectionAssistantForReason:WebKit::DropAnimationIsRunning];
 
     CGPoint global;
     CGPoint client;
     [self computeClientAndGlobalPointsForDropSession:dropSession outClientPoint:&client outGlobalPoint:&global];
     [self cleanUpDragSourceSessionState];
-    _page->dragEnded(roundedIntPoint(client), roundedIntPoint(global), _page->currentDragOperation());
+    _page->dragEnded(WebCore::roundedIntPoint(client), WebCore::roundedIntPoint(global), _page->currentDragOperation());
 }
 
 - (void)_didChangeDataInteractionCaretRect:(CGRect)previousRect currentRect:(CGRect)rect
@@ -5206,7 +5528,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     [_editDropCaretView updateToPosition:[WKTextPosition textPositionWithRect:rect]];
 }
 
-- (void)_prepareToDragPromisedAttachment:(const PromisedAttachmentInfo&)info
+- (void)_prepareToDragPromisedAttachment:(const WebCore::PromisedAttachmentInfo&)info
 {
     auto session = retainPtr(_dragDropInteractionState.dragSession());
     if (!session) {
@@ -5244,7 +5566,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
             return;
         }
 
-        NSString *temporaryBlobDirectory = FileSystem::createTemporaryDirectory(@"blobs");
+        NSString *temporaryBlobDirectory = WebCore::FileSystem::createTemporaryDirectory(@"blobs");
         NSURL *destinationURL = [NSURL fileURLWithPath:[temporaryBlobDirectory stringByAppendingPathComponent:[NSUUID UUID].UUIDString] isDirectory:NO];
 
         auto attachment = strongSelf->_page->attachmentForIdentifier(info.attachmentIdentifier);
@@ -5296,14 +5618,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         return;
 
     // FIXME: This SPI should be renamed in UIKit to reflect a more general purpose of revealing hidden interaction assistant controls.
-    [_webSelectionAssistant didEndScrollingOverflow];
     [_textSelectionAssistant didEndScrollingOverflow];
     _shouldRestoreCalloutBarAfterDrop = NO;
 }
 
-- (NSArray<UIDragItem *> *)_itemsForBeginningOrAddingToSessionWithRegistrationList:(WebItemProviderRegistrationInfoList *)registrationList stagedDragSource:(const DragSourceState&)stagedDragSource
+- (NSArray<UIDragItem *> *)_itemsForBeginningOrAddingToSessionWithRegistrationList:(WebItemProviderRegistrationInfoList *)registrationList stagedDragSource:(const WebKit::DragSourceState&)stagedDragSource
 {
-    UIItemProvider *defaultItemProvider = registrationList.itemProvider;
+    NSItemProvider *defaultItemProvider = registrationList.itemProvider;
     if (!defaultItemProvider)
         return @[ ];
 
@@ -5323,7 +5644,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         adjustedItemProviders = @[ defaultItemProvider ];
 
     NSMutableArray *dragItems = [NSMutableArray arrayWithCapacity:adjustedItemProviders.count];
-    for (UIItemProvider *itemProvider in adjustedItemProviders) {
+    for (NSItemProvider *itemProvider in adjustedItemProviders) {
         auto item = adoptNS([[UIDragItem alloc] initWithItemProvider:itemProvider]);
         [item _setPrivateLocalContext:@(stagedDragSource.itemIdentifier)];
         [dragItems addObject:item.autorelease()];
@@ -5334,7 +5655,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
 - (NSDictionary *)_autofillContext
 {
-    BOOL provideStrongPasswordAssistance = _focusRequiresStrongPasswordAssistance && _assistedNodeInformation.elementType == InputType::Password;
+    BOOL provideStrongPasswordAssistance = _focusRequiresStrongPasswordAssistance && _assistedNodeInformation.elementType == WebKit::InputType::Password;
     if (!hasAssistedNode(_assistedNodeInformation) || (!_assistedNodeInformation.acceptsAutofilledLoginCredentials && !provideStrongPasswordAssistance))
         return nil;
 
@@ -5379,7 +5700,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     }
 
     _dragDropInteractionState.dragSessionWillRequestAdditionalItem(completion);
-    _page->requestAdditionalItemsForDragSession(roundedIntPoint(point), roundedIntPoint(point));
+    _page->requestAdditionalItemsForDragSession(WebCore::roundedIntPoint(point), WebCore::roundedIntPoint(point));
 }
 
 - (void)_dragInteraction:(UIDragInteraction *)interaction prepareForSession:(id <UIDragSession>)session completion:(dispatch_block_t)completion
@@ -5398,8 +5719,8 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
     _dragDropInteractionState.prepareForDragSession(session, completion);
 
-    auto dragOrigin = roundedIntPoint([session locationInView:self]);
-    _page->requestStartDataInteraction(dragOrigin, roundedIntPoint([self convertPoint:dragOrigin toView:self.window]));
+    auto dragOrigin = WebCore::roundedIntPoint([session locationInView:self]);
+    _page->requestStartDataInteraction(dragOrigin, WebCore::roundedIntPoint([self convertPoint:dragOrigin toView:self.window]));
 
     RELEASE_LOG(DragAndDrop, "Drag session requested: %p at origin: {%d, %d}", session, dragOrigin.x(), dragOrigin.y());
 }
@@ -5425,7 +5746,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         _page->dragCancelled();
 
     RELEASE_LOG(DragAndDrop, "Drag session: %p starting with %tu items", session, [dragItems count]);
-    _dragDropInteractionState.clearStagedDragSource([dragItems count] ? DragDropInteractionState::DidBecomeActive::Yes : DragDropInteractionState::DidBecomeActive::No);
+    _dragDropInteractionState.clearStagedDragSource([dragItems count] ? WebKit::DragDropInteractionState::DidBecomeActive::Yes : WebKit::DragDropInteractionState::DidBecomeActive::No);
 
     return dragItems;
 }
@@ -5443,14 +5764,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
 - (void)dragInteraction:(UIDragInteraction *)interaction willAnimateLiftWithAnimator:(id <UIDragAnimating>)animator session:(id <UIDragSession>)session
 {
-    if (!_shouldRestoreCalloutBarAfterDrop && _dragDropInteractionState.anyActiveDragSourceIs(DragSourceActionSelection)) {
+    if (!_shouldRestoreCalloutBarAfterDrop && _dragDropInteractionState.anyActiveDragSourceIs(WebCore::DragSourceActionSelection)) {
         // FIXME: This SPI should be renamed in UIKit to reflect a more general purpose of hiding interaction assistant controls.
-        [_webSelectionAssistant willStartScrollingOverflow];
         [_textSelectionAssistant willStartScrollingOverflow];
         _shouldRestoreCalloutBarAfterDrop = YES;
     }
 
-    auto positionForDragEnd = roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd());
+    auto positionForDragEnd = WebCore::roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd());
     RetainPtr<WKContentView> protectedSelf(self);
     [animator addCompletion:[session, positionForDragEnd, protectedSelf, page = _page] (UIViewAnimatingPosition finalPosition) {
 #if RELEASE_LOG_DISABLED
@@ -5460,7 +5780,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
             RELEASE_LOG(DragAndDrop, "Drag session ended at start: %p", session);
             // The lift was canceled, so -dropInteraction:sessionDidEnd: will never be invoked. This is the last chance to clean up.
             [protectedSelf cleanUpDragSourceSessionState];
-            page->dragEnded(positionForDragEnd, positionForDragEnd, DragOperationNone);
+            page->dragEnded(positionForDragEnd, positionForDragEnd, WebCore::DragOperationNone);
         }
     }];
 }
@@ -5491,7 +5811,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         return;
 
     [self cleanUpDragSourceSessionState];
-    _page->dragEnded(roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd()), roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd()), operation);
+    _page->dragEnded(WebCore::roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd()), WebCore::roundedIntPoint(_dragDropInteractionState.adjustedPositionForDragEnd()), operation);
 }
 
 - (UITargetedDragPreview *)dragInteraction:(UIDragInteraction *)interaction previewForCancellingItem:(UIDragItem *)item withDefault:(UITargetedDragPreview *)defaultPreview
@@ -5516,7 +5836,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     [animator addCompletion:[protectedSelf = retainPtr(self), page = _page] (UIViewAnimatingPosition finalPosition) {
         page->dragCancelled();
         if (auto completion = protectedSelf->_dragDropInteractionState.takeDragCancelSetDownBlock()) {
-            page->callAfterNextPresentationUpdate([completion] (CallbackBase::Error) {
+            page->callAfterNextPresentationUpdate([completion] (WebKit::CallbackBase::Error) {
                 completion();
             });
         }
@@ -5567,11 +5887,18 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     _page->dragUpdated(dragData, "data interaction pasteboard");
     _dragDropInteractionState.dropSessionDidEnterOrUpdate(session, dragData);
 
-    NSUInteger operation = dropOperationForWebCoreDragOperation(_page->currentDragOperation());
-    if ([self.webViewUIDelegate respondsToSelector:@selector(_webView:willUpdateDataInteractionOperationToOperation:forSession:)])
-        operation = [self.webViewUIDelegate _webView:_webView willUpdateDataInteractionOperationToOperation:operation forSession:session];
+    auto delegate = self.webViewUIDelegate;
+    auto operation = dropOperationForWebCoreDragOperation(_page->currentDragOperation());
+    if ([delegate respondsToSelector:@selector(_webView:willUpdateDataInteractionOperationToOperation:forSession:)])
+        operation = static_cast<UIDropOperation>([delegate _webView:_webView willUpdateDataInteractionOperationToOperation:operation forSession:session]);
+
+    auto proposal = adoptNS([[UIDropProposal alloc] initWithDropOperation:static_cast<UIDropOperation>(operation)]);
+    auto dragHandlingMethod = _page->currentDragHandlingMethod();
+    [proposal setPrecise:dragHandlingMethod == WebCore::DragHandlingMethod::EditPlainText || dragHandlingMethod == WebCore::DragHandlingMethod::EditRichText];
+    if ([delegate respondsToSelector:@selector(_webView:willUpdateDropProposalToProposal:forSession:)])
+        proposal = [delegate _webView:_webView willUpdateDropProposalToProposal:proposal.get() forSession:session];
 
-    return [[[UIDropProposal alloc] initWithDropOperation:static_cast<UIDropOperation>(operation)] autorelease];
+    return proposal.autorelease();
 }
 
 - (void)dropInteraction:(UIDropInteraction *)interaction sessionDidExit:(id <UIDropSession>)session
@@ -5588,7 +5915,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
 - (void)dropInteraction:(UIDropInteraction *)interaction performDrop:(id <UIDropSession>)session
 {
-    NSArray <UIItemProvider *> *itemProviders = extractItemProvidersFromDropSession(session);
+    NSArray <NSItemProvider *> *itemProviders = extractItemProvidersFromDropSession(session);
     id <WKUIDelegatePrivate> uiDelegate = self.webViewUIDelegate;
     if ([uiDelegate respondsToSelector:@selector(_webView:performDataInteractionOperationWithItemProviders:)]) {
         if ([uiDelegate _webView:_webView performDataInteractionOperationWithItemProviders:itemProviders])
@@ -5620,13 +5947,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
             filenames.append([fileURL path]);
         capturedDragData.setFileNames(filenames);
 
-        SandboxExtension::Handle sandboxExtensionHandle;
-        SandboxExtension::HandleArray sandboxExtensionForUpload;
+        WebKit::SandboxExtension::Handle sandboxExtensionHandle;
+        WebKit::SandboxExtension::HandleArray sandboxExtensionForUpload;
         retainedSelf->_page->createSandboxExtensionsIfNeeded(filenames, sandboxExtensionHandle, sandboxExtensionForUpload);
         retainedSelf->_page->performDragOperation(capturedDragData, "data interaction pasteboard", WTFMove(sandboxExtensionHandle), WTFMove(sandboxExtensionForUpload));
 
         retainedSelf->_visibleContentViewSnapshot = [retainedSelf snapshotViewAfterScreenUpdates:NO];
-        [retainedSelf setSuppressAssistantSelectionView:YES];
+        [retainedSelf _beginSuppressingSelectionAssistantForReason:WebKit::DropAnimationIsRunning];
         [UIView performWithoutAnimation:[retainedSelf] {
             [retainedSelf->_visibleContentViewSnapshot setFrame:[retainedSelf bounds]];
             [retainedSelf addSubview:retainedSelf->_visibleContentViewSnapshot.get()];
@@ -5666,7 +5993,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     CGPoint client;
     [self computeClientAndGlobalPointsForDropSession:session outClientPoint:&client outGlobalPoint:&global];
     [self cleanUpDragSourceSessionState];
-    _page->dragEnded(roundedIntPoint(client), roundedIntPoint(global), DragOperationNone);
+    _page->dragEnded(WebCore::roundedIntPoint(client), WebCore::roundedIntPoint(global), WebCore::DragOperationNone);
 }
 
 #endif
@@ -5731,12 +6058,12 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 - (BOOL)allowsLanguageSelectionMenuForListViewController:(PUICQuickboardViewController *)controller
 {
     switch (_assistedNodeInformation.elementType) {
-    case InputType::ContentEditable:
-    case InputType::Text:
-    case InputType::TextArea:
-    case InputType::Search:
-    case InputType::Email:
-    case InputType::URL:
+    case WebKit::InputType::ContentEditable:
+    case WebKit::InputType::Text:
+    case WebKit::InputType::TextArea:
+    case WebKit::InputType::Search:
+    case WebKit::InputType::Email:
+    case WebKit::InputType::URL:
         return YES;
     default:
         return NO;
@@ -5774,14 +6101,14 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 - (BOOL)shouldDisplayInputContextViewForListViewController:(PUICQuickboardViewController *)controller
 {
     switch (_assistedNodeInformation.elementType) {
-    case InputType::ContentEditable:
-    case InputType::Text:
-    case InputType::Password:
-    case InputType::TextArea:
-    case InputType::Search:
-    case InputType::Email:
-    case InputType::URL:
-    case InputType::Phone:
+    case WebKit::InputType::ContentEditable:
+    case WebKit::InputType::Text:
+    case WebKit::InputType::Password:
+    case WebKit::InputType::TextArea:
+    case WebKit::InputType::Search:
+    case WebKit::InputType::Email:
+    case WebKit::InputType::URL:
+    case WebKit::InputType::Phone:
         return YES;
     default:
         return NO;
@@ -5793,11 +6120,11 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 - (WKNumberPadInputMode)numericInputModeForListViewController:(WKTextInputListViewController *)controller
 {
     switch (_assistedNodeInformation.elementType) {
-    case InputType::Phone:
+    case WebKit::InputType::Phone:
         return WKNumberPadInputModeTelephone;
-    case InputType::Number:
+    case WebKit::InputType::Number:
         return WKNumberPadInputModeNumbersAndSymbols;
-    case InputType::NumberPad:
+    case WebKit::InputType::NumberPad:
         return WKNumberPadInputModeNumbersOnly;
     default:
         return WKNumberPadInputModeNone;
@@ -5807,13 +6134,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 - (NSString *)textContentTypeForListViewController:(WKTextInputListViewController *)controller
 {
     switch (_assistedNodeInformation.elementType) {
-    case InputType::Password:
+    case WebKit::InputType::Password:
         return UITextContentTypePassword;
-    case InputType::URL:
+    case WebKit::InputType::URL:
         return UITextContentTypeURL;
-    case InputType::Email:
+    case WebKit::InputType::Email:
         return UITextContentTypeEmailAddress;
-    case InputType::Phone:
+    case WebKit::InputType::Phone:
         return UITextContentTypeTelephoneNumber;
     default:
         // The element type alone is insufficient to infer content type; fall back to autofill data.
@@ -5840,12 +6167,18 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
 - (BOOL)allowsDictationInputForListViewController:(PUICQuickboardViewController *)controller
 {
-    return _assistedNodeInformation.elementType != InputType::Password;
+    return _assistedNodeInformation.elementType != WebKit::InputType::Password;
 }
 
 #endif // PLATFORM(WATCHOS)
 
 #if PLATFORM(IOSMAC)
+- (void)_lookupGestureRecognized:(UIGestureRecognizer *)gestureRecognizer
+{
+    NSPoint locationInViewCoordinates = [gestureRecognizer locationInView:self];
+    _page->performDictionaryLookupAtLocation(WebCore::FloatPoint(locationInViewCoordinates));
+}
+
 - (void)_hoverGestureRecognizerChanged:(UIGestureRecognizer *)gestureRecognizer
 {
     if (!_page->isValid())
@@ -5868,7 +6201,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     }
 
     auto event = adoptNS([[::WebEvent alloc] initWithMouseEventType:WebEventMouseMoved timeStamp:timestamp location:point]);
-    _page->handleMouseEvent(NativeWebMouseEvent(event.get()));
+    _page->handleMouseEvent(WebKit::NativeWebMouseEvent(event.get()));
 }
 #endif
 
@@ -5876,6 +6209,13 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 
 @implementation WKContentView (WKTesting)
 
+- (WKFormInputControl *)formInputControl
+{
+    if ([_inputPeripheral isKindOfClass:WKFormInputControl.class])
+        return (WKFormInputControl *)_inputPeripheral.get();
+    return nil;
+}
+
 - (void)_simulateTextEntered:(NSString *)text
 {
 #if PLATFORM(WATCHOS)
@@ -5889,10 +6229,10 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 - (void)_simulateLongPressActionAtLocation:(CGPoint)location
 {
     RetainPtr<WKContentView> protectedSelf = self;
-    [self doAfterPositionInformationUpdate:[protectedSelf] (InteractionInformationAtPosition) {
+    [self doAfterPositionInformationUpdate:[protectedSelf] (WebKit::InteractionInformationAtPosition) {
         if (SEL action = [protectedSelf _actionForLongPress])
             [protectedSelf performSelector:action];
-    } forRequest:InteractionInformationRequest(roundedIntPoint(location))];
+    } forRequest:WebKit::InteractionInformationRequest(WebCore::roundedIntPoint(location))];
 }
 
 - (void)selectFormAccessoryPickerRow:(NSInteger)rowIndex
@@ -5940,13 +6280,6 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
 #endif
 }
 
-- (void)invokeShareSheetWithResolution:(BOOL)resolved
-{
-#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
-    [_shareSheet invokeShareSheetWithResolution:resolved];
-#endif
-}
-
 - (NSDictionary *)_contentsOfUserInterfaceItem:(NSString *)userInterfaceItem
 {
     if ([userInterfaceItem isEqualToString:@"actionSheet"])
@@ -5993,7 +6326,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
     if (!_highlightLongPressCanClick)
         return NO;
 
-    InteractionInformationRequest request(roundedIntPoint(position));
+    WebKit::InteractionInformationRequest request(WebCore::roundedIntPoint(position));
     request.includeSnapshot = true;
     request.includeLinkIndicator = true;
     if (![self ensurePositionInformationIsUpToDate:request])
@@ -6013,7 +6346,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
         if (linkURL.protocolIsInHTTPFamily())
             return YES;
 #if ENABLE(DATA_DETECTION)
-        if (DataDetection::canBePresentedByDataDetectors(linkURL))
+        if (WebCore::DataDetection::canBePresentedByDataDetectors(linkURL))
             return YES;
 #endif
         return NO;
@@ -6103,11 +6436,10 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop
                 dataForPreview[UIPreviewDataAttachmentList] = [uiDelegate _attachmentListForWebView:_webView];
             dataForPreview[UIPreviewDataAttachmentIndex] = [NSNumber numberWithUnsignedInteger:index];
 
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
-            // FIXME: Replace the following NSString literal with a UIKit NSString constant.
-            dataForPreview[@"UIPreviewDataAttachmentListIsContentManaged"] = [NSNumber numberWithBool:sourceIsManaged];
-#else
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
             dataForPreview[UIPreviewDataAttachmentListSourceIsManaged] = [NSNumber numberWithBool:sourceIsManaged];
+#else
+            dataForPreview[UIPreviewDataAttachmentListIsContentManaged] = [NSNumber numberWithBool:sourceIsManaged];
 #endif
         }
     }
@@ -6148,7 +6480,7 @@ static NSString *previewIdentifierForElementAction(_WKElementAction *action)
 
     NSURL *targetURL = controller.previewData[UIPreviewDataLink];
     URL coreTargetURL = targetURL;
-    bool isValidURLForImagePreview = !coreTargetURL.isEmpty() && (WebCore::protocolIsInHTTPFamily(coreTargetURL) || WebCore::protocolIs(coreTargetURL, "data"));
+    bool isValidURLForImagePreview = !coreTargetURL.isEmpty() && (WTF::protocolIsInHTTPFamily(coreTargetURL) || WTF::protocolIs(coreTargetURL, "data"));
 
     if ([_previewItemController type] == UIPreviewItemTypeLink) {
         _highlightLongPressCanClick = NO;
@@ -6285,8 +6617,8 @@ static NSString *previewIdentifierForElementAction(_WKElementAction *action)
     RetainPtr<NSMutableArray> rectArray = adoptNS([[NSMutableArray alloc] init]);
 
     if (_positionInformation.linkIndicator.contentImage) {
-        FloatPoint origin = _positionInformation.linkIndicator.textBoundingRectInRootViewCoordinates.location();
-        for (FloatRect& rect : _positionInformation.linkIndicator.textRectsInBoundingRectCoordinates) {
+        WebCore::FloatPoint origin = _positionInformation.linkIndicator.textBoundingRectInRootViewCoordinates.location();
+        for (WebCore::FloatRect& rect : _positionInformation.linkIndicator.textRectsInBoundingRectCoordinates) {
             CGRect cgRect = rect;
             cgRect.origin.x += origin.x();
             cgRect.origin.y += origin.y();
@@ -6464,10 +6796,12 @@ static NSString *previewIdentifierForElementAction(_WKElementAction *action)
     return _webRect.rect;
 }
 
+ALLOW_DEPRECATED_DECLARATIONS_BEGIN
 - (UITextWritingDirection)writingDirection
 {
     return (UITextWritingDirection)_webRect.writingDirection;
 }
+ALLOW_DEPRECATED_DECLARATIONS_END
 
 - (UITextRange *)range
 {
@@ -6523,4 +6857,4 @@ static NSString *previewIdentifierForElementAction(_WKElementAction *action)
 
 @end
 
-#endif // PLATFORM(IOS)
+#endif // PLATFORM(IOS_FAMILY)