Subpixel layout: remove roundedLayoutPoint/roundedLayoutSize functions.
[WebKit-https.git] / Source / WebKit2 / UIProcess / ios / WebPageProxyIOS.mm
index ce714b2..f73f537 100644 (file)
 
 #if PLATFORM(IOS)
 
+#import "APIUIClient.h"
 #import "DataReference.h"
 #import "EditingRange.h"
 #import "NativeWebKeyboardEvent.h"
 #import "PageClient.h"
+#import "RemoteLayerTreeDrawingAreaProxy.h"
+#import "RemoteLayerTreeDrawingAreaProxyMessages.h"
 #import "RemoteLayerTreeTransaction.h"
 #import "ViewUpdateDispatcherMessages.h"
 #import "WKBrowsingContextControllerInternal.h"
 #import "WebPageMessages.h"
 #import "WebProcessProxy.h"
 #import "WebVideoFullscreenManagerProxy.h"
+#import <WebCore/FrameView.h>
 #import <WebCore/NotImplemented.h>
 #import <WebCore/SharedBuffer.h>
 #import <WebCore/UserAgent.h>
 
+#if USE(QUICK_LOOK)
+#import "APILoaderClient.h"
+#import <wtf/text/WTFString.h>
+#endif
+
 using namespace WebCore;
 
 namespace WebKit {
@@ -52,22 +61,14 @@ void WebPageProxy::platformInitialize()
 {
 }
 
-static String userVisibleWebKitVersionString()
+static String webKitBundleVersionString()
 {
-    // If the version is longer than 3 digits then the leading digits represent the version of the OS. Our user agent
-    // string should not include the leading digits, so strip them off and report the rest as the version. <rdar://problem/4997547>
-    NSString *fullVersion = [[NSBundle bundleForClass:NSClassFromString(@"WKView")] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
-    NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
-    if (nonDigitRange.location == NSNotFound && fullVersion.length > 3)
-        return [fullVersion substringFromIndex:fullVersion.length - 3];
-    if (nonDigitRange.location != NSNotFound && nonDigitRange.location > 3)
-        return [fullVersion substringFromIndex:nonDigitRange.location - 3];
-    return fullVersion;
+    return [[NSBundle bundleForClass:NSClassFromString(@"WKWebView")] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
 }
 
-String WebPageProxy::standardUserAgent(const String& applicationName)
+String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
 {
-    return standardUserAgentWithApplicationName(applicationName, userVisibleWebKitVersionString());
+    return standardUserAgentWithApplicationName(applicationNameForUserAgent, webKitBundleVersionString());
 }
 
 void WebPageProxy::getIsSpeaking(bool&)
@@ -125,7 +126,7 @@ void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint&)
 
 void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, uint64_t callbackID)
 {
-    RefPtr<GestureCallback> callback = m_gestureCallbacks.take(callbackID);
+    auto callback = m_callbacks.take<GestureCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
@@ -136,7 +137,7 @@ void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gest
 
 void WebPageProxy::touchesCallback(const WebCore::IntPoint& point, uint32_t touches, uint64_t callbackID)
 {
-    RefPtr<TouchesCallback> callback = m_touchesCallbacks.take(callbackID);
+    auto callback = m_callbacks.take<TouchesCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
@@ -147,7 +148,7 @@ void WebPageProxy::touchesCallback(const WebCore::IntPoint& point, uint32_t touc
 
 void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>& rects, const String& fontName, float fontSize, uint64_t fontTraits, uint64_t callbackID)
 {
-    RefPtr<AutocorrectionDataCallback> callback = m_autocorrectionCallbacks.take(callbackID);
+    auto callback = m_callbacks.take<AutocorrectionDataCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
@@ -158,7 +159,7 @@ void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>&
 
 void WebPageProxy::dictationContextCallback(const String& selectedText, const String& beforeText, const String& afterText, uint64_t callbackID)
 {
-    RefPtr<DictationContextCallback> callback = m_dictationContextCallbacks.take(callbackID);
+    auto callback = m_callbacks.take<DictationContextCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
@@ -169,7 +170,7 @@ void WebPageProxy::dictationContextCallback(const String& selectedText, const St
 
 void WebPageProxy::autocorrectionContextCallback(const String& beforeText, const String& markedText, const String& selectedText, const String& afterText, uint64_t location, uint64_t length, uint64_t callbackID)
 {
-    RefPtr<AutocorrectionContextCallback> callback = m_autocorrectionContextCallbacks.take(callbackID);
+    auto callback = m_callbacks.take<AutocorrectionContextCallback>(callbackID);
     if (!callback) {
         ASSERT_NOT_REACHED();
         return;
@@ -178,19 +179,133 @@ void WebPageProxy::autocorrectionContextCallback(const String& beforeText, const
     callback->performCallbackWithReturnValue(beforeText, markedText, selectedText, afterText, location, length);
 }
 
-bool WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdateInfo)
+void WebPageProxy::updateVisibleContentRects(const WebCore::FloatRect& exposedRect, const WebCore::FloatRect& unobscuredRect, const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& customFixedPositionRect, double scale, bool inStableState, bool isChangingObscuredInsetsInteractively, double timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate)
 {
+    if (!isValid())
+        return;
+
+    VisibleContentRectUpdateInfo visibleContentRectUpdateInfo(exposedRect, unobscuredRect, unobscuredRectInScrollViewCoordinates, customFixedPositionRect, scale, inStableState, isChangingObscuredInsetsInteractively, timestamp, horizontalVelocity, verticalVelocity, scaleChangeRate, toRemoteLayerTreeDrawingAreaProxy(drawingArea())->lastCommittedLayerTreeTransactionID());
+
     if (visibleContentRectUpdateInfo == m_lastVisibleContentRectUpdate)
-        return false;
+        return;
 
     m_lastVisibleContentRectUpdate = visibleContentRectUpdateInfo;
     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdateInfo), 0);
-    return true;
 }
 
-void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, double targetScale)
+void WebPageProxy::resendLastVisibleContentRects()
+{
+    m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
+}
+
+static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
+{
+    if (exposedRectEdge < documentEdge)
+        return documentEdge - factor * (documentEdge - exposedRectEdge);
+    
+    return exposedRectEdge;
+}
+
+static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
+{
+    if (exposedRectEdge > documentEdge)
+        return documentEdge + factor * (exposedRectEdge - documentEdge);
+    
+    return exposedRectEdge;
+}
+
+WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, double displayedContentScale, UnobscuredRectConstraint constraint) const
+{
+    FloatRect constrainedUnobscuredRect = unobscuredContentRect;
+    FloatSize contentsSize = m_pageClient.contentsSize();
+    FloatRect documentRect = FloatRect(FloatPoint(), contentsSize);
+
+    if (m_pageClient.isAssistingNode())
+        return documentRect;
+
+    if (constraint == UnobscuredRectConstraint::ConstrainedToDocumentRect)
+        constrainedUnobscuredRect.intersect(documentRect);
+
+    double minimumScale = m_pageClient.minimumZoomScale();
+    
+    if (displayedContentScale < minimumScale) {
+        const CGFloat slope = 12;
+        CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
+            
+        constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
+        constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
+        constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
+        constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
+    }
+    
+    return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(contentsSize), displayedContentScale, false, StickToViewportBounds);
+}
+
+void WebPageProxy::overflowScrollViewWillStartPanGesture()
+{
+    m_pageClient.overflowScrollViewWillStartPanGesture();
+}
+
+void WebPageProxy::overflowScrollViewDidScroll()
+{
+    m_pageClient.overflowScrollViewDidScroll();
+}
+
+void WebPageProxy::overflowScrollWillStartScroll()
+{
+    m_pageClient.overflowScrollWillStartScroll();
+}
+
+void WebPageProxy::overflowScrollDidEndScroll()
 {
-    m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, targetExposedContentRect, targetUnobscuredRect, targetScale), m_pageID);
+    m_pageClient.overflowScrollDidEndScroll();
+}
+
+void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const WebCore::FloatSize& minimumLayoutSizeForMinimalUI, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates,  double targetScale, int32_t deviceOrientation)
+{
+    if (!isValid())
+        return;
+
+    m_dynamicViewportSizeUpdateWaitingForTarget = true;
+    m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = true;
+    m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, minimumLayoutSizeForMinimalUI, maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect, targetUnobscuredRectInScrollViewCoordinates, targetScale, deviceOrientation), m_pageID);
+}
+
+void WebPageProxy::synchronizeDynamicViewportUpdate()
+{
+    if (!isValid())
+        return;
+
+    if (m_dynamicViewportSizeUpdateWaitingForTarget) {
+        // We do not want the UIProcess to finish animated resize with the old content size, scale, etc.
+        // If that happens, the UIProcess would start pushing new VisibleContentRectUpdateInfo to the WebProcess with
+        // invalid informations.
+        //
+        // Ideally, the animated resize should just be transactional, and the UIProcess would remain in the "resize" state
+        // until both DynamicViewportUpdateChangedTarget and the associated commitLayerTree are finished.
+        // The tricky part with such implementation is if a second animated resize starts before the end of the previous one.
+        // In that case, the values used for the target state needs to be computed from the output of the previous animated resize.
+        //
+        // The following is a workaround to have the UIProcess in a consistent state.
+        // Instead of handling nested resize, we block the UIProcess until the animated resize finishes.
+        double newScale;
+        FloatPoint newScrollPosition;
+        uint64_t nextValidLayerTreeTransactionID;
+        if (m_process->sendSync(Messages::WebPage::SynchronizeDynamicViewportUpdate(), Messages::WebPage::SynchronizeDynamicViewportUpdate::Reply(newScale, newScrollPosition, nextValidLayerTreeTransactionID), m_pageID, std::chrono::seconds(2))) {
+            m_dynamicViewportSizeUpdateWaitingForTarget = false;
+            m_dynamicViewportSizeUpdateLayerTreeTransactionID = nextValidLayerTreeTransactionID;
+            m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, nextValidLayerTreeTransactionID);
+        }
+
+    }
+
+    // If m_dynamicViewportSizeUpdateWaitingForTarget is false, we are waiting for the next valid frame with the hope it is the one for the new target.
+    // If m_dynamicViewportSizeUpdateWaitingForTarget is still true, this is a desesperate attempt to get the valid frame before finishing the animation.
+    if (m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit)
+        m_process->connection()->waitForAndDispatchImmediately<Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree>(m_pageID, std::chrono::seconds(1), IPC::InterruptWaitingIfSyncMessageArrives);
+
+    m_dynamicViewportSizeUpdateWaitingForTarget = false;
+    m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
 }
 
 void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size)
@@ -198,39 +313,56 @@ void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::Floa
     m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size), m_pageID);
 }
 
-void WebPageProxy::setMinimumLayoutSizeForMinimalUI(const WebCore::FloatSize& size)
+void WebPageProxy::setViewportConfigurationMinimumLayoutSizeForMinimalUI(const WebCore::FloatSize& size)
+{
+    m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSizeForMinimalUI(size), m_pageID);
+}
+
+void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
 {
-    m_process->send(Messages::WebPage::SetMinimumLayoutSizeForMinimalUI(size), m_pageID);
+    m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
+}
+
+void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
+{
+    if (deviceOrientation != m_deviceOrientation) {
+        m_deviceOrientation = deviceOrientation;
+        if (isValid())
+            m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
+    }
 }
 
 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
 {
     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
 
+    if (!m_dynamicViewportSizeUpdateWaitingForTarget && m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit) {
+        if (layerTreeTransaction.transactionID() >= m_dynamicViewportSizeUpdateLayerTreeTransactionID)
+            m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
+    }
+
     m_pageClient.didCommitLayerTree(layerTreeTransaction);
 }
 
-void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, PassRefPtr<GestureCallback> callback)
+void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, std::function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
         return;
     }
-    
-    uint64_t callbackID = callback->callbackID();
-    m_gestureCallbacks.set(callbackID, callback);
+
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, callbackID), m_pageID);
 }
 
-void WebPageProxy::updateSelectionWithTouches(const WebCore::IntPoint point, uint32_t touches, bool baseIsStart, PassRefPtr<TouchesCallback> callback)
+void WebPageProxy::updateSelectionWithTouches(const WebCore::IntPoint point, uint32_t touches, bool baseIsStart, std::function<void (const WebCore::IntPoint&, uint32_t, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(WebCore::IntPoint(), 0, CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_touchesCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
 }
     
@@ -244,30 +376,39 @@ void WebPageProxy::replaceSelectedText(const String& oldText, const String& newT
     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
 }
 
-void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, PassRefPtr<AutocorrectionDataCallback> callback)
+void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, std::function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_autocorrectionCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
 }
 
-void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, PassRefPtr<StringCallback> callback)
+void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, std::function<void (const String&, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(String(), CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_stringCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
 }
 
+void WebPageProxy::executeEditCommand(const String& commandName, std::function<void (CallbackBase::Error)> callbackFunction)
+{
+    if (!isValid()) {
+        callbackFunction(CallbackBase::Error::Unknown);
+        return;
+    }
+    
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
+    m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, callbackID), m_pageID);
+}
+
 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
 {
     bool autocorrectionApplied = false;
@@ -275,27 +416,25 @@ bool WebPageProxy::applyAutocorrection(const String& correction, const String& o
     return autocorrectionApplied;
 }
 
-void WebPageProxy::requestDictationContext(PassRefPtr<DictationContextCallback> callback)
+void WebPageProxy::requestDictationContext(std::function<void (const String&, const String&, const String&, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_dictationContextCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::RequestDictationContext(callbackID), m_pageID);
 }
 
-void WebPageProxy::requestAutocorrectionContext(PassRefPtr<AutocorrectionContextCallback> callback)
+void WebPageProxy::requestAutocorrectionContext(std::function<void (const String&, const String&, const String&, const String&, uint64_t, uint64_t, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(String(), String(), String(), String(), 0, 0, CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_autocorrectionContextCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
 }
 
@@ -304,15 +443,14 @@ void WebPageProxy::getAutocorrectionContext(String& beforeContext, String& marke
     m_process->sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
 }
 
-void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, PassRefPtr<GestureCallback> callback)
+void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, std::function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)> callbackFunction)
 {
     if (!isValid()) {
-        callback->invalidate();
+        callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
         return;
     }
 
-    uint64_t callbackID = callback->callbackID();
-    m_gestureCallbacks.set(callbackID, callback);
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
 }
 
@@ -388,6 +526,22 @@ void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
 }
 
+void WebPageProxy::selectWordBackward()
+{
+    m_process->send(Messages::WebPage::SelectWordBackward(), m_pageID);
+}
+
+void WebPageProxy::moveSelectionByOffset(int32_t offset, std::function<void (CallbackBase::Error)> callbackFunction)
+{
+    if (!isValid()) {
+        callbackFunction(CallbackBase::Error::Unknown);
+        return;
+    }
+    
+    uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), std::make_unique<ProcessThrottler::BackgroundActivityToken>(m_process->throttler()));
+    m_process->send(Messages::WebPage::MoveSelectionByOffset(offset, callbackID), m_pageID);
+}
+
 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
 {
     m_editorState = state;
@@ -455,14 +609,36 @@ void WebPageProxy::willStartUserTriggeredZooming()
     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
 }
 
-void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
+void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
 {
-    static uint64_t uniqueRequestID = 0;
-    requestID = ++uniqueRequestID;
+    process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID);
+}
 
+void WebPageProxy::commitPotentialTap()
+{
+    process().send(Messages::WebPage::CommitPotentialTap(), m_pageID);
+}
+
+void WebPageProxy::cancelPotentialTap()
+{
+    process().send(Messages::WebPage::CancelPotentialTap(), m_pageID);
+}
+
+void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
+{
     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
 }
 
+void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position)
+{
+    process().send(Messages::WebPage::InspectorNodeSearchMovedToPosition(position), m_pageID);
+}
+
+void WebPageProxy::inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint& position)
+{
+    process().send(Messages::WebPage::InspectorNodeSearchEndedAtPosition(position), m_pageID);
+}
+
 void WebPageProxy::blurAssistedNode()
 {
     process().send(Messages::WebPage::BlurAssistedNode(), m_pageID);
@@ -477,10 +653,29 @@ FloatSize WebPageProxy::availableScreenSize()
 {
     return FloatSize(WKGetAvailableScreenSize());
 }
+    
+float WebPageProxy::textAutosizingWidth()
+{
+    return WKGetScreenSize().width;
+}
 
 void WebPageProxy::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition)
 {
-    m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition);
+    if (m_dynamicViewportSizeUpdateWaitingForTarget) {
+        m_dynamicViewportSizeUpdateLayerTreeTransactionID = toRemoteLayerTreeDrawingAreaProxy(drawingArea())->nextLayerTreeTransactionID();
+        m_dynamicViewportSizeUpdateWaitingForTarget = false;
+        m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, m_dynamicViewportSizeUpdateLayerTreeTransactionID);
+    }
+}
+
+void WebPageProxy::restorePageState(const WebCore::FloatRect& exposedRect, double scale)
+{
+    m_pageClient.restorePageState(exposedRect, scale);
+}
+
+void WebPageProxy::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
+{
+    m_pageClient.restorePageCenterAndScale(center, scale);
 }
 
 void WebPageProxy::didGetTapHighlightGeometries(uint64_t requestID, const WebCore::Color& color, const Vector<WebCore::FloatQuad>& highlightedQuads, const WebCore::IntSize& topLeftRadius, const WebCore::IntSize& topRightRadius, const WebCore::IntSize& bottomLeftRadius, const WebCore::IntSize& bottomRightRadius)
@@ -488,14 +683,14 @@ void WebPageProxy::didGetTapHighlightGeometries(uint64_t requestID, const WebCor
     m_pageClient.didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
 }
 
-void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, IPC::MessageDecoder& decoder)
+void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, IPC::MessageDecoder& decoder)
 {
     RefPtr<API::Object> userData;
     WebContextUserMessageDecoder messageDecoder(userData, process());
     if (!decoder.decode(messageDecoder))
         return;
 
-    m_pageClient.startAssistingNode(information, userData.get());
+    m_pageClient.startAssistingNode(information, userIsInteracting, blurPreviousNode, userData.get());
 }
 
 void WebPageProxy::stopAssistingNode()
@@ -504,6 +699,16 @@ void WebPageProxy::stopAssistingNode()
 }
 
 #if ENABLE(INSPECTOR)
+void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
+{
+    m_pageClient.showInspectorHighlight(highlight);
+}
+
+void WebPageProxy::hideInspectorHighlight()
+{
+    m_pageClient.hideInspectorHighlight();
+}
+
 void WebPageProxy::showInspectorIndication()
 {
     m_pageClient.showInspectorIndication();
@@ -513,6 +718,16 @@ void WebPageProxy::hideInspectorIndication()
 {
     m_pageClient.hideInspectorIndication();
 }
+
+void WebPageProxy::enableInspectorNodeSearch()
+{
+    m_pageClient.enableInspectorNodeSearch();
+}
+
+void WebPageProxy::disableInspectorNodeSearch()
+{
+    m_pageClient.disableInspectorNodeSearch();
+}
 #endif
 
 void WebPageProxy::focusNextAssistedNode(bool isForward)
@@ -570,6 +785,51 @@ void WebPageProxy::zoomToRect(FloatRect rect, double minimumScale, double maximu
     m_pageClient.zoomToRect(rect, minimumScale, maximumScale);
 }
 
+void WebPageProxy::commitPotentialTapFailed()
+{
+    m_pageClient.commitPotentialTapFailed();
+}
+
+void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
+{
+    m_uiClient->didNotHandleTapAsClick(point);
+}
+
+void WebPageProxy::viewportMetaTagWidthDidChange(float width)
+{
+    m_pageClient.didChangeViewportMetaTagWidth(width);
+}
+
+void WebPageProxy::setUsesMinimalUI(bool usesMinimalUI)
+{
+    m_pageClient.setUsesMinimalUI(usesMinimalUI);
+}
+
+void WebPageProxy::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
+{
+    m_pageClient.didFinishDrawingPagesToPDF(pdfData);
+}
+
+void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
+{
+    process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
+}
+
+#if USE(QUICK_LOOK)
+    
+void WebPageProxy::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
+{
+    // Ensure that fileName isn't really a path name
+    static_assert(notFound + 1 == 0, "The following line assumes WTF::notFound equals -1");
+    m_loaderClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
+}
+
+void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
+{
+    m_loaderClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
+}
+#endif
+
 } // namespace WebKit
 
 #endif // PLATFORM(IOS)