Revert r194125 and r194186: We're going to fix this a different way.
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / Cocoa / WKWebView.mm
index cd7eb8c..f4fc0d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2016 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 "WebPreferencesKeys.h"
 #import "WebProcessPool.h"
 #import "WebProcessProxy.h"
+#import "WebViewImpl.h"
 #import "_WKDiagnosticLoggingDelegate.h"
 #import "_WKFindDelegate.h"
 #import "_WKFormDelegate.h"
+#import "_WKFrameHandleInternal.h"
+#import "_WKHitTestResultInternal.h"
 #import "_WKInputDelegate.h"
 #import "_WKRemoteObjectRegistryInternal.h"
 #import "_WKSessionStateInternal.h"
 #import "_WKVisitedLinkStoreInternal.h"
 #import <WebCore/IOSurface.h>
 #import <WebCore/JSDOMBinding.h>
+#import <WebCore/NSTextFinderSPI.h>
+#import <WebCore/RuntimeApplicationChecks.h>
 #import <wtf/HashMap.h>
 #import <wtf/MathExtras.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/Optional.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/TemporaryChange.h>
 
 #if PLATFORM(IOS)
-#import "_WKFrameHandleInternal.h"
 #import "_WKWebViewPrintFormatter.h"
 #import "PrintInfo.h"
 #import "ProcessThrottler.h"
 #import "WebVideoFullscreenManagerProxy.h"
 #import <UIKit/UIApplication.h>
 #import <WebCore/CoreGraphicsSPI.h>
+#import <WebCore/DynamicLinkerSPI.h>
 #import <WebCore/FrameLoaderTypes.h>
 #import <WebCore/InspectorOverlay.h>
 #import <WebCore/QuartzCoreSPI.h>
 
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
+#if __has_include(<AccessibilitySupport.h>)
+#include <AccessibilitySupport.h>
+#else
+extern "C" {
+CFStringRef kAXSAllowForceWebScalingEnabledNotification;
+}
+#endif
+#endif
+
 @interface UIScrollView (UIScrollViewInternal)
 - (void)_adjustForAutomaticKeyboardInfo:(NSDictionary*)info animated:(BOOL)animated lastAdjustment:(CGFloat*)lastAdjustment;
 - (BOOL)_isScrollingToTop;
@@ -137,11 +153,32 @@ enum class DynamicViewportUpdateMode {
     ResizingWithDocumentHidden,
 };
 
+#if USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/RemoteLayerBackingStoreAdditions.mm>
+#else
+
+namespace WebKit {
+
+#if USE(IOSURFACE)
+static WebCore::IOSurface::Format bufferFormat(bool)
+{
+    return WebCore::IOSurface::Format::RGBA;
+}
+#endif // USE(IOSURFACE)
+
+} // namespace WebKit
+
 #endif
 
+#endif // PLATFORM(IOS)
+
 #if PLATFORM(MAC)
+#import "WKTextFinderClient.h"
 #import "WKViewInternal.h"
 #import <WebCore/ColorMac.h>
+
+@interface WKWebView () <WebViewImplDelegate>
+@end
 #endif
 
 static HashMap<WebKit::WebPageProxy*, WKWebView *>& pageToViewMap()
@@ -159,12 +196,13 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
     std::unique_ptr<WebKit::NavigationState> _navigationState;
     std::unique_ptr<WebKit::UIDelegate> _uiDelegate;
 
-    RetainPtr<_WKRemoteObjectRegistry> _remoteObjectRegistry;
     _WKRenderingProgressEvents _observedRenderingProgressEvents;
 
     WebKit::WeakObjCPtr<id <_WKInputDelegate>> _inputDelegate;
 
 #if PLATFORM(IOS)
+    RetainPtr<_WKRemoteObjectRegistry> _remoteObjectRegistry;
+
     RetainPtr<WKScrollView> _scrollView;
     RetainPtr<WKContentView> _contentView;
 
@@ -174,6 +212,11 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
     CGSize _maximumUnobscuredSizeOverride;
     CGRect _inputViewBounds;
     CGFloat _viewportMetaTagWidth;
+    BOOL _viewportMetaTagWidthWasExplicit;
+    BOOL _viewportMetaTagCameFromImageDocument;
+    CGFloat _initialScaleFactor;
+    BOOL _fastClickingIsDisabled;
+
     BOOL _allowsLinkPreview;
 
     UIEdgeInsets _obscuredInsets;
@@ -182,6 +225,8 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
 
     UIInterfaceOrientation _interfaceOrientationOverride;
     BOOL _overridesInterfaceOrientation;
+    
+    BOOL _allowsViewportShrinkToFit;
 
     BOOL _hasCommittedLoadForMainFrame;
     BOOL _needsResetViewStateAfterCommitLoadForMainFrame;
@@ -209,6 +254,12 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
 
     WebCore::Color _scrollViewBackgroundColor;
 
+    // This value tracks the current adjustment added to the bottom inset due to the keyboard sliding out from the bottom
+    // when computing obscured content insets. This is used when updating the visible content rects where we should not
+    // include this adjustment.
+    CGFloat _totalScrollViewBottomInsetAdjustmentForKeyboard;
+    BOOL _currentlyAdjustingScrollViewInsetsForKeyboard;
+
     BOOL _delayUpdateVisibleContentRects;
     BOOL _hadDelayedUpdateVisibleContentRects;
 
@@ -217,8 +268,8 @@ WKWebView* fromWebPageProxy(WebKit::WebPageProxy& page)
     Vector<std::function<void ()>> _snapshotsDeferredDuringResize;
 #endif
 #if PLATFORM(MAC)
-    RetainPtr<WKView> _wkView;
-    CGSize _intrinsicContentSize;
+    std::unique_ptr<WebKit::WebViewImpl> _impl;
+    RetainPtr<WKTextFinderClient> _textFinderClient;
 #endif
 }
 
@@ -270,17 +321,51 @@ static int32_t deviceOrientation()
 
 static bool shouldAllowPictureInPictureMediaPlayback()
 {
-    static bool shouldAllowPictureInPictureMediaPlayback = iosExecutableWasLinkedOnOrAfterVersion(wkIOSSystemVersion_9_0);
+    static bool shouldAllowPictureInPictureMediaPlayback = dyld_get_program_sdk_version() >= DYLD_IOS_VERSION_9_0;
     return shouldAllowPictureInPictureMediaPlayback;
 }
 
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
+static void forceAlwaysUserScalableChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
+{
+    ASSERT(observer);
+    WKWebView* webview = static_cast<WKWebView*>(observer);
+    [webview _updateForceAlwaysUserScalable];
+}
 #endif
 
-- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
+#endif
+
+#if ENABLE(DATA_DETECTION)
+static WebCore::DataDetectorTypes fromWKDataDetectorTypes(uint64_t types)
 {
-    if (!(self = [super initWithFrame:frame]))
-        return nil;
+    if (static_cast<WKDataDetectorTypes>(types) == WKDataDetectorTypeNone)
+        return WebCore::DataDetectorTypeNone;
+    if (static_cast<WKDataDetectorTypes>(types) == WKDataDetectorTypeAll)
+        return WebCore::DataDetectorTypeAll;
+    
+    uint32_t value = WebCore::DataDetectorTypeNone;
+    if (types & WKDataDetectorTypePhoneNumber)
+        value |= WebCore::DataDetectorTypePhoneNumber;
+    if (types & WKDataDetectorTypeLink)
+        value |= WebCore::DataDetectorTypeLink;
+    if (types & WKDataDetectorTypeAddress)
+        value |= WebCore::DataDetectorTypeAddress;
+    if (types & WKDataDetectorTypeCalendarEvent)
+        value |= WebCore::DataDetectorTypeCalendarEvent;
+    if (types & WKDataDetectorTypeTrackingNumber)
+        value |= WebCore::DataDetectorTypeTrackingNumber;
+    if (types & WKDataDetectorTypeFlightNumber)
+        value |= WebCore::DataDetectorTypeFlightNumber;
+    if (types & WKDataDetectorTypeSpotlightSuggestion)
+        value |= WebCore::DataDetectorTypeSpotlightSuggestion;
+
+    return static_cast<WebCore::DataDetectorTypes>(value);
+}
+#endif
 
+- (void)_initializeWithConfiguration:(WKWebViewConfiguration *)configuration
+{
     if (!configuration)
         [NSException raise:NSInvalidArgumentException format:@"Configuration cannot be nil"];
 
@@ -297,9 +382,8 @@ static bool shouldAllowPictureInPictureMediaPlayback()
 
     [_configuration _validate];
 
-    CGRect bounds = self.bounds;
-
     WebKit::WebProcessPool& processPool = *[_configuration processPool]->_processPool;
+    processPool.setResourceLoadStatisticsEnabled(configuration.websiteDataStore._resourceLoadStatisticsEnabled);
     
     auto pageConfiguration = API::PageConfiguration::create();
 
@@ -322,6 +406,20 @@ static bool shouldAllowPictureInPictureMediaPlayback()
 
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::suppressesIncrementalRenderingKey(), WebKit::WebPreferencesStore::Value(!![_configuration suppressesIncrementalRendering]));
 
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::shouldRespectImageOrientationKey(), WebKit::WebPreferencesStore::Value(!![_configuration _respectsImageOrientation]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::shouldPrintBackgroundsKey(), WebKit::WebPreferencesStore::Value(!![_configuration _printsBackgrounds]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::incrementalRenderingSuppressionTimeoutKey(), WebKit::WebPreferencesStore::Value([_configuration _incrementalRenderingSuppressionTimeout]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::javaScriptMarkupEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _allowsJavaScriptMarkup]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::shouldConvertPositionStyleOnCopyKey(), WebKit::WebPreferencesStore::Value(!![_configuration _convertsPositionStyleOnCopy]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::httpEquivEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _allowsMetaRefresh]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::allowUniversalAccessFromFileURLsKey(), WebKit::WebPreferencesStore::Value(!![_configuration _allowUniversalAccessFromFileURLs]));
+    
+#if PLATFORM(MAC)
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::showsURLsInToolTipsEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _showsURLsInToolTips]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::serviceControlsEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _serviceControlsEnabled]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::imageControlsEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _imageControlsEnabled]));
+#endif
+
 #if PLATFORM(IOS)
     pageConfiguration->setAlwaysRunsAtForegroundPriority([_configuration _alwaysRunsAtForegroundPriority]);
 
@@ -329,20 +427,41 @@ static bool shouldAllowPictureInPictureMediaPlayback()
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::inlineMediaPlaybackRequiresPlaysInlineAttributeKey(), WebKit::WebPreferencesStore::Value(!![_configuration _inlineMediaPlaybackRequiresPlaysInlineAttribute]));
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::allowsPictureInPictureMediaPlaybackKey(), WebKit::WebPreferencesStore::Value(!![_configuration allowsPictureInPictureMediaPlayback] && shouldAllowPictureInPictureMediaPlayback()));
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::requiresUserGestureForMediaPlaybackKey(), WebKit::WebPreferencesStore::Value(!![_configuration requiresUserActionForMediaPlayback]));
+#endif
+
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::requiresUserGestureForVideoPlaybackKey(), WebKit::WebPreferencesStore::Value(!![_configuration _requiresUserActionForVideoPlayback]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::requiresUserGestureForAudioPlaybackKey(), WebKit::WebPreferencesStore::Value(!![_configuration _requiresUserActionForAudioPlayback]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::mainContentUserGestureOverrideEnabledKey(), WebKit::WebPreferencesStore::Value(!![_configuration _mainContentUserGestureOverrideEnabled]));
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::invisibleAutoplayNotPermittedKey(), WebKit::WebPreferencesStore::Value(!![_configuration _invisibleAutoplayNotPermitted]));
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::mediaDataLoadsAutomaticallyKey(), WebKit::WebPreferencesStore::Value(!![_configuration _mediaDataLoadsAutomatically]));
+
+// FIXME: <rdar://problem/25135244> Remove bundle checks for attachmentElementEnabled
+#if PLATFORM(IOS)
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::attachmentElementEnabledKey(), WebKit::WebPreferencesStore::Value(WebCore::IOSApplication::isMobileMail() ? true : !![_configuration _attachmentElementEnabled]));
+#else
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::attachmentElementEnabledKey(), WebKit::WebPreferencesStore::Value(WebCore::MacApplication::isAppleMail() ? true : !![_configuration _attachmentElementEnabled]));
+#endif
+
+#if ENABLE(DATA_DETECTION)
+    pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::dataDetectorTypesKey(), WebKit::WebPreferencesStore::Value(static_cast<uint32_t>(fromWKDataDetectorTypes([_configuration dataDetectorTypes]))));
 #endif
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     pageConfiguration->preferenceValues().set(WebKit::WebPreferencesKey::allowsAirPlayForMediaPlaybackKey(), WebKit::WebPreferencesStore::Value(!![_configuration allowsAirPlayForMediaPlayback]));
 #endif
 
+#if USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/WKWebViewInitialization.mm>
+#endif
+
 #if PLATFORM(IOS)
+    CGRect bounds = self.bounds;
     _scrollView = adoptNS([[WKScrollView alloc] initWithFrame:bounds]);
     [_scrollView setInternalDelegate:self];
     [_scrollView setBouncesZoom:YES];
 
     [self addSubview:_scrollView.get()];
 
-    _contentView = adoptNS([[WKContentView alloc] initWithFrame:bounds processPool:processPool configuration:WTF::move(pageConfiguration) webView:self]);
+    _contentView = adoptNS([[WKContentView alloc] initWithFrame:bounds processPool:processPool configuration:WTFMove(pageConfiguration) webView:self]);
 
     _page = [_contentView page];
     _page->setDeviceOrientation(deviceOrientation());
@@ -353,7 +472,9 @@ static bool shouldAllowPictureInPictureMediaPlayback()
     [_scrollView addSubview:[_contentView unscaledView]];
     [self _updateScrollViewBackground];
 
-    _viewportMetaTagWidth = -1;
+    _viewportMetaTagWidth = WebCore::ViewportArguments::ValueAuto;
+    _initialScaleFactor = 1;
+    _fastClickingIsDisabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitFastClickingDisabled"];
 
     [self _frameOrBoundsChanged];
 
@@ -365,20 +486,19 @@ static bool shouldAllowPictureInPictureMediaPlayback()
     [center addObserver:self selector:@selector(_windowDidRotate:) name:UIWindowDidRotateNotification object:nil];
     [center addObserver:self selector:@selector(_contentSizeCategoryDidChange:) name:UIContentSizeCategoryDidChangeNotification object:nil];
     _page->contentSizeCategoryDidChange([self _contentSizeCategory]);
+    
+#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
+    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), forceAlwaysUserScalableChangedCallback, kAXSAllowForceWebScalingEnabledNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
+#endif
 
     [[_configuration _contentProviderRegistry] addPage:*_page];
 #endif
 
 #if PLATFORM(MAC)
-    _wkView = adoptNS([[WKView alloc] initWithFrame:bounds processPool:processPool configuration:WTF::move(pageConfiguration) webView:self]);
-    [self addSubview:_wkView.get()];
-    _page = WebKit::toImpl([_wkView pageRef]);
+    _impl = std::make_unique<WebKit::WebViewImpl>(self, self, processPool, WTFMove(pageConfiguration));
+    _page = &_impl->page();
 
-    _intrinsicContentSize = CGSizeMake(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric);
-
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-    [_wkView _setAutomaticallyAdjustsContentInsets:YES];
-#endif
+    _impl->setAutomaticallyAdjustsContentInsets(true);
 #endif
 
     _page->setBackgroundExtendsBeyondPage(true);
@@ -392,26 +512,71 @@ static bool shouldAllowPictureInPictureMediaPlayback()
     _page->setDiagnosticLoggingClient(std::make_unique<WebKit::DiagnosticLoggingClient>(self));
 
     pageToViewMap().add(_page.get(), self);
+}
+
+- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
+{
+    if (!(self = [super initWithFrame:frame]))
+        return nil;
+
+    [self _initializeWithConfiguration:configuration];
 
     return self;
 }
 
 - (instancetype)initWithCoder:(NSCoder *)coder
 {
-    [self release];
-    return nil;
+    if (!(self = [super initWithCoder:coder]))
+        return nil;
+
+    WKWebViewConfiguration *configuration = [coder decodeObjectForKey:@"configuration"];
+    [self _initializeWithConfiguration:configuration];
+
+    self.allowsBackForwardNavigationGestures = [coder decodeBoolForKey:@"allowsBackForwardNavigationGestures"];
+    self.customUserAgent = [coder decodeObjectForKey:@"customUserAgent"];
+    self.allowsLinkPreview = [coder decodeBoolForKey:@"allowsLinkPreview"];
+
+#if PLATFORM(MAC)
+    self.allowsMagnification = [coder decodeBoolForKey:@"allowsMagnification"];
+    self.magnification = [coder decodeDoubleForKey:@"magnification"];
+#endif
+
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+    [coder encodeObject:_configuration.get() forKey:@"configuration"];
+
+    [coder encodeBool:self.allowsBackForwardNavigationGestures forKey:@"allowsBackForwardNavigationGestures"];
+    [coder encodeObject:self.customUserAgent forKey:@"customUserAgent"];
+    [coder encodeBool:self.allowsLinkPreview forKey:@"allowsLinkPreview"];
+
+#if PLATFORM(MAC)
+    [coder encodeBool:self.allowsMagnification forKey:@"allowsMagnification"];
+    [coder encodeDouble:self.magnification forKey:@"magnification"];
+#endif
 }
 
 - (void)dealloc
 {
+#if PLATFORM(MAC)
+    [_textFinderClient willDestroyView:self];
+#endif
+
+#if PLATFORM(IOS)
+    [_contentView _webViewDestroyed];
+
     if (_remoteObjectRegistry)
         _page->process().processPool().removeMessageReceiver(Messages::RemoteObjectRegistry::messageReceiverName(), _page->pageID());
 
     _page->close();
 
     [_remoteObjectRegistry _invalidate];
-#if PLATFORM(IOS)
     [[_configuration _contentProviderRegistry] removePage:*_page];
+#if PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000
+    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), (__bridge const void *)(self), nullptr, nullptr);
+#endif
     [[NSNotificationCenter defaultCenter] removeObserver:self];
     [_scrollView setInternalDelegate:nil];
 #endif
@@ -449,6 +614,9 @@ static bool shouldAllowPictureInPictureMediaPlayback()
 
 - (void)setUIDelegate:(id<WKUIDelegate>)UIDelegate
 {
+#if ENABLE(CONTEXT_MENUS)
+    _page->setContextMenuClient(_uiDelegate->createContextMenuClient());
+#endif
     _page->setUIClient(_uiDelegate->createUIClient());
     _uiDelegate->setDelegate(UIDelegate);
 }
@@ -681,7 +849,7 @@ static WKErrorCode callbackErrorCode(WebKit::CallbackBase::Error error)
 - (BOOL)allowsLinkPreview
 {
 #if PLATFORM(MAC)
-    return [_wkView allowsLinkPreview];
+    return _impl->allowsLinkPreview();
 #elif PLATFORM(IOS)
     return _allowsLinkPreview;
 #endif
@@ -690,7 +858,7 @@ static WKErrorCode callbackErrorCode(WebKit::CallbackBase::Error error)
 - (void)setAllowsLinkPreview:(BOOL)allowsLinkPreview
 {
 #if PLATFORM(MAC)
-    [_wkView setAllowsLinkPreview:allowsLinkPreview];
+    _impl->setAllowsLinkPreview(allowsLinkPreview);
     return;
 #elif PLATFORM(IOS)
     if (_allowsLinkPreview == allowsLinkPreview)
@@ -710,6 +878,15 @@ static WKErrorCode callbackErrorCode(WebKit::CallbackBase::Error error)
 #pragma mark iOS-specific methods
 
 #if PLATFORM(IOS)
+
+- (BOOL)_isBackground
+{
+    if ([self _isDisplayingPDF])
+        return [(WKPDFView *)_customContentView isBackground];
+
+    return [_contentView isBackground];
+}
+
 - (void)setFrame:(CGRect)frame
 {
     CGRect oldFrame = self.frame;
@@ -741,7 +918,14 @@ static WKErrorCode callbackErrorCode(WebKit::CallbackBase::Error error)
 
 - (BOOL)becomeFirstResponder
 {
-    return [_contentView becomeFirstResponder] || [super becomeFirstResponder];
+    return [self._currentContentView becomeFirstResponder] || [super becomeFirstResponder];
+}
+
+- (BOOL)canBecomeFirstResponder
+{
+    if (self._currentContentView == _contentView && [_contentView isResigningFirstResponder])
+        return NO;
+    return YES;
 }
 
 static inline CGFloat floorToDevicePixel(CGFloat input, float deviceScaleFactor)
@@ -766,6 +950,16 @@ static CGSize roundScrollViewContentSize(const WebKit::WebPageProxy& page, CGSiz
     return _customContentView ? _customContentView.get() : _contentView.get();
 }
 
+- (WKWebViewContentProviderRegistry *)_contentProviderRegistry
+{
+    return [_configuration _contentProviderRegistry];
+}
+
+- (WKSelectionGranularity)_selectionGranularity
+{
+    return [_configuration selectionGranularity];
+}
+
 - (void)_setHasCustomContentView:(BOOL)pageHasCustomContentView loadedMIMEType:(const WTF::String&)mimeType
 {
     if (pageHasCustomContentView) {
@@ -799,6 +993,9 @@ static CGSize roundScrollViewContentSize(const WebKit::WebPageProxy& page, CGSiz
         [_customContentFixedOverlayView setFrame:self.bounds];
         [self addSubview:_customContentFixedOverlayView.get()];
     }
+
+    if (self.isFirstResponder && self._currentContentView.canBecomeFirstResponder)
+        [self._currentContentView becomeFirstResponder];
 }
 
 - (void)_didFinishLoadingDataForCustomContentProviderWithSuggestedFilename:(const String&)suggestedFilename data:(NSData *)data
@@ -811,11 +1008,6 @@ static CGSize roundScrollViewContentSize(const WebKit::WebPageProxy& page, CGSiz
     _page->didLayoutForCustomContentProvider();
 }
 
-- (void)_setViewportMetaTagWidth:(float)newWidth
-{
-    _viewportMetaTagWidth = newWidth;
-}
-
 - (void)_willInvokeUIScrollViewDelegateCallback
 {
     _delayUpdateVisibleContentRects = YES;
@@ -881,7 +1073,7 @@ static WebCore::Color scrollViewBackgroundColor(WKWebView *webView)
 
     _scrollViewBackgroundColor = color;
 
-    auto uiBackgroundColor = adoptNS([[UIColor alloc] initWithCGColor:cachedCGColor(color, WebCore::ColorSpaceDeviceRGB)]);
+    auto uiBackgroundColor = adoptNS([[UIColor alloc] initWithCGColor:cachedCGColor(color)]);
     [_scrollView setBackgroundColor:uiBackgroundColor.get()];
 
     // Update the indicator style based on the lightness/darkness of the background color.
@@ -928,7 +1120,8 @@ static WebCore::Color scrollViewBackgroundColor(WKWebView *webView)
     [_scrollView setContentOffset:[self _adjustedContentOffset:CGPointZero]];
     [_scrollView setZoomScale:1];
 
-    _viewportMetaTagWidth = -1;
+    _viewportMetaTagWidth = WebCore::ViewportArguments::ValueAuto;
+    _initialScaleFactor = 1;
     _hasCommittedLoadForMainFrame = NO;
     _needsResetViewStateAfterCommitLoadForMainFrame = NO;
     _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
@@ -1010,7 +1203,12 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
     if (!layerTreeTransaction.scaleWasSetByUIProcess() && ![_scrollView isZooming] && ![_scrollView isZoomBouncing] && ![_scrollView _isAnimatingZoom])
         [_scrollView setZoomScale:layerTreeTransaction.pageScaleFactor()];
 
-    [_contentView _setDoubleTapGesturesEnabled:self._viewportIsUserScalable];
+    _viewportMetaTagWidth = layerTreeTransaction.viewportMetaTagWidth();
+    _viewportMetaTagWidthWasExplicit = layerTreeTransaction.viewportMetaTagWidthWasExplicit();
+    _viewportMetaTagCameFromImageDocument = layerTreeTransaction.viewportMetaTagCameFromImageDocument();
+    _initialScaleFactor = layerTreeTransaction.initialScaleFactor();
+    if (![_contentView _mayDisableDoubleTapGesturesDuringSingleTap])
+        [_contentView _setDoubleTapGesturesEnabled:self._allowsDoubleTapGestures];
 
     [self _updateScrollViewBackground];
 
@@ -1122,22 +1320,28 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
 
 - (PassRefPtr<WebKit::ViewSnapshot>)_takeViewSnapshot
 {
-    float deviceScale = WKGetScreenScaleFactor();
+    float deviceScale = WebCore::screenScaleFactor();
     WebCore::FloatSize snapshotSize(self.bounds.size);
     snapshotSize.scale(deviceScale, deviceScale);
 
     CATransform3D transform = CATransform3DMakeScale(deviceScale, deviceScale, 1);
 
 #if USE(IOSURFACE)
-    auto surface = WebCore::IOSurface::create(WebCore::expandedIntSize(snapshotSize), WebCore::ColorSpaceDeviceRGB);
+    WebCore::IOSurface::Format snapshotFormat = WebKit::bufferFormat(true /* is opaque */);
+    auto surface = WebCore::IOSurface::create(WebCore::expandedIntSize(snapshotSize), WebCore::ColorSpaceSRGB, snapshotFormat);
     CARenderServerRenderLayerWithTransform(MACH_PORT_NULL, self.layer.context.contextId, reinterpret_cast<uint64_t>(self.layer), surface->surface(), 0, 0, &transform);
 
-    RefPtr<WebKit::ViewSnapshot> viewSnapshot = WebKit::ViewSnapshot::create(nullptr);
-    WebCore::IOSurface::convertToFormat(WTF::move(surface), WebCore::IOSurface::Format::YUV422, [viewSnapshot](std::unique_ptr<WebCore::IOSurface> convertedSurface) {
-        viewSnapshot->setSurface(WTF::move(convertedSurface));
-    });
+    WebCore::IOSurface::Format compressedFormat = WebCore::IOSurface::Format::YUV422;
+    if (WebCore::IOSurface::allowConversionFromFormatToFormat(snapshotFormat, compressedFormat)) {
+        RefPtr<WebKit::ViewSnapshot> viewSnapshot = WebKit::ViewSnapshot::create(nullptr);
+        WebCore::IOSurface::convertToFormat(WTFMove(surface), WebCore::IOSurface::Format::YUV422, [viewSnapshot](std::unique_ptr<WebCore::IOSurface> convertedSurface) {
+            viewSnapshot->setSurface(WTFMove(convertedSurface));
+        });
 
-    return viewSnapshot;
+        return viewSnapshot;
+    }
+
+    return WebKit::ViewSnapshot::create(WTFMove(surface));
 #else
     uint32_t slotID = [WebKit::ViewSnapshotStore::snapshottingContext() createImageSlot:snapshotSize hasAlpha:YES];
 
@@ -1201,9 +1405,7 @@ static inline bool areEssentiallyEqualAsFloat(float a, float b)
 static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOffset, WebCore::FloatSize contentSize, WebCore::FloatSize unobscuredContentSize)
 {
     WebCore::FloatSize maximumContentOffset = contentSize - unobscuredContentSize;
-    contentOffset = contentOffset.shrunkTo(WebCore::FloatPoint(maximumContentOffset.width(), maximumContentOffset.height()));
-    contentOffset = contentOffset.expandedTo(WebCore::FloatPoint());
-    return contentOffset;
+    return contentOffset.constrainedBetween(WebCore::FloatPoint(), WebCore::FloatPoint(maximumContentOffset));
 }
 
 - (void)_scrollToContentOffset:(WebCore::FloatPoint)contentOffsetInPageCoordinates scrollOrigin:(WebCore::IntPoint)scrollOrigin
@@ -1272,12 +1474,15 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     return true;
 }
 
-- (void)_scrollByOffset:(WebCore::FloatPoint)offset
+- (void)_scrollByContentOffset:(WebCore::FloatPoint)contentOffsetDelta
 {
-    CGPoint currentOffset = ([_scrollView _isAnimatingScroll]) ? [_scrollView _animatedTargetOffset] : [_scrollView contentOffset];
+    WebCore::FloatPoint scaledOffsetDelta = contentOffsetDelta;
+    CGFloat zoomScale = contentZoomScale(self);
+    scaledOffsetDelta.scale(zoomScale, zoomScale);
+
+    CGPoint currentOffset = [_scrollView _isAnimatingScroll] ? [_scrollView _animatedTargetOffset] : [_scrollView contentOffset];
+    CGPoint boundedOffset = contentOffsetBoundedInValidRange(_scrollView.get(), currentOffset + scaledOffsetDelta);
 
-    CGPoint boundedOffset = contentOffsetBoundedInValidRange(_scrollView.get(), currentOffset + offset);
-    
     if (CGPointEqualToPoint(boundedOffset, currentOffset))
         return;
     [_contentView willStartZoomOrScroll];
@@ -1289,6 +1494,12 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     [self _zoomToPoint:origin atScale:[_scrollView minimumZoomScale] animated:animated];
 }
 
+- (void)_zoomToInitialScaleWithOrigin:(WebCore::FloatPoint)origin animated:(BOOL)animated
+{
+    ASSERT(_initialScaleFactor > 0);
+    [self _zoomToPoint:origin atScale:_initialScaleFactor animated:animated];
+}
+
 // focusedElementRect and selectionRect are both in document coordinates.
 - (void)_zoomToFocusRect:(WebCore::FloatRect)focusedElementRectInDocumentCoordinates selectionRect:(WebCore::FloatRect)selectionRectInDocumentCoordinates fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll
 {
@@ -1408,11 +1619,6 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
                         force:YES];
 }
 
-- (CGFloat)_contentZoomScale
-{
-    return contentZoomScale(self);
-}
-
 - (CGFloat)_targetContentZoomScaleForRect:(const WebCore::FloatRect&)targetRect currentScale:(double)currentScale fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale
 {
     WebCore::FloatSize unobscuredContentSize([self _contentRectForUserInteraction].size);
@@ -1468,6 +1674,26 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     [_contentView setBackgroundColor:backgroundColor];
 }
 
+- (BOOL)_allowsDoubleTapGestures
+{
+    if (_fastClickingIsDisabled)
+        return YES;
+
+    // If the page is not user scalable, we don't allow double tap gestures.
+    if (![_scrollView isZoomEnabled] || [_scrollView minimumZoomScale] >= [_scrollView maximumZoomScale])
+        return NO;
+
+    // If the viewport width was not explicit, we allow double tap gestures.
+    if (!_viewportMetaTagWidthWasExplicit || _viewportMetaTagCameFromImageDocument)
+        return YES;
+
+    // For scalable viewports, only disable double tap gestures if the viewport width is device width.
+    if (_viewportMetaTagWidth != WebCore::ViewportArguments::ValueDeviceWidth)
+        return YES;
+
+    return !areEssentiallyEqualAsFloat(contentZoomScale(self), _initialScaleFactor);
+}
+
 #pragma mark - UIScrollViewDelegate
 
 - (BOOL)usesStandardContentView
@@ -1663,19 +1889,20 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
         return;
     }
 
-    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing)
-        return;
-
-    if (_needsResetViewStateAfterCommitLoadForMainFrame)
-        return;
-
-    if ([_scrollView isZoomBouncing])
+    if (_dynamicViewportUpdateMode != DynamicViewportUpdateMode::NotResizing
+        || _needsResetViewStateAfterCommitLoadForMainFrame
+        || [_scrollView isZoomBouncing]
+        || _currentlyAdjustingScrollViewInsetsForKeyboard)
         return;
 
     CGRect fullViewRect = self.bounds;
     CGRect visibleRectInContentCoordinates = _frozenVisibleContentRect ? _frozenVisibleContentRect.value() : [self convertRect:fullViewRect toView:_contentView.get()];
 
-    CGRect unobscuredRect = UIEdgeInsetsInsetRect(fullViewRect, [self _computedContentInset]);
+    UIEdgeInsets computedContentInsetUnadjustedForKeyboard = [self _computedContentInset];
+    if (!_haveSetObscuredInsets)
+        computedContentInsetUnadjustedForKeyboard.bottom -= _totalScrollViewBottomInsetAdjustmentForKeyboard;
+
+    CGRect unobscuredRect = UIEdgeInsetsInsetRect(fullViewRect, computedContentInsetUnadjustedForKeyboard);
     CGRect unobscuredRectInContentCoordinates = _frozenUnobscuredContentRect ? _frozenUnobscuredContentRect.value() : [self convertRect:unobscuredRect toView:_contentView.get()];
 
     CGFloat scaleFactor = contentZoomScale(self);
@@ -1691,7 +1918,7 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
         WebKit::RemoteScrollingCoordinatorProxy* coordinator = _page->scrollingCoordinatorProxy();
         if (coordinator && coordinator->hasActiveSnapPoint()) {
             CGRect fullViewRect = self.bounds;
-            CGRect unobscuredRect = UIEdgeInsetsInsetRect(fullViewRect, [self _computedContentInset]);
+            CGRect unobscuredRect = UIEdgeInsetsInsetRect(fullViewRect, computedContentInsetUnadjustedForKeyboard);
             
             CGPoint currentPoint = [_scrollView contentOffset];
             CGPoint activePoint = coordinator->nearestActiveContentInsetAdjustedSnapPoint(unobscuredRect.origin.y, currentPoint);
@@ -1710,7 +1937,8 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
         unobscuredRect:unobscuredRectInContentCoordinates
         unobscuredRectInScrollViewCoordinates:unobscuredRect
         scale:scaleFactor minimumScale:[_scrollView minimumZoomScale]
-        inStableState:isStableState isChangingObscuredInsetsInteractively:_isChangingObscuredInsetsInteractively];
+        inStableState:isStableState
+        isChangingObscuredInsetsInteractively:_isChangingObscuredInsetsInteractively];
 }
 
 - (void)_didFinishLoadForMainFrame
@@ -1747,10 +1975,16 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     else
         _inputViewBounds = [self.window convertRect:CGRectIntersection([endFrameValue CGRectValue], self.window.screen.bounds) fromWindow:nil];
 
-    [self _updateVisibleContentRects];
-
-    if (adjustScrollView)
+    if (adjustScrollView) {
+        CGFloat bottomInsetBeforeAdjustment = [_scrollView contentInset].bottom;
+        TemporaryChange<BOOL> insetAdjustmentGuard(_currentlyAdjustingScrollViewInsetsForKeyboard, YES);
         [_scrollView _adjustForAutomaticKeyboardInfo:keyboardInfo animated:YES lastAdjustment:&_lastAdjustmentForScroller];
+        CGFloat bottomInsetAfterAdjustment = [_scrollView contentInset].bottom;
+        if (bottomInsetBeforeAdjustment != bottomInsetAfterAdjustment)
+            _totalScrollViewBottomInsetAdjustmentForKeyboard += bottomInsetAfterAdjustment - bottomInsetBeforeAdjustment;
+    }
+
+    [self _updateVisibleContentRects];
 }
 
 - (BOOL)_shouldUpdateKeyboardWithInfo:(NSDictionary *)keyboardInfo
@@ -1848,288 +2082,1078 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
     _frozenUnobscuredContentRect = Nullopt;
 }
 
+- (void)_updateForceAlwaysUserScalable
+{
+    _page->updateForceAlwaysUserScalable();
+}
+
 #endif // PLATFORM(IOS)
 
 #pragma mark OS X-specific methods
 
 #if PLATFORM(MAC)
 
-- (BOOL)becomeFirstResponder
+- (BOOL)acceptsFirstResponder
 {
-    return [[self window] makeFirstResponder: _wkView.get()];
+    return _impl->acceptsFirstResponder();
 }
 
-- (BOOL)acceptsFirstResponder
+- (BOOL)becomeFirstResponder
 {
-    return [_wkView acceptsFirstResponder];
+    return _impl->becomeFirstResponder();
 }
 
-- (void)resizeSubviewsWithOldSize:(NSSize)oldSize
+- (BOOL)resignFirstResponder
 {
-    [_wkView setFrame:self.bounds];
+    return _impl->resignFirstResponder();
 }
 
-- (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigationGestures
+- (void)viewWillStartLiveResize
 {
-    [_wkView setAllowsBackForwardNavigationGestures:allowsBackForwardNavigationGestures];
+    _impl->viewWillStartLiveResize();
 }
 
-- (BOOL)allowsBackForwardNavigationGestures
+- (void)viewDidEndLiveResize
+{
+    _impl->viewDidEndLiveResize();
+}
+
+- (BOOL)isFlipped
+{
+    return YES;
+}
+
+- (NSSize)intrinsicContentSize
+{
+    return NSSizeFromCGSize(_impl->intrinsicContentSize());
+}
+
+- (void)prepareContentInRect:(NSRect)rect
+{
+    _impl->prepareContentInRect(NSRectToCGRect(rect));
+}
+
+- (void)setFrameSize:(NSSize)size
+{
+    [super setFrameSize:size];
+    _impl->setFrameSize(NSSizeToCGSize(size));
+}
+
+- (void)renewGState
+{
+    _impl->renewGState();
+    [super renewGState];
+}
+
+#define WEBCORE_COMMAND(command) - (void)command:(id)sender { _impl->executeEditCommandForSelector(_cmd); }
+
+WEBCORE_COMMAND(alignCenter)
+WEBCORE_COMMAND(alignJustified)
+WEBCORE_COMMAND(alignLeft)
+WEBCORE_COMMAND(alignRight)
+WEBCORE_COMMAND(copy)
+WEBCORE_COMMAND(cut)
+WEBCORE_COMMAND(delete)
+WEBCORE_COMMAND(deleteBackward)
+WEBCORE_COMMAND(deleteBackwardByDecomposingPreviousCharacter)
+WEBCORE_COMMAND(deleteForward)
+WEBCORE_COMMAND(deleteToBeginningOfLine)
+WEBCORE_COMMAND(deleteToBeginningOfParagraph)
+WEBCORE_COMMAND(deleteToEndOfLine)
+WEBCORE_COMMAND(deleteToEndOfParagraph)
+WEBCORE_COMMAND(deleteToMark)
+WEBCORE_COMMAND(deleteWordBackward)
+WEBCORE_COMMAND(deleteWordForward)
+WEBCORE_COMMAND(ignoreSpelling)
+WEBCORE_COMMAND(indent)
+WEBCORE_COMMAND(insertBacktab)
+WEBCORE_COMMAND(insertLineBreak)
+WEBCORE_COMMAND(insertNewline)
+WEBCORE_COMMAND(insertNewlineIgnoringFieldEditor)
+WEBCORE_COMMAND(insertParagraphSeparator)
+WEBCORE_COMMAND(insertTab)
+WEBCORE_COMMAND(insertTabIgnoringFieldEditor)
+WEBCORE_COMMAND(makeTextWritingDirectionLeftToRight)
+WEBCORE_COMMAND(makeTextWritingDirectionNatural)
+WEBCORE_COMMAND(makeTextWritingDirectionRightToLeft)
+WEBCORE_COMMAND(moveBackward)
+WEBCORE_COMMAND(moveBackwardAndModifySelection)
+WEBCORE_COMMAND(moveDown)
+WEBCORE_COMMAND(moveDownAndModifySelection)
+WEBCORE_COMMAND(moveForward)
+WEBCORE_COMMAND(moveForwardAndModifySelection)
+WEBCORE_COMMAND(moveLeft)
+WEBCORE_COMMAND(moveLeftAndModifySelection)
+WEBCORE_COMMAND(moveParagraphBackwardAndModifySelection)
+WEBCORE_COMMAND(moveParagraphForwardAndModifySelection)
+WEBCORE_COMMAND(moveRight)
+WEBCORE_COMMAND(moveRightAndModifySelection)
+WEBCORE_COMMAND(moveToBeginningOfDocument)
+WEBCORE_COMMAND(moveToBeginningOfDocumentAndModifySelection)
+WEBCORE_COMMAND(moveToBeginningOfLine)
+WEBCORE_COMMAND(moveToBeginningOfLineAndModifySelection)
+WEBCORE_COMMAND(moveToBeginningOfParagraph)
+WEBCORE_COMMAND(moveToBeginningOfParagraphAndModifySelection)
+WEBCORE_COMMAND(moveToBeginningOfSentence)
+WEBCORE_COMMAND(moveToBeginningOfSentenceAndModifySelection)
+WEBCORE_COMMAND(moveToEndOfDocument)
+WEBCORE_COMMAND(moveToEndOfDocumentAndModifySelection)
+WEBCORE_COMMAND(moveToEndOfLine)
+WEBCORE_COMMAND(moveToEndOfLineAndModifySelection)
+WEBCORE_COMMAND(moveToEndOfParagraph)
+WEBCORE_COMMAND(moveToEndOfParagraphAndModifySelection)
+WEBCORE_COMMAND(moveToEndOfSentence)
+WEBCORE_COMMAND(moveToEndOfSentenceAndModifySelection)
+WEBCORE_COMMAND(moveToLeftEndOfLine)
+WEBCORE_COMMAND(moveToLeftEndOfLineAndModifySelection)
+WEBCORE_COMMAND(moveToRightEndOfLine)
+WEBCORE_COMMAND(moveToRightEndOfLineAndModifySelection)
+WEBCORE_COMMAND(moveUp)
+WEBCORE_COMMAND(moveUpAndModifySelection)
+WEBCORE_COMMAND(moveWordBackward)
+WEBCORE_COMMAND(moveWordBackwardAndModifySelection)
+WEBCORE_COMMAND(moveWordForward)
+WEBCORE_COMMAND(moveWordForwardAndModifySelection)
+WEBCORE_COMMAND(moveWordLeft)
+WEBCORE_COMMAND(moveWordLeftAndModifySelection)
+WEBCORE_COMMAND(moveWordRight)
+WEBCORE_COMMAND(moveWordRightAndModifySelection)
+WEBCORE_COMMAND(outdent)
+WEBCORE_COMMAND(pageDown)
+WEBCORE_COMMAND(pageDownAndModifySelection)
+WEBCORE_COMMAND(pageUp)
+WEBCORE_COMMAND(pageUpAndModifySelection)
+WEBCORE_COMMAND(paste)
+WEBCORE_COMMAND(pasteAsPlainText)
+WEBCORE_COMMAND(scrollPageDown)
+WEBCORE_COMMAND(scrollPageUp)
+WEBCORE_COMMAND(scrollLineDown)
+WEBCORE_COMMAND(scrollLineUp)
+WEBCORE_COMMAND(scrollToBeginningOfDocument)
+WEBCORE_COMMAND(scrollToEndOfDocument)
+WEBCORE_COMMAND(selectAll)
+WEBCORE_COMMAND(selectLine)
+WEBCORE_COMMAND(selectParagraph)
+WEBCORE_COMMAND(selectSentence)
+WEBCORE_COMMAND(selectToMark)
+WEBCORE_COMMAND(selectWord)
+WEBCORE_COMMAND(setMark)
+WEBCORE_COMMAND(subscript)
+WEBCORE_COMMAND(superscript)
+WEBCORE_COMMAND(swapWithMark)
+WEBCORE_COMMAND(takeFindStringFromSelection)
+WEBCORE_COMMAND(transpose)
+WEBCORE_COMMAND(underline)
+WEBCORE_COMMAND(unscript)
+WEBCORE_COMMAND(yank)
+WEBCORE_COMMAND(yankAndSelect)
+
+#undef WEBCORE_COMMAND
+
+- (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types
 {
-    return [_wkView allowsBackForwardNavigationGestures];
+    return _impl->writeSelectionToPasteboard(pasteboard, types);
 }
 
-- (void)setAllowsMagnification:(BOOL)allowsMagnification
+- (void)centerSelectionInVisibleArea:(id)sender
 {
-    [_wkView setAllowsMagnification:allowsMagnification];
+    _impl->centerSelectionInVisibleArea();
 }
 
-- (BOOL)allowsMagnification
+- (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType
 {
-    return [_wkView allowsMagnification];
+    return _impl->validRequestorForSendAndReturnTypes(sendType, returnType);
 }
 
-- (void)setMagnification:(CGFloat)magnification
+- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pasteboard
 {
-    [_wkView setMagnification:magnification];
+    return _impl->readSelectionFromPasteboard(pasteboard);
 }
 
-- (CGFloat)magnification
+- (void)changeFont:(id)sender
 {
-    return [_wkView magnification];
+    _impl->changeFontFromFontPanel();
 }
 
-- (void)setMagnification:(CGFloat)magnification centeredAtPoint:(CGPoint)point
+- (IBAction)startSpeaking:(id)sender
 {
-    [_wkView setMagnification:magnification centeredAtPoint:NSPointFromCGPoint(point)];
+    _impl->startSpeaking();
 }
 
-- (BOOL)_ignoresNonWheelEvents
+- (IBAction)stopSpeaking:(id)sender
 {
-    return [_wkView _ignoresNonWheelEvents];
+    _impl->stopSpeaking(sender);
 }
 
-- (void)_setIgnoresNonWheelEvents:(BOOL)ignoresNonWheelEvents
+- (IBAction)showGuessPanel:(id)sender
 {
-    [_wkView _setIgnoresNonWheelEvents:ignoresNonWheelEvents];
+    _impl->showGuessPanel(sender);
 }
 
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+- (IBAction)checkSpelling:(id)sender
 {
-    return [_wkView draggingEntered:sender];
+    _impl->checkSpelling();
 }
 
-- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+- (void)changeSpelling:(id)sender
 {
-    return [_wkView draggingUpdated:sender];
+    _impl->changeSpelling(sender);
 }
 
-- (void)draggingExited:(id <NSDraggingInfo>)sender
+- (IBAction)toggleContinuousSpellChecking:(id)sender
 {
-    [_wkView draggingExited:sender];
+    _impl->toggleContinuousSpellChecking();
 }
 
-- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
+- (BOOL)isGrammarCheckingEnabled
 {
-    return [_wkView prepareForDragOperation:sender];
+    return _impl->isGrammarCheckingEnabled();
 }
 
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+- (void)setGrammarCheckingEnabled:(BOOL)flag
 {
-    return [_wkView performDragOperation:sender];
+    _impl->setGrammarCheckingEnabled(flag);
 }
 
-- (CGSize)intrinsicContentSize
+- (IBAction)toggleGrammarChecking:(id)sender
 {
-    return _intrinsicContentSize;
+    _impl->toggleGrammarChecking();
 }
 
-- (void)_setIntrinsicContentSize:(CGSize)intrinsicContentSize
+- (IBAction)toggleAutomaticSpellingCorrection:(id)sender
 {
-    // If the intrinsic content size is less than the minimum layout width, the content flowed to fit,
-    // so we can report that that dimension is flexible. If not, we need to report our intrinsic width
-    // so that autolayout will know to provide space for us.
+    _impl->toggleAutomaticSpellingCorrection();
+}
 
-    CGSize intrinsicContentSizeAcknowledgingFlexibleWidth = intrinsicContentSize;
-    if (intrinsicContentSize.width < _page->minimumLayoutSize().width())
-        intrinsicContentSizeAcknowledgingFlexibleWidth.width = NSViewNoInstrinsicMetric;
+- (void)orderFrontSubstitutionsPanel:(id)sender
+{
+    _impl->orderFrontSubstitutionsPanel(sender);
+}
 
-    _intrinsicContentSize = intrinsicContentSizeAcknowledgingFlexibleWidth;
-    [self invalidateIntrinsicContentSize];
+- (IBAction)toggleSmartInsertDelete:(id)sender
+{
+    _impl->toggleSmartInsertDelete();
 }
 
-#endif // PLATFORM(MAC)
+- (BOOL)isAutomaticQuoteSubstitutionEnabled
+{
+    return _impl->isAutomaticQuoteSubstitutionEnabled();
+}
 
-@end
+- (void)setAutomaticQuoteSubstitutionEnabled:(BOOL)flag
+{
+    _impl->setAutomaticQuoteSubstitutionEnabled(flag);
+}
 
-@implementation WKWebView (WKPrivate)
+- (void)toggleAutomaticQuoteSubstitution:(id)sender
+{
+    _impl->toggleAutomaticQuoteSubstitution();
+}
 
-- (BOOL)_isEditable
+- (BOOL)isAutomaticDashSubstitutionEnabled
 {
-    return _page->isEditable();
+    return _impl->isAutomaticDashSubstitutionEnabled();
 }
 
-- (void)_setEditable:(BOOL)editable
+- (void)setAutomaticDashSubstitutionEnabled:(BOOL)flag
 {
-    _page->setEditable(editable);
-#if !PLATFORM(IOS)
-    [_wkView _addFontPanelObserver];
-#endif
+    _impl->setAutomaticDashSubstitutionEnabled(flag);
 }
 
-- (_WKRemoteObjectRegistry *)_remoteObjectRegistry
+- (void)toggleAutomaticDashSubstitution:(id)sender
 {
-    if (!_remoteObjectRegistry) {
-        _remoteObjectRegistry = adoptNS([[_WKRemoteObjectRegistry alloc] _initWithMessageSender:*_page]);
-        _page->process().processPool().addMessageReceiver(Messages::RemoteObjectRegistry::messageReceiverName(), _page->pageID(), [_remoteObjectRegistry remoteObjectRegistry]);
-    }
+    _impl->toggleAutomaticDashSubstitution();
+}
 
-    return _remoteObjectRegistry.get();
+- (BOOL)isAutomaticLinkDetectionEnabled
+{
+    return _impl->isAutomaticLinkDetectionEnabled();
 }
 
-- (WKBrowsingContextHandle *)_handle
+- (void)setAutomaticLinkDetectionEnabled:(BOOL)flag
 {
-    return [[[WKBrowsingContextHandle alloc] _initWithPageID:_page->pageID()] autorelease];
+    _impl->setAutomaticLinkDetectionEnabled(flag);
 }
 
-- (_WKRenderingProgressEvents)_observedRenderingProgressEvents
+- (void)toggleAutomaticLinkDetection:(id)sender
 {
-    return _observedRenderingProgressEvents;
+    _impl->toggleAutomaticLinkDetection();
 }
 
-- (id <WKHistoryDelegatePrivate>)_historyDelegate
+- (BOOL)isAutomaticTextReplacementEnabled
 {
-    return _navigationState->historyDelegate().autorelease();
+    return _impl->isAutomaticTextReplacementEnabled();
 }
 
-- (void)_setHistoryDelegate:(id <WKHistoryDelegatePrivate>)historyDelegate
+- (void)setAutomaticTextReplacementEnabled:(BOOL)flag
 {
-    _page->setHistoryClient(_navigationState->createHistoryClient());
-    _navigationState->setHistoryDelegate(historyDelegate);
+    _impl->setAutomaticTextReplacementEnabled(flag);
 }
 
-- (NSURL *)_unreachableURL
+- (void)toggleAutomaticTextReplacement:(id)sender
 {
-    return [NSURL _web_URLWithWTFString:_page->pageLoadState().unreachableURL()];
+    _impl->toggleAutomaticTextReplacement();
 }
 
-- (void)_loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
+- (void)uppercaseWord:(id)sender
 {
-    _page->loadAlternateHTMLString(string, [baseURL _web_originalDataAsWTFString], [unreachableURL _web_originalDataAsWTFString]);
+    _impl->uppercaseWord();
 }
 
-- (WKNavigation *)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL userData:(id)userData
+- (void)lowercaseWord:(id)sender
 {
-    auto navigation = _page->loadData(API::Data::createWithoutCopying(data).ptr(), MIMEType, characterEncodingName, baseURL.absoluteString, WebKit::ObjCObjectGraph::create(userData).ptr());
-    if (!navigation)
-        return nil;
+    _impl->lowercaseWord();
+}
 
-    return [wrapper(*navigation.release().leakRef()) autorelease];
+- (void)capitalizeWord:(id)sender
+{
+    _impl->capitalizeWord();
 }
 
-- (NSArray *)_certificateChain
+- (BOOL)_wantsKeyDownForEvent:(NSEvent *)event
 {
-    if (WebKit::WebFrameProxy* mainFrame = _page->mainFrame())
-        return mainFrame->certificateInfo() ? (NSArray *)mainFrame->certificateInfo()->certificateInfo().certificateChain() : nil;
+    return _impl->wantsKeyDownForEvent(event);
+}
 
-    return nil;
+- (void)scrollWheel:(NSEvent *)event
+{
+    _impl->scrollWheel(event);
 }
 
-- (NSURL *)_committedURL
+- (void)swipeWithEvent:(NSEvent *)event
 {
-    return [NSURL _web_URLWithWTFString:_page->pageLoadState().url()];
+    _impl->swipeWithEvent(event);
 }
 
-- (NSString *)_MIMEType
+- (void)mouseMoved:(NSEvent *)event
 {
-    if (_page->mainFrame())
-        return _page->mainFrame()->mimeType();
+    _impl->mouseMoved(event);
+}
 
-    return nil;
+- (void)mouseDown:(NSEvent *)event
+{
+    _impl->mouseDown(event);
 }
 
-- (NSString *)_userAgent
+- (void)mouseUp:(NSEvent *)event
 {
-    return _page->userAgent();
+    _impl->mouseUp(event);
 }
 
-- (NSString *)_applicationNameForUserAgent
+- (void)mouseDragged:(NSEvent *)event
 {
-    return _page->applicationNameForUserAgent();
+    _impl->mouseDragged(event);
 }
 
-- (void)_setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
+- (void)mouseEntered:(NSEvent *)event
 {
-    _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
+    _impl->mouseEntered(event);
 }
 
-- (NSString *)_customUserAgent
+- (void)mouseExited:(NSEvent *)event
 {
-    return self.customUserAgent;
+    _impl->mouseExited(event);
 }
 
-- (void)_setCustomUserAgent:(NSString *)customUserAgent
+- (void)otherMouseDown:(NSEvent *)event
 {
-    self.customUserAgent = customUserAgent;
+    _impl->otherMouseDown(event);
 }
 
-- (void)_setUserContentExtensionsEnabled:(BOOL)userContentExtensionsEnabled
+- (void)otherMouseDragged:(NSEvent *)event
 {
-    // This is kept for binary compatibility with iOS 9.
+    _impl->otherMouseDragged(event);
 }
 
-- (BOOL)_userContentExtensionsEnabled
+- (void)otherMouseUp:(NSEvent *)event
 {
-    // This is kept for binary compatibility with iOS 9.
-    return true;
+    _impl->otherMouseUp(event);
 }
 
-- (pid_t)_webProcessIdentifier
+- (void)rightMouseDown:(NSEvent *)event
 {
-    return _page->isValid() ? _page->processIdentifier() : 0;
+    _impl->rightMouseDown(event);
 }
 
-- (void)_killWebContentProcess
+- (void)rightMouseDragged:(NSEvent *)event
 {
-    if (!_page->isValid())
-        return;
+    _impl->rightMouseDragged(event);
+}
 
-    _page->process().terminate();
+- (void)rightMouseUp:(NSEvent *)event
+{
+    _impl->rightMouseUp(event);
 }
 
-- (WKNavigation *)_reloadWithoutContentBlockers
+- (void)pressureChangeWithEvent:(NSEvent *)event
 {
-    const bool reloadFromOrigin = false;
-    const bool contentBlockersEnabled = false;
-    auto navigation = _page->reload(reloadFromOrigin, contentBlockersEnabled);
-    if (!navigation)
-        return nil;
-    
-    return [wrapper(*navigation.release().leakRef()) autorelease];
+    _impl->pressureChangeWithEvent(event);
 }
 
-- (void)_killWebContentProcessAndResetState
+- (BOOL)acceptsFirstMouse:(NSEvent *)event
 {
-    _page->terminateProcess();
+    return _impl->acceptsFirstMouse(event);
 }
 
-#if PLATFORM(IOS)
-static WebCore::FloatSize activeMinimumLayoutSize(WKWebView *webView, const CGRect& bounds)
+- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)event
 {
-    return WebCore::FloatSize(webView->_overridesMinimumLayoutSize ? webView->_minimumLayoutSizeOverride : bounds.size);
+    return _impl->shouldDelayWindowOrderingForEvent(event);
 }
 
-static WebCore::FloatSize activeMaximumUnobscuredSize(WKWebView *webView, const CGRect& bounds)
+- (void)doCommandBySelector:(SEL)selector
 {
-    return WebCore::FloatSize(webView->_overridesMaximumUnobscuredSize ? webView->_maximumUnobscuredSizeOverride : bounds.size);
+    _impl->doCommandBySelector(selector);
 }
 
-static int32_t activeOrientation(WKWebView *webView)
+- (void)insertText:(id)string
 {
-    return webView->_overridesInterfaceOrientation ? deviceOrientationForUIInterfaceOrientation(webView->_interfaceOrientationOverride) : webView->_page->deviceOrientation();
+    _impl->insertText(string);
 }
 
-- (void (^)(void))_retainActiveFocusedState
+- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
+{
+    _impl->insertText(string, replacementRange);
+}
+
+- (NSTextInputContext *)inputContext
+{
+    return _impl->inputContext();
+}
+
+- (BOOL)performKeyEquivalent:(NSEvent *)event
+{
+    return _impl->performKeyEquivalent(event);
+}
+
+- (void)keyUp:(NSEvent *)theEvent
+{
+    _impl->keyUp(theEvent);
+}
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+    _impl->keyDown(theEvent);
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+    _impl->flagsChanged(theEvent);
+}
+
+- (void)setMarkedText:(id)string selectedRange:(NSRange)newSelectedRange replacementRange:(NSRange)replacementRange
+{
+    _impl->setMarkedText(string, newSelectedRange, replacementRange);
+}
+
+- (void)unmarkText
+{
+    _impl->unmarkText();
+}
+
+- (NSRange)selectedRange
+{
+    return _impl->selectedRange();
+}
+
+- (BOOL)hasMarkedText
+{
+    return _impl->hasMarkedText();
+}
+
+- (NSRange)markedRange
+{
+    return _impl->markedRange();
+}
+
+- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)nsRange actualRange:(NSRangePointer)actualRange
+{
+    return _impl->attributedSubstringForProposedRange(nsRange, actualRange);
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
+{
+    return _impl->characterIndexForPoint(thePoint);
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePointer)actualRange
+{
+    return _impl->firstRectForCharacterRange(theRange, actualRange);
+}
+
+- (void)selectedRangeWithCompletionHandler:(void(^)(NSRange selectedRange))completionHandlerPtr
+{
+    _impl->selectedRangeWithCompletionHandler(completionHandlerPtr);
+}
+
+- (void)markedRangeWithCompletionHandler:(void(^)(NSRange markedRange))completionHandlerPtr
+{
+    _impl->markedRangeWithCompletionHandler(completionHandlerPtr);
+}
+
+- (void)hasMarkedTextWithCompletionHandler:(void(^)(BOOL hasMarkedText))completionHandlerPtr
+{
+    _impl->hasMarkedTextWithCompletionHandler(completionHandlerPtr);
+}
+
+- (void)attributedSubstringForProposedRange:(NSRange)nsRange completionHandler:(void(^)(NSAttributedString *attrString, NSRange actualRange))completionHandlerPtr
+{
+    _impl->attributedSubstringForProposedRange(nsRange, completionHandlerPtr);
+}
+
+- (void)firstRectForCharacterRange:(NSRange)theRange completionHandler:(void(^)(NSRect firstRect, NSRange actualRange))completionHandlerPtr
+{
+    _impl->firstRectForCharacterRange(theRange, completionHandlerPtr);
+}
+
+- (void)characterIndexForPoint:(NSPoint)thePoint completionHandler:(void(^)(NSUInteger))completionHandlerPtr
+{
+    _impl->characterIndexForPoint(thePoint, completionHandlerPtr);
+}
+
+- (NSArray *)validAttributesForMarkedText
+{
+    return _impl->validAttributesForMarkedText();
+}
+
+#if ENABLE(DRAG_SUPPORT)
+- (void)draggedImage:(NSImage *)image endedAt:(NSPoint)endPoint operation:(NSDragOperation)operation
+{
+    _impl->draggedImage(image, NSPointToCGPoint(endPoint), operation);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)draggingInfo
+{
+    return _impl->draggingEntered(draggingInfo);
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)draggingInfo
+{
+    return _impl->draggingUpdated(draggingInfo);
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)draggingInfo
+{
+    _impl->draggingExited(draggingInfo);
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)draggingInfo
+{
+    return _impl->prepareForDragOperation(draggingInfo);
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)draggingInfo
+{
+    return _impl->performDragOperation(draggingInfo);
+}
+
+- (NSView *)_hitTest:(NSPoint *)point dragTypes:(NSSet *)types
+{
+    return _impl->hitTestForDragTypes(NSPointToCGPoint(*point), types);
+}
+#endif // ENABLE(DRAG_SUPPORT)
+
+- (BOOL)_windowResizeMouseLocationIsInVisibleScrollerThumb:(NSPoint)point
+{
+    return _impl->windowResizeMouseLocationIsInVisibleScrollerThumb(NSPointToCGPoint(point));
+}
+
+- (void)viewWillMoveToWindow:(NSWindow *)window
+{
+    _impl->viewWillMoveToWindow(window);
+}
+
+- (void)viewDidMoveToWindow
+{
+    _impl->viewDidMoveToWindow();
+}
+
+- (void)drawRect:(NSRect)rect
+{
+    _impl->drawRect(NSRectToCGRect(rect));
+}
+
+- (BOOL)isOpaque
+{
+    return _impl->isOpaque();
+}
+
+- (BOOL)mouseDownCanMoveWindow
+{
+    return WebKit::WebViewImpl::mouseDownCanMoveWindow();
+}
+
+- (void)viewDidHide
+{
+    _impl->viewDidHide();
+}
+
+- (void)viewDidUnhide
+{
+    _impl->viewDidUnhide();
+}
+
+- (void)viewDidChangeBackingProperties
+{
+    _impl->viewDidChangeBackingProperties();
+}
+
+- (void)_activeSpaceDidChange:(NSNotification *)notification
+{
+    _impl->activeSpaceDidChange();
+}
+
+- (id)accessibilityFocusedUIElement
+{
+    return _impl->accessibilityFocusedUIElement();
+}
+
+- (BOOL)accessibilityIsIgnored
+{
+    return _impl->accessibilityIsIgnored();
+}
+
+- (id)accessibilityHitTest:(NSPoint)point
+{
+    return _impl->accessibilityHitTest(NSPointToCGPoint(point));
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute
+{
+    return _impl->accessibilityAttributeValue(attribute);
+}
+
+- (NSView *)hitTest:(NSPoint)point
+{
+    if (!_impl)
+        return [super hitTest:point];
+    return _impl->hitTest(NSPointToCGPoint(point));
+}
+
+- (NSInteger)conversationIdentifier
+{
+    return (NSInteger)self;
+}
+
+- (void)quickLookWithEvent:(NSEvent *)event
+{
+    _impl->quickLookWithEvent(event);
+}
+
+- (NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside
+{
+    return _impl->addTrackingRect(NSRectToCGRect(rect), owner, data, assumeInside);
+}
+
+- (NSTrackingRectTag)_addTrackingRect:(NSRect)rect owner:(id)owner userData:(void *)data assumeInside:(BOOL)assumeInside useTrackingNum:(int)tag
+{
+    return _impl->addTrackingRectWithTrackingNum(NSRectToCGRect(rect), owner, data, assumeInside, tag);
+}
+
+- (void)_addTrackingRects:(NSRect *)rects owner:(id)owner userDataList:(void **)userDataList assumeInsideList:(BOOL *)assumeInsideList trackingNums:(NSTrackingRectTag *)trackingNums count:(int)count
+{
+    CGRect *cgRects = (CGRect *)calloc(1, sizeof(CGRect));
+    for (int i = 0; i < count; i++)
+        cgRects[i] = NSRectToCGRect(rects[i]);
+    _impl->addTrackingRectsWithTrackingNums(cgRects, owner, userDataList, assumeInsideList, trackingNums, count);
+    free(cgRects);
+}
+
+- (void)removeTrackingRect:(NSTrackingRectTag)tag
+{
+    if (!_impl)
+        return;
+    _impl->removeTrackingRect(tag);
+}
+
+- (void)_removeTrackingRects:(NSTrackingRectTag *)tags count:(int)count
+{
+    if (!_impl)
+        return;
+    _impl->removeTrackingRects(tags, count);
+}
+
+- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)data
+{
+    return _impl->stringForToolTip(tag);
+}
+
+- (void)pasteboardChangedOwner:(NSPasteboard *)pasteboard
+{
+    _impl->pasteboardChangedOwner(pasteboard);
+}
+
+- (void)pasteboard:(NSPasteboard *)pasteboard provideDataForType:(NSString *)type
+{
+    _impl->provideDataForPasteboard(pasteboard, type);
+}
+
+- (NSArray *)namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination
+{
+    return _impl->namesOfPromisedFilesDroppedAtDestination(dropDestination);
+}
+
+- (BOOL)wantsUpdateLayer
+{
+    return WebKit::WebViewImpl::wantsUpdateLayer();
+}
+
+- (void)updateLayer
+{
+    _impl->updateLayer();
+}
+
+- (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigationGestures
+{
+    _impl->setAllowsBackForwardNavigationGestures(allowsBackForwardNavigationGestures);
+}
+
+- (BOOL)allowsBackForwardNavigationGestures
+{
+    return _impl->allowsBackForwardNavigationGestures();
+}
+
+- (void)smartMagnifyWithEvent:(NSEvent *)event
+{
+    _impl->smartMagnifyWithEvent(event);
+}
+
+- (void)setMagnification:(double)magnification centeredAtPoint:(NSPoint)point
+{
+    _impl->setMagnification(magnification, NSPointToCGPoint(point));
+}
+
+- (void)setMagnification:(double)magnification
+{
+    _impl->setMagnification(magnification);
+}
+
+- (double)magnification
+{
+    return _impl->magnification();
+}
+
+- (void)setAllowsMagnification:(BOOL)allowsMagnification
+{
+    _impl->setAllowsMagnification(allowsMagnification);
+}
+
+- (BOOL)allowsMagnification
+{
+    return _impl->allowsMagnification();
+}
+
+- (void)magnifyWithEvent:(NSEvent *)event
+{
+    _impl->magnifyWithEvent(event);
+}
+
+#if ENABLE(MAC_GESTURE_EVENTS)
+- (void)rotateWithEvent:(NSEvent *)event
+{
+    _impl->rotateWithEvent(event);
+}
+#endif
+
+- (WKTextFinderClient *)_ensureTextFinderClient
+{
+    if (!_textFinderClient)
+        _textFinderClient = adoptNS([[WKTextFinderClient alloc] initWithPage:*_page view:self]);
+    return _textFinderClient.get();
+}
+
+- (void)findMatchesForString:(NSString *)targetString relativeToMatch:(id <NSTextFinderAsynchronousDocumentFindMatch>)relativeMatch findOptions:(NSTextFinderAsynchronousDocumentFindOptions)findOptions maxResults:(NSUInteger)maxResults resultCollector:(void (^)(NSArray *matches, BOOL didWrap))resultCollector
+{
+    [[self _ensureTextFinderClient] findMatchesForString:targetString relativeToMatch:relativeMatch findOptions:findOptions maxResults:maxResults resultCollector:resultCollector];
+}
+
+- (NSView *)documentContainerView
+{
+    return self;
+}
+
+- (void)getSelectedText:(void (^)(NSString *selectedTextString))completionHandler
+{
+    [[self _ensureTextFinderClient] getSelectedText:completionHandler];
+}
+
+- (void)selectFindMatch:(id <NSTextFinderAsynchronousDocumentFindMatch>)findMatch completionHandler:(void (^)(void))completionHandler
+{
+    [[self _ensureTextFinderClient] selectFindMatch:findMatch completionHandler:completionHandler];
+}
+
+- (NSTextInputContext *)_web_superInputContext
+{
+    return [super inputContext];
+}
+
+- (void)_web_superQuickLookWithEvent:(NSEvent *)event
+{
+    [super quickLookWithEvent:event];
+}
+
+- (void)_web_superSwipeWithEvent:(NSEvent *)event
+{
+    [super swipeWithEvent:event];
+}
+
+- (void)_web_superMagnifyWithEvent:(NSEvent *)event
+{
+    [super magnifyWithEvent:event];
+}
+
+- (void)_web_superSmartMagnifyWithEvent:(NSEvent *)event
+{
+    [super smartMagnifyWithEvent:event];
+}
+
+- (void)_web_superRemoveTrackingRect:(NSTrackingRectTag)tag
+{
+    [super removeTrackingRect:tag];
+}
+
+- (id)_web_superAccessibilityAttributeValue:(NSString *)attribute
+{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    return [super accessibilityAttributeValue:attribute];
+#pragma clang diagnostic pop
+}
+
+- (void)_web_superDoCommandBySelector:(SEL)selector
+{
+    [super doCommandBySelector:selector];
+}
+
+- (BOOL)_web_superPerformKeyEquivalent:(NSEvent *)event
+{
+    return [super performKeyEquivalent:event];
+}
+
+- (void)_web_superKeyDown:(NSEvent *)event
+{
+    [super keyDown:event];
+}
+
+- (NSView *)_web_superHitTest:(NSPoint)point
+{
+    return [super hitTest:point];
+}
+
+- (id)_web_immediateActionAnimationControllerForHitTestResultInternal:(API::HitTestResult*)hitTestResult withType:(uint32_t)type userData:(API::Object*)userData
+{
+    id<NSSecureCoding> data = userData ? static_cast<id<NSSecureCoding>>(userData->wrapper()) : nil;
+    return [self _immediateActionAnimationControllerForHitTestResult:wrapper(*hitTestResult) withType:(_WKImmediateActionType)type userData:data];
+}
+
+// We don't expose these various bits of SPI like WKView does,
+// so have these internal methods just do the work (or do nothing):
+- (void)_web_prepareForImmediateActionAnimation
+{
+}
+
+- (void)_web_cancelImmediateActionAnimation
+{
+}
+
+- (void)_web_completeImmediateActionAnimation
+{
+}
+
+- (void)_web_didChangeContentSize:(NSSize)newSize
+{
+}
+
+- (void)_web_dismissContentRelativeChildWindows
+{
+    _impl->dismissContentRelativeChildWindowsFromViewOnly();
+}
+
+- (void)_web_dismissContentRelativeChildWindowsWithAnimation:(BOOL)withAnimation
+{
+    _impl->dismissContentRelativeChildWindowsWithAnimationFromViewOnly(withAnimation);
+}
+
+- (void)_web_gestureEventWasNotHandledByWebCore:(NSEvent *)event
+{
+    _impl->gestureEventWasNotHandledByWebCoreFromViewOnly(event);
+}
+
+#endif // PLATFORM(MAC)
+
+@end
+
+@implementation WKWebView (WKPrivate)
+
+- (BOOL)_isEditable
+{
+    return _page->isEditable();
+}
+
+- (void)_setEditable:(BOOL)editable
+{
+    _page->setEditable(editable);
+#if PLATFORM(MAC)
+    _impl->startObservingFontPanel();
+#endif
+}
+
+- (_WKRemoteObjectRegistry *)_remoteObjectRegistry
+{
+#if PLATFORM(MAC)
+    return _impl->remoteObjectRegistry();
+#else
+    if (!_remoteObjectRegistry) {
+        _remoteObjectRegistry = adoptNS([[_WKRemoteObjectRegistry alloc] _initWithMessageSender:*_page]);
+        _page->process().processPool().addMessageReceiver(Messages::RemoteObjectRegistry::messageReceiverName(), _page->pageID(), [_remoteObjectRegistry remoteObjectRegistry]);
+    }
+
+    return _remoteObjectRegistry.get();
+#endif
+}
+
+- (WKBrowsingContextHandle *)_handle
+{
+    return [[[WKBrowsingContextHandle alloc] _initWithPageID:_page->pageID()] autorelease];
+}
+
+- (_WKRenderingProgressEvents)_observedRenderingProgressEvents
+{
+    return _observedRenderingProgressEvents;
+}
+
+- (id <WKHistoryDelegatePrivate>)_historyDelegate
+{
+    return _navigationState->historyDelegate().autorelease();
+}
+
+- (void)_setHistoryDelegate:(id <WKHistoryDelegatePrivate>)historyDelegate
+{
+    _page->setHistoryClient(_navigationState->createHistoryClient());
+    _navigationState->setHistoryDelegate(historyDelegate);
+}
+
+- (NSURL *)_unreachableURL
+{
+    return [NSURL _web_URLWithWTFString:_page->pageLoadState().unreachableURL()];
+}
+
+- (void)_loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
+{
+    _page->loadAlternateHTMLString(string, [baseURL _web_originalDataAsWTFString], [unreachableURL _web_originalDataAsWTFString]);
+}
+
+- (WKNavigation *)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL userData:(id)userData
+{
+    auto navigation = _page->loadData(API::Data::createWithoutCopying(data).ptr(), MIMEType, characterEncodingName, baseURL.absoluteString, WebKit::ObjCObjectGraph::create(userData).ptr());
+    if (!navigation)
+        return nil;
+
+    return [wrapper(*navigation.release().leakRef()) autorelease];
+}
+
+- (NSArray *)_certificateChain
+{
+    if (WebKit::WebFrameProxy* mainFrame = _page->mainFrame())
+        return mainFrame->certificateInfo() ? (NSArray *)mainFrame->certificateInfo()->certificateInfo().certificateChain() : nil;
+
+    return nil;
+}
+
+- (NSURL *)_committedURL
+{
+    return [NSURL _web_URLWithWTFString:_page->pageLoadState().url()];
+}
+
+- (NSString *)_MIMEType
+{
+    if (_page->mainFrame())
+        return _page->mainFrame()->mimeType();
+
+    return nil;
+}
+
+- (NSString *)_userAgent
+{
+    return _page->userAgent();
+}
+
+- (NSString *)_applicationNameForUserAgent
+{
+    return _page->applicationNameForUserAgent();
+}
+
+- (void)_setApplicationNameForUserAgent:(NSString *)applicationNameForUserAgent
+{
+    _page->setApplicationNameForUserAgent(applicationNameForUserAgent);
+}
+
+- (NSString *)_customUserAgent
+{
+    return self.customUserAgent;
+}
+
+- (void)_setCustomUserAgent:(NSString *)customUserAgent
+{
+    self.customUserAgent = customUserAgent;
+}
+
+- (void)_setUserContentExtensionsEnabled:(BOOL)userContentExtensionsEnabled
+{
+    // This is kept for binary compatibility with iOS 9.
+}
+
+- (BOOL)_userContentExtensionsEnabled
+{
+    // This is kept for binary compatibility with iOS 9.
+    return true;
+}
+
+- (pid_t)_webProcessIdentifier
+{
+    return _page->isValid() ? _page->processIdentifier() : 0;
+}
+
+- (void)_killWebContentProcess
+{
+    if (!_page->isValid())
+        return;
+
+    _page->process().terminate();
+}
+
+- (WKNavigation *)_reloadWithoutContentBlockers
+{
+    const bool reloadFromOrigin = false;
+    const bool contentBlockersEnabled = false;
+    auto navigation = _page->reload(reloadFromOrigin, contentBlockersEnabled);
+    if (!navigation)
+        return nil;
+    
+    return [wrapper(*navigation.release().leakRef()) autorelease];
+}
+
+- (void)_killWebContentProcessAndResetState
+{
+    _page->terminateProcess();
+}
+
+#if PLATFORM(IOS)
+static WebCore::FloatSize activeMinimumLayoutSize(WKWebView *webView, const CGRect& bounds)
+{
+    return WebCore::FloatSize(webView->_overridesMinimumLayoutSize ? webView->_minimumLayoutSizeOverride : bounds.size);
+}
+
+static WebCore::FloatSize activeMaximumUnobscuredSize(WKWebView *webView, const CGRect& bounds)
+{
+    return WebCore::FloatSize(webView->_overridesMaximumUnobscuredSize ? webView->_maximumUnobscuredSizeOverride : bounds.size);
+}
+
+static int32_t activeOrientation(WKWebView *webView)
+{
+    return webView->_overridesInterfaceOrientation ? deviceOrientationForUIInterfaceOrientation(webView->_interfaceOrientationOverride) : webView->_page->deviceOrientation();
+}
+
+- (void (^)(void))_retainActiveFocusedState
 {
     ++_activeFocusedStateRetainCount;
 
@@ -2165,6 +3189,10 @@ static int32_t activeOrientation(WKWebView *webView)
     return nil;
 }
 
+- (NSArray *)_dataDetectionResults
+{
+    return [_contentView _dataDetectionResults];
+}
 #endif
 
 - (void)_didRelaunchProcess
@@ -2197,7 +3225,7 @@ static int32_t activeOrientation(WKWebView *webView)
     if (!WebKit::decodeLegacySessionState(static_cast<const uint8_t*>(sessionStateData.bytes), sessionStateData.length, sessionState))
         return;
 
-    _page->restoreFromSessionState(WTF::move(sessionState), true);
+    _page->restoreFromSessionState(WTFMove(sessionState), true);
 }
 
 - (WKNavigation *)_restoreSessionState:(_WKSessionState *)sessionState andNavigate:(BOOL)navigate
@@ -2230,6 +3258,22 @@ static int32_t activeOrientation(WKWebView *webView)
 #endif
 }
 
+- (NSString *)_remoteInspectionNameOverride
+{
+#if ENABLE(REMOTE_INSPECTOR)
+    return _page->remoteInspectionNameOverride();
+#else
+    return nil;
+#endif
+}
+
+- (void)_setRemoteInspectionNameOverride:(NSString *)name
+{
+#if ENABLE(REMOTE_INSPECTOR)
+    _page->setRemoteInspectionNameOverride(name);
+#endif
+}
+
 - (BOOL)_addsVisitedLinks
 {
     return _page->addsVisitedLinks();
@@ -2381,6 +3425,16 @@ static inline WebCore::LayoutMilestones layoutMilestones(_WKRenderingProgressEve
     _page->setGapBetweenPages(gapBetweenPages);
 }
 
+- (BOOL)_paginationLineGridEnabled
+{
+    return _page->paginationLineGridEnabled();
+}
+
+- (void)_setPaginationLineGridEnabled:(BOOL)lineGridEnabled
+{
+    _page->setPaginationLineGridEnabled(lineGridEnabled);
+}
+
 - (NSUInteger)_pageCount
 {
     return _page->pageCount();
@@ -2518,7 +3572,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 
         virtual ~FormClient() { }
 
-        virtual void willSubmitForm(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, WebKit::WebFrameProxy& sourceFrame, const Vector<std::pair<WTF::String, WTF::String>>& textFieldValues, API::Object* userData, Ref<WebKit::WebFormSubmissionListenerProxy>&& listener) override
+        void willSubmitForm(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, WebKit::WebFrameProxy& sourceFrame, const Vector<std::pair<WTF::String, WTF::String>>& textFieldValues, API::Object* userData, Ref<WebKit::WebFormSubmissionListenerProxy>&& listener) override
         {
             if (userData && userData->type() != API::Object::Type::Data) {
                 ASSERT(!userData || userData->type() == API::Object::Type::Data);
@@ -2550,7 +3604,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
                 }
             }
 
-            RefPtr<WebKit::WebFormSubmissionListenerProxy> localListener = WTF::move(listener);
+            RefPtr<WebKit::WebFormSubmissionListenerProxy> localListener = WTFMove(listener);
             RefPtr<WebKit::CompletionHandlerCallChecker> checker = WebKit::CompletionHandlerCallChecker::create(inputDelegate.get(), @selector(_webView:willSubmitFormValues:userObject:submissionHandler:));
             [inputDelegate _webView:m_webView willSubmitFormValues:valueMap.get() userObject:userObject submissionHandler:[localListener, checker] {
                 checker->didCallCompletionHandler();
@@ -2595,7 +3649,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 - (_WKLayoutMode)_layoutMode
 {
 #if PLATFORM(MAC)
-    switch ([_wkView _layoutMode]) {
+    switch (_impl->layoutMode()) {
     case kWKLayoutModeFixedSize:
         return _WKLayoutModeFixedSize;
     case kWKLayoutModeDynamicSizeComputedFromViewScale:
@@ -2630,7 +3684,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
         wkViewLayoutMode = kWKLayoutModeViewSize;
         break;
     }
-    [_wkView _setLayoutMode:wkViewLayoutMode];
+    _impl->setLayoutMode(wkViewLayoutMode);
 #else
     _page->setUseFixedLayout(layoutMode == _WKLayoutModeFixedSize || layoutMode == _WKLayoutModeDynamicSizeComputedFromViewScale);
 #endif
@@ -2654,7 +3708,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 - (void)_setViewScale:(CGFloat)viewScale
 {
 #if PLATFORM(MAC)
-    [_wkView _setViewScale:viewScale];
+    _impl->setViewScale(viewScale);
 #else
     if (viewScale <= 0 || isnan(viewScale) || isinf(viewScale))
         [NSException raise:NSInvalidArgumentException format:@"View scale should be a positive number"];
@@ -2702,6 +3756,11 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 #endif
 }
 
+- (BOOL)_webProcessIsResponsive
+{
+    return _page->process().responsivenessTimer().isResponsive();
+}
+
 #pragma mark iOS-specific methods
 
 #if PLATFORM(IOS)
@@ -2795,6 +3854,16 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     return _page->backgroundExtendsBeyondPage();
 }
 
+- (void)_setAllowsViewportShrinkToFit:(BOOL)allowShrinkToFit
+{
+    _allowsViewportShrinkToFit = allowShrinkToFit;
+}
+
+- (BOOL)_allowsViewportShrinkToFit
+{
+    return _allowsViewportShrinkToFit;
+}
+
 - (void)_beginInteractiveObscuredInsetsChange
 {
     ASSERT(!_isChangingObscuredInsetsInteractively);
@@ -3005,7 +4074,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 #if USE(IOSURFACE)
     // If we are parented and thus won't incur a significant penalty from paging in tiles, snapshot the view hierarchy directly.
     if (CADisplay *display = self.window.screen._display) {
-        auto surface = WebCore::IOSurface::create(WebCore::expandedIntSize(WebCore::FloatSize(imageSize)), WebCore::ColorSpaceDeviceRGB);
+        auto surface = WebCore::IOSurface::create(WebCore::expandedIntSize(WebCore::FloatSize(imageSize)), WebCore::ColorSpaceSRGB);
         CGFloat imageScaleInViewCoordinates = imageWidth / rectInViewCoordinates.size.width;
         CATransform3D transform = CATransform3DMakeScale(imageScaleInViewCoordinates, imageScaleInViewCoordinates, 1);
         transform = CATransform3DTranslate(transform, -rectInViewCoordinates.origin.x, -rectInViewCoordinates.origin.y, 0);
@@ -3093,16 +4162,6 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     return [(WKPDFView *)_customContentView.get() suggestedFilename];
 }
 
-- (CGFloat)_viewportMetaTagWidth
-{
-    return _viewportMetaTagWidth;
-}
-
-- (BOOL)_viewportIsUserScalable
-{
-    return [_scrollView isZoomEnabled] && [_scrollView minimumZoomScale] < [_scrollView maximumZoomScale];
-}
-
 - (_WKWebViewPrintFormatter *)_webViewPrintFormatter
 {
     UIViewPrintFormatter *viewPrintFormatter = self.viewPrintFormatter;
@@ -3114,74 +4173,78 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 
 #pragma mark - OS X-specific methods
 
-- (NSColor *)_pageExtendedBackgroundColor
+- (BOOL)_drawsBackground
 {
-    WebCore::Color color = _page->pageExtendedBackgroundColor();
-    if (!color.isValid())
-        return nil;
+    return _impl->drawsBackground();
+}
 
-    return nsColor(color);
+- (void)_setDrawsBackground:(BOOL)drawsBackground
+{
+    _impl->setDrawsBackground(drawsBackground);
 }
 
-- (BOOL)_drawsTransparentBackground
+#if WK_API_ENABLED
+- (NSView *)_inspectorAttachmentView
 {
-    return _page->drawsTransparentBackground();
+    return _impl->inspectorAttachmentView();
 }
 
-- (void)_setDrawsTransparentBackground:(BOOL)drawsTransparentBackground
+- (void)_setInspectorAttachmentView:(NSView *)newView
 {
-    _page->setDrawsTransparentBackground(drawsTransparentBackground);
+    _impl->setInspectorAttachmentView(newView);
 }
+#endif
 
-- (void)_setOverrideDeviceScaleFactor:(CGFloat)deviceScaleFactor
+- (BOOL)_windowOcclusionDetectionEnabled
 {
-    [_wkView _setOverrideDeviceScaleFactor:deviceScaleFactor];
+    return _impl->windowOcclusionDetectionEnabled();
 }
 
-- (CGFloat)_overrideDeviceScaleFactor
+- (void)_setWindowOcclusionDetectionEnabled:(BOOL)enabled
 {
-    return [_wkView _overrideDeviceScaleFactor];
+    _impl->setWindowOcclusionDetectionEnabled(enabled);
 }
 
-- (id)_immediateActionAnimationControllerForHitTestResult:(_WKHitTestResult *)hitTestResult withType:(_WKImmediateActionType)type userData:(id<NSSecureCoding>)userData
+- (void)_setOverrideDeviceScaleFactor:(CGFloat)deviceScaleFactor
 {
-    return nil;
+    _impl->setOverrideDeviceScaleFactor(deviceScaleFactor);
+}
+
+- (CGFloat)_overrideDeviceScaleFactor
+{
+    return _impl->overrideDeviceScaleFactor();
 }
 
 - (void)_setTopContentInset:(CGFloat)contentInset
 {
-    [_wkView _setTopContentInset:contentInset];
+    return _impl->setTopContentInset(contentInset);
 }
 
 - (CGFloat)_topContentInset
 {
-    return [_wkView _topContentInset];
+    return _impl->topContentInset();
 }
 
-- (BOOL)_windowOcclusionDetectionEnabled
+- (NSColor *)_pageExtendedBackgroundColor
 {
-    return [_wkView windowOcclusionDetectionEnabled];
+    return _impl->pageExtendedBackgroundColor();
 }
 
-- (void)_setWindowOcclusionDetectionEnabled:(BOOL)flag
+- (id)_immediateActionAnimationControllerForHitTestResult:(_WKHitTestResult *)hitTestResult withType:(_WKImmediateActionType)type userData:(id<NSSecureCoding>)userData
 {
-    [_wkView setWindowOcclusionDetectionEnabled:flag];
+    return nil;
 }
 
-#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-
 - (void)_setAutomaticallyAdjustsContentInsets:(BOOL)automaticallyAdjustsContentInsets
 {
-    [_wkView _setAutomaticallyAdjustsContentInsets:automaticallyAdjustsContentInsets];
+    _impl->setAutomaticallyAdjustsContentInsets(automaticallyAdjustsContentInsets);
 }
 
 - (BOOL)_automaticallyAdjustsContentInsets
 {
-    return [_wkView _automaticallyAdjustsContentInsets];
+    return _impl->automaticallyAdjustsContentInsets();
 }
 
-#endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
-
 - (CGFloat)_minimumLayoutWidth
 {
     return _page->minimumLayoutSize().width();
@@ -3194,7 +4257,21 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     _page->setMinimumLayoutSize(WebCore::IntSize(width, 0));
     _page->setMainFrameIsScrollable(!expandsToFit);
 
-    [_wkView setShouldClipToVisibleRect:expandsToFit];
+    _impl->setClipsToVisibleRect(expandsToFit);
+}
+
+- (NSPrintOperation *)_printOperationWithPrintInfo:(NSPrintInfo *)printInfo
+{
+    if (auto webFrameProxy = _page->mainFrame())
+        return _impl->printOperationWithPrintInfo(printInfo, *webFrameProxy);
+    return nil;
+}
+
+- (NSPrintOperation *)_printOperationWithPrintInfo:(NSPrintInfo *)printInfo forFrame:(_WKFrameHandle *)frameHandle
+{
+    if (auto webFrameProxy = _page->process().webFrame(frameHandle._frameID))
+        return _impl->printOperationWithPrintInfo(printInfo, *webFrameProxy);
+    return nil;
 }
 
 #endif
@@ -3265,7 +4342,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
         return YES;
     }
 
-    return NO;
+    return _impl->validateUserInterfaceItem(item);
 }
 
 - (IBAction)goBack:(id)sender
@@ -3359,4 +4436,12 @@ static constexpr std::chrono::milliseconds didFinishLoadingTimeout = std::chrono
 @end
 #endif
 
+#if PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/WKWebViewAdditions.mm>
+#endif
+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200 && USE(APPLE_INTERNAL_SDK)
+#import <WebKitAdditions/WKWebViewAdditionsMac.mm>
+#endif
+
 #endif // WK_API_ENABLED