b473f081a5075e443cce39b5dc37854bd68d86f2
[WebKit-https.git] / Source / WebKit / UIProcess / ios / WebPageProxyIOS.mm
1 /*
2  * Copyright (C) 2012-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WebPageProxy.h"
28
29 #if PLATFORM(IOS_FAMILY)
30
31 #import "APIUIClient.h"
32 #import "DataReference.h"
33 #import "EditingRange.h"
34 #import "InteractionInformationAtPosition.h"
35 #import "Logging.h"
36 #import "NativeWebKeyboardEvent.h"
37 #import "NavigationState.h"
38 #import "PageClient.h"
39 #import "PrintInfo.h"
40 #import "RemoteLayerTreeDrawingAreaProxy.h"
41 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
42 #import "RemoteLayerTreeTransaction.h"
43 #import "UIKitSPI.h"
44 #import "UserData.h"
45 #import "VideoFullscreenManagerProxy.h"
46 #import "ViewUpdateDispatcherMessages.h"
47 #import "WKBrowsingContextControllerInternal.h"
48 #import "WebPageMessages.h"
49 #import "WebProcessProxy.h"
50 #import <WebCore/FrameView.h>
51 #import <WebCore/NotImplemented.h>
52 #import <WebCore/PlatformScreen.h>
53 #import <WebCore/SharedBuffer.h>
54 #import <WebCore/UserAgent.h>
55 #import <WebCore/ValidationBubble.h>
56 #import <wtf/text/TextStream.h>
57
58 #if USE(QUICK_LOOK)
59 #import "APILoaderClient.h"
60 #import "APINavigationClient.h"
61 #import <wtf/text/WTFString.h>
62 #endif
63
64 namespace WebKit {
65 using namespace WebCore;
66
67 void WebPageProxy::platformInitialize()
68 {
69 }
70
71 String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
72 {
73     return standardUserAgentWithApplicationName(applicationNameForUserAgent);
74 }
75
76 void WebPageProxy::getIsSpeaking(bool&)
77 {
78     notImplemented();
79 }
80
81 void WebPageProxy::speak(const String&)
82 {
83     notImplemented();
84 }
85
86 void WebPageProxy::stopSpeaking()
87 {
88     notImplemented();
89 }
90
91 void WebPageProxy::searchWithSpotlight(const String&)
92 {
93     notImplemented();
94 }
95
96 void WebPageProxy::searchTheWeb(const String&)
97 {
98     notImplemented();
99 }
100
101 void WebPageProxy::windowAndViewFramesChanged(const FloatRect&, const FloatPoint&)
102 {
103     notImplemented();
104 }
105
106 String WebPageProxy::stringSelectionForPasteboard()
107 {
108     notImplemented();
109     return String();
110 }
111
112 RefPtr<WebCore::SharedBuffer> WebPageProxy::dataSelectionForPasteboard(const String&)
113 {
114     notImplemented();
115     return nullptr;
116 }
117
118 bool WebPageProxy::readSelectionFromPasteboard(const String&)
119 {
120     notImplemented();
121     return false;
122 }
123
124 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint&)
125 {
126     notImplemented();
127 }
128
129 void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, CallbackID callbackID)
130 {
131     auto callback = m_callbacks.take<GestureCallback>(callbackID);
132     if (!callback) {
133         ASSERT_NOT_REACHED();
134         return;
135     }
136     
137     callback->performCallbackWithReturnValue(point, gestureType, gestureState, flags);
138 }
139
140 void WebPageProxy::touchesCallback(const WebCore::IntPoint& point, uint32_t touches, uint32_t flags, CallbackID callbackID)
141 {
142     auto callback = m_callbacks.take<TouchesCallback>(callbackID);
143     if (!callback) {
144         ASSERT_NOT_REACHED();
145         return;
146     }
147
148     callback->performCallbackWithReturnValue(point, touches, flags);
149 }
150
151 void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>& rects, const String& fontName, float fontSize, uint64_t fontTraits, CallbackID callbackID)
152 {
153     auto callback = m_callbacks.take<AutocorrectionDataCallback>(callbackID);
154     if (!callback) {
155         ASSERT_NOT_REACHED();
156         return;
157     }
158
159     callback->performCallbackWithReturnValue(rects, fontName, fontSize, fontTraits);
160 }
161
162 void WebPageProxy::selectionContextCallback(const String& selectedText, const String& beforeText, const String& afterText, CallbackID callbackID)
163 {
164     auto callback = m_callbacks.take<SelectionContextCallback>(callbackID);
165     if (!callback) {
166         ASSERT_NOT_REACHED();
167         return;
168     }
169
170     callback->performCallbackWithReturnValue(selectedText, beforeText, afterText);
171 }
172
173 void WebPageProxy::autocorrectionContextCallback(const String& beforeText, const String& markedText, const String& selectedText, const String& afterText, uint64_t location, uint64_t length, CallbackID callbackID)
174 {
175     auto callback = m_callbacks.take<AutocorrectionContextCallback>(callbackID);
176     if (!callback) {
177         ASSERT_NOT_REACHED();
178         return;
179     }
180
181     callback->performCallbackWithReturnValue(beforeText, markedText, selectedText, afterText, location, length);
182 }
183
184 void WebPageProxy::selectionRectsCallback(const Vector<WebCore::SelectionRect>& selectionRects, CallbackID callbackID)
185 {
186     auto callback = m_callbacks.take<SelectionRectsCallback>(callbackID);
187     if (!callback) {
188         ASSERT_NOT_REACHED();
189         return;
190     }
191     
192     callback->performCallbackWithReturnValue(selectionRects);
193 }
194
195 void WebPageProxy::assistedNodeInformationCallback(const AssistedNodeInformation& info, CallbackID callbackID)
196 {
197     auto callback = m_callbacks.take<AssistedNodeInformationCallback>(callbackID);
198     if (!callback) {
199         ASSERT_NOT_REACHED();
200         return;
201     }
202
203     callback->performCallbackWithReturnValue(info);
204 }
205
206 void WebPageProxy::requestAssistedNodeInformation(Function<void(const AssistedNodeInformation&, CallbackBase::Error)>&& callback)
207 {
208     if (!isValid()) {
209         callback({ }, CallbackBase::Error::OwnerWasInvalidated);
210         return;
211     }
212
213     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
214     m_process->send(Messages::WebPage::RequestAssistedNodeInformation(callbackID), m_pageID);
215 }
216
217 void WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdate)
218 {
219     if (!isValid())
220         return;
221
222     if (visibleContentRectUpdate == m_lastVisibleContentRectUpdate)
223         return;
224
225     m_lastVisibleContentRectUpdate = visibleContentRectUpdate;
226     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdate), 0);
227 }
228
229 void WebPageProxy::resendLastVisibleContentRects()
230 {
231     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
232 }
233
234 static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
235 {
236     if (exposedRectEdge < documentEdge)
237         return documentEdge - factor * (documentEdge - exposedRectEdge);
238     
239     return exposedRectEdge;
240 }
241
242 static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
243 {
244     if (exposedRectEdge > documentEdge)
245         return documentEdge + factor * (exposedRectEdge - documentEdge);
246     
247     return exposedRectEdge;
248 }
249
250 // FIXME: rename this when visual viewports are the default.
251 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& unobscuredContentRectRespectingInputViewBounds, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, FrameView::LayoutViewportConstraint constraint, bool visualViewportEnabled) const
252 {
253     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
254     FloatRect documentRect = pageClient().documentRect();
255
256     if (!visualViewportEnabled && pageClient().isAssistingNode())
257         return documentRect;
258
259     if (constraint == FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect)
260         constrainedUnobscuredRect.intersect(documentRect);
261
262     double minimumScale = pageClient().minimumZoomScale();
263     bool isBelowMinimumScale = displayedContentScale < minimumScale;
264     if (isBelowMinimumScale) {
265         const CGFloat slope = 12;
266         CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
267             
268         constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
269         constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
270         constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
271         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
272     }
273
274     if (!visualViewportEnabled)
275         return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
276         
277     FloatSize constrainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
278     FloatRect unobscuredContentRectForViewport = isBelowMinimumScale ? constrainedUnobscuredRect : unobscuredContentRectRespectingInputViewBounds;
279
280     auto layoutViewportSize = FrameView::expandedLayoutViewportSize(m_baseLayoutViewportSize, LayoutSize(documentRect.size()), m_preferences->layoutViewportHeightExpansionFactor());
281     FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constrainedSize), LayoutRect(unobscuredContentRectForViewport), layoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
282     
283     if (layoutViewportRect != currentCustomFixedPositionRect)
284         LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
285     return layoutViewportRect;
286 }
287
288 void WebPageProxy::scrollingNodeScrollViewWillStartPanGesture()
289 {
290     pageClient().scrollingNodeScrollViewWillStartPanGesture();
291 }
292
293 void WebPageProxy::scrollingNodeScrollViewDidScroll()
294 {
295     pageClient().scrollingNodeScrollViewDidScroll();
296 }
297
298 void WebPageProxy::scrollingNodeScrollWillStartScroll()
299 {
300     pageClient().scrollingNodeScrollWillStartScroll();
301 }
302
303 void WebPageProxy::scrollingNodeScrollDidEndScroll()
304 {
305     pageClient().scrollingNodeScrollDidEndScroll();
306 }
307
308 void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& viewLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation, DynamicViewportSizeUpdateID dynamicViewportSizeUpdateID)
309 {
310     if (!isValid())
311         return;
312
313     hideValidationMessage();
314
315     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(viewLayoutSize,
316         maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect,
317         targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets,
318         targetScale, deviceOrientation, dynamicViewportSizeUpdateID), m_pageID);
319 }
320
321 void WebPageProxy::setViewportConfigurationViewLayoutSize(const WebCore::FloatSize& size, double scaleFactor, double minimumEffectiveDeviceWidth)
322 {
323     m_viewportConfigurationViewLayoutSize = size;
324     m_viewportConfigurationLayoutSizeScaleFactor = scaleFactor;
325
326     if (isValid())
327         m_process->send(Messages::WebPage::SetViewportConfigurationViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth), m_pageID);
328 }
329
330 void WebPageProxy::setForceAlwaysUserScalable(bool userScalable)
331 {
332     if (m_forceAlwaysUserScalable == userScalable)
333         return;
334     m_forceAlwaysUserScalable = userScalable;
335
336     if (isValid())
337         m_process->send(Messages::WebPage::SetForceAlwaysUserScalable(userScalable), m_pageID);
338 }
339
340 void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
341 {
342     m_maximumUnobscuredSize = size;
343
344     if (isValid())
345         m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
346 }
347
348 void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
349 {
350     if (deviceOrientation != m_deviceOrientation) {
351         m_deviceOrientation = deviceOrientation;
352         if (isValid())
353             m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
354     }
355 }
356
357 void WebPageProxy::setOverrideViewportArguments(const std::optional<ViewportArguments>& viewportArguments)
358 {
359     if (isValid())
360         m_process->send(Messages::WebPage::SetOverrideViewportArguments(viewportArguments), m_pageID);
361 }
362
363 static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t committedSize)
364 {
365     const double thesholdSizeFraction = 0.5; // Empirically-derived.
366     return committedSize > thresholdSize * thesholdSizeFraction;
367 }
368
369 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
370 {
371     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
372
373     if (!m_hasReceivedLayerTreeTransactionAfterDidCommitLoad) {
374         if (layerTreeTransaction.transactionID() >= m_firstLayerTreeTransactionIdAfterDidCommitLoad) {
375             m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = true;
376             m_lastVisibleContentRectUpdate = VisibleContentRectUpdateInfo();
377         }
378     }
379
380     pageClient().didCommitLayerTree(layerTreeTransaction);
381
382     // FIXME: Remove this special mechanism and fold it into the transaction's layout milestones.
383     if (m_observedLayoutMilestones.contains(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold) && !m_hitRenderTreeSizeThreshold
384         && exceedsRenderTreeSizeSizeThreshold(m_sessionRestorationRenderTreeSize, layerTreeTransaction.renderTreeSize())) {
385         m_hitRenderTreeSizeThreshold = true;
386         didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
387     }
388
389     if (m_deferredNodeAssistanceArguments) {
390         pageClient().startAssistingNode(m_deferredNodeAssistanceArguments->m_nodeInformation, m_deferredNodeAssistanceArguments->m_userIsInteracting, m_deferredNodeAssistanceArguments->m_blurPreviousNode,
391             m_deferredNodeAssistanceArguments->m_changingActivityState, m_deferredNodeAssistanceArguments->m_userData.get());
392         m_deferredNodeAssistanceArguments = nullptr;
393     }
394 }
395
396 bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
397 {
398     if (m_baseLayoutViewportSize == layerTreeTransaction.baseLayoutViewportSize()
399         && m_minStableLayoutViewportOrigin == layerTreeTransaction.minStableLayoutViewportOrigin()
400         && m_maxStableLayoutViewportOrigin == layerTreeTransaction.maxStableLayoutViewportOrigin())
401         return false;
402
403     m_baseLayoutViewportSize = layerTreeTransaction.baseLayoutViewportSize();
404     m_minStableLayoutViewportOrigin = layerTreeTransaction.minStableLayoutViewportOrigin();
405     m_maxStableLayoutViewportOrigin = layerTreeTransaction.maxStableLayoutViewportOrigin();
406
407     LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::updateLayoutViewportParameters: baseLayoutViewportSize: " << m_baseLayoutViewportSize << " minStableLayoutViewportOrigin: " << m_minStableLayoutViewportOrigin << " maxStableLayoutViewportOrigin: " << m_maxStableLayoutViewportOrigin);
408
409     return true;
410 }
411
412 void WebPageProxy::layerTreeCommitComplete()
413 {
414     pageClient().layerTreeCommitComplete();
415 }
416
417 void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)>&& callbackFunction)
418 {
419     if (!isValid()) {
420         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
421         return;
422     }
423
424     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
425     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, isInteractingWithAssistedNode, callbackID), m_pageID);
426 }
427
428 void WebPageProxy::updateSelectionWithTouches(const WebCore::IntPoint point, uint32_t touches, bool baseIsStart, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, CallbackBase::Error)>&& callbackFunction)
429 {
430     if (!isValid()) {
431         callbackFunction(WebCore::IntPoint(), 0, 0, CallbackBase::Error::Unknown);
432         return;
433     }
434
435     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
436     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
437 }
438     
439 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
440 {
441     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
442 }
443
444 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
445 {
446     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
447 }
448
449 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, WTF::Function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)>&& callbackFunction)
450 {
451     if (!isValid()) {
452         callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, CallbackBase::Error::Unknown);
453         return;
454     }
455
456     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
457     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
458 }
459
460 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
461 {
462     if (!isValid()) {
463         callbackFunction(String(), CallbackBase::Error::Unknown);
464         return;
465     }
466
467     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
468     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
469 }
470
471 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
472 {
473     bool autocorrectionApplied = false;
474     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
475     return autocorrectionApplied;
476 }
477
478 void WebPageProxy::selectTextWithGranularityAtPoint(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithAssistedNode, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
479 {
480     if (!isValid()) {
481         callbackFunction(CallbackBase::Error::Unknown);
482         return;
483     }
484     
485     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
486     m_process->send(Messages::WebPage::SelectTextWithGranularityAtPoint(point, static_cast<uint32_t>(granularity), isInteractingWithAssistedNode, callbackID), m_pageID);
487 }
488
489 void WebPageProxy::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint point, WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, bool isInteractingWithAssistedNode, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
490 {
491     if (!isValid()) {
492         callbackFunction(CallbackBase::Error::Unknown);
493         return;
494     }
495     
496     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
497     m_process->send(Messages::WebPage::SelectPositionAtBoundaryWithDirection(point, static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), isInteractingWithAssistedNode, callbackID), m_pageID);
498 }
499
500 void WebPageProxy::moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
501 {
502     if (!isValid()) {
503         callbackFunction(CallbackBase::Error::Unknown);
504         return;
505     }
506     
507     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
508     m_process->send(Messages::WebPage::MoveSelectionAtBoundaryWithDirection(static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), callbackID), m_pageID);
509 }
510     
511 void WebPageProxy::selectPositionAtPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
512 {
513     if (!isValid()) {
514         callbackFunction(CallbackBase::Error::Unknown);
515         return;
516     }
517     
518     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
519     m_process->send(Messages::WebPage::SelectPositionAtPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
520 }
521
522 void WebPageProxy::beginSelectionInDirection(WebCore::SelectionDirection direction, WTF::Function<void (uint64_t, CallbackBase::Error)>&& callbackFunction)
523 {
524     if (!isValid()) {
525         callbackFunction(0, CallbackBase::Error::Unknown);
526         return;
527     }
528     
529     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
530     m_process->send(Messages::WebPage::BeginSelectionInDirection(direction, callbackID), m_pageID);
531 }
532
533 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, WTF::Function<void (uint64_t, CallbackBase::Error)>&& callbackFunction)
534 {
535     if (!isValid()) {
536         callbackFunction(0, CallbackBase::Error::Unknown);
537         return;
538     }
539     
540     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
541     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
542     
543 }
544
545 void WebPageProxy::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithAssistedNode, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
546 {
547     if (!isValid()) {
548         callbackFunction(0, CallbackBase::Error::Unknown);
549         return;
550     }
551     
552     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
553     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPointAndBoundary(point, granularity, isInteractingWithAssistedNode, callbackID), m_pageID);
554     
555 }
556
557 void WebPageProxy::requestDictationContext(WTF::Function<void (const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
558 {
559     if (!isValid()) {
560         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
561         return;
562     }
563
564     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
565     m_process->send(Messages::WebPage::RequestDictationContext(callbackID), m_pageID);
566 }
567
568 void WebPageProxy::requestAutocorrectionContext(WTF::Function<void (const String&, const String&, const String&, const String&, uint64_t, uint64_t, CallbackBase::Error)>&& callbackFunction)
569 {
570     if (!isValid()) {
571         callbackFunction(String(), String(), String(), String(), 0, 0, CallbackBase::Error::Unknown);
572         return;
573     }
574
575     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
576     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
577 }
578
579 void WebPageProxy::getAutocorrectionContext(String& beforeContext, String& markedText, String& selectedText, String& afterContext, uint64_t& location, uint64_t& length)
580 {
581     m_process->sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
582 }
583
584 void WebPageProxy::getSelectionContext(WTF::Function<void(const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
585 {
586     if (!isValid()) {
587         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
588         return;
589     }
590     
591     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
592     m_process->send(Messages::WebPage::GetSelectionContext(callbackID), m_pageID);
593 }
594
595 void WebPageProxy::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID)
596 {
597     process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, requestID), m_pageID);
598 }
599
600 void WebPageProxy::handleStylusSingleTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID)
601 {
602     process().send(Messages::WebPage::HandleStylusSingleTapAtPoint(point, requestID), m_pageID);
603 }
604
605 void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, WTF::Function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)>&& callbackFunction)
606 {
607     if (!isValid()) {
608         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
609         return;
610     }
611
612     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
613     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
614 }
615
616 void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition& info)
617 {
618     pageClient().positionInformationDidChange(info);
619 }
620
621 void WebPageProxy::requestPositionInformation(const InteractionInformationRequest& request)
622 {
623     m_process->send(Messages::WebPage::RequestPositionInformation(request), m_pageID);
624 }
625
626 void WebPageProxy::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)
627 {
628     m_process->send(Messages::WebPage::StartInteractionWithElementAtPosition(point), m_pageID);
629 }
630
631 void WebPageProxy::stopInteraction()
632 {
633     m_process->send(Messages::WebPage::StopInteraction(), m_pageID);
634 }
635
636 void WebPageProxy::performActionOnElement(uint32_t action)
637 {
638     m_process->send(Messages::WebPage::PerformActionOnElement(action), m_pageID);
639 }
640
641 void WebPageProxy::saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize)
642 {
643     auto sharedMemoryBuffer = SharedMemory::map(imageHandle, SharedMemory::Protection::ReadOnly);
644     auto buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
645     pageClient().saveImageToLibrary(WTFMove(buffer));
646 }
647
648 void WebPageProxy::applicationDidEnterBackground()
649 {
650     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
651
652 #if !PLATFORM(WATCHOS)
653     // We normally delay process suspension when the app is backgrounded until the current page load completes. However,
654     // we do not want to do so when the screen is locked for power reasons.
655     if (isSuspendedUnderLock)
656         NavigationState::fromWebPage(*this).releaseNetworkActivityToken(NavigationState::NetworkActivityTokenReleaseReason::ScreenLocked);
657 #endif
658     m_process->send(Messages::WebPage::ApplicationDidEnterBackground(isSuspendedUnderLock), m_pageID);
659 }
660
661 void WebPageProxy::applicationDidFinishSnapshottingAfterEnteringBackground()
662 {
663     if (m_drawingArea) {
664         m_drawingArea->prepareForAppSuspension();
665         m_drawingArea->hideContentUntilPendingUpdate();
666     }
667     m_process->send(Messages::WebPage::ApplicationDidFinishSnapshottingAfterEnteringBackground(), m_pageID);
668 }
669
670 void WebPageProxy::applicationWillEnterForeground()
671 {
672     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
673     m_process->send(Messages::WebPage::ApplicationWillEnterForeground(isSuspendedUnderLock), m_pageID);
674 }
675
676 void WebPageProxy::applicationWillResignActive()
677 {
678     m_process->send(Messages::WebPage::ApplicationWillResignActive(), m_pageID);
679 }
680
681 void WebPageProxy::applicationDidBecomeActive()
682 {
683 #if HAVE(AVKIT)
684     if (m_videoFullscreenManager)
685         m_videoFullscreenManager->applicationDidBecomeActive();
686 #endif
687     m_process->send(Messages::WebPage::ApplicationDidBecomeActive(), m_pageID);
688 }
689
690 void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
691 {
692     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
693 }
694
695 void WebPageProxy::selectWordBackward()
696 {
697     m_process->send(Messages::WebPage::SelectWordBackward(), m_pageID);
698 }
699
700 void WebPageProxy::requestRectsForGranularityWithSelectionOffset(WebCore::TextGranularity granularity, uint32_t offset, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
701 {
702     if (!isValid()) {
703         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
704         return;
705     }
706     
707     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
708     m_process->send(Messages::WebPage::GetRectsForGranularityWithSelectionOffset(static_cast<uint32_t>(granularity), offset, callbackID), m_pageID);
709 }
710
711 void WebPageProxy::requestRectsAtSelectionOffsetWithText(int32_t offset, const String& text, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
712 {
713     if (!isValid()) {
714         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
715         return;
716     }
717     
718     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
719     m_process->send(Messages::WebPage::GetRectsAtSelectionOffsetWithText(offset, text, callbackID), m_pageID);
720 }
721
722 void WebPageProxy::storeSelectionForAccessibility(bool shouldStore)
723 {
724     m_process->send(Messages::WebPage::StoreSelectionForAccessibility(shouldStore), m_pageID);
725 }
726
727 void WebPageProxy::startAutoscrollAtPosition(const WebCore::FloatPoint& positionInWindow)
728 {
729     m_process->send(Messages::WebPage::StartAutoscrollAtPosition(positionInWindow), m_pageID);
730 }
731     
732 void WebPageProxy::cancelAutoscroll()
733 {
734     m_process->send(Messages::WebPage::CancelAutoscroll(), m_pageID);
735 }
736
737 void WebPageProxy::moveSelectionByOffset(int32_t offset, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
738 {
739     if (!isValid()) {
740         callbackFunction(CallbackBase::Error::Unknown);
741         return;
742     }
743     
744     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
745     m_process->send(Messages::WebPage::MoveSelectionByOffset(offset, callbackID), m_pageID);
746 }
747
748 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
749 {
750     m_editorState = state;
751     handled = pageClient().interpretKeyEvent(m_keyEventQueue.first(), isCharEvent);
752 }
753
754 // Complex text input support for plug-ins.
755 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t, const String&)
756 {
757     notImplemented();
758 }
759
760 void WebPageProxy::setSmartInsertDeleteEnabled(bool)
761 {
762     notImplemented();
763 }
764
765 void WebPageProxy::registerWebProcessAccessibilityToken(const IPC::DataReference& data)
766 {
767     pageClient().accessibilityWebProcessTokenReceived(data);
768 }    
769
770 void WebPageProxy::assistiveTechnologyMakeFirstResponder()
771 {
772     notImplemented();
773 }
774     
775 void WebPageProxy::makeFirstResponder()
776 {
777     notImplemented();
778 }
779
780 void WebPageProxy::registerUIProcessAccessibilityTokens(const IPC::DataReference& elementToken, const IPC::DataReference& windowToken)
781 {
782     if (!isValid())
783         return;
784     
785     process().send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
786 }
787
788 void WebPageProxy::pluginFocusOrWindowFocusChanged(uint64_t, bool)
789 {
790     notImplemented();
791 }
792
793 void WebPageProxy::setPluginComplexTextInputState(uint64_t, uint64_t)
794 {
795     notImplemented();
796 }
797
798 void WebPageProxy::executeSavedCommandBySelector(const String&, bool&)
799 {
800     notImplemented();
801 }
802
803 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent&)
804 {
805     notImplemented();
806     return false;
807 }
808
809 bool WebPageProxy::acceptsFirstMouse(int, const WebKit::WebMouseEvent&)
810 {
811     notImplemented();
812     return false;
813 }
814
815 void WebPageProxy::willStartUserTriggeredZooming()
816 {
817     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
818 }
819
820 void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
821 {
822     hideValidationMessage();
823     process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID);
824 }
825
826 void WebPageProxy::commitPotentialTap(uint64_t layerTreeTransactionIdAtLastTouchStart)
827 {
828     process().send(Messages::WebPage::CommitPotentialTap(layerTreeTransactionIdAtLastTouchStart), m_pageID);
829 }
830
831 void WebPageProxy::cancelPotentialTap()
832 {
833     process().send(Messages::WebPage::CancelPotentialTap(), m_pageID);
834 }
835
836 void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
837 {
838     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
839 }
840
841 void WebPageProxy::handleTap(const FloatPoint& location, uint64_t layerTreeTransactionIdAtLastTouchStart)
842 {
843     process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), layerTreeTransactionIdAtLastTouchStart), m_pageID);
844 }
845
846 void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position)
847 {
848     process().send(Messages::WebPage::InspectorNodeSearchMovedToPosition(position), m_pageID);
849 }
850
851 void WebPageProxy::inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint& position)
852 {
853     process().send(Messages::WebPage::InspectorNodeSearchEndedAtPosition(position), m_pageID);
854 }
855
856 void WebPageProxy::blurAssistedNode()
857 {
858     process().send(Messages::WebPage::BlurAssistedNode(), m_pageID);
859 }
860
861 FloatSize WebPageProxy::screenSize()
862 {
863     return WebCore::screenSize();
864 }
865
866 FloatSize WebPageProxy::availableScreenSize()
867 {
868     return WebCore::availableScreenSize();
869 }
870
871 FloatSize WebPageProxy::overrideScreenSize()
872 {
873     return WebCore::overrideScreenSize();
874 }
875
876 float WebPageProxy::textAutosizingWidth()
877 {
878     return WebCore::screenSize().width();
879 }
880
881 void WebPageProxy::couldNotRestorePageState()
882 {
883     pageClient().couldNotRestorePageState();
884 }
885
886 void WebPageProxy::restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatBoxExtent& obscuredInsetsOnSave, double scale)
887 {
888     pageClient().restorePageState(scrollPosition, scrollOrigin, obscuredInsetsOnSave, scale);
889 }
890
891 void WebPageProxy::restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale)
892 {
893     pageClient().restorePageCenterAndScale(center, scale);
894 }
895
896 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)
897 {
898     pageClient().didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
899 }
900
901 void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData)
902 {
903     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
904     if (m_editorState.isMissingPostLayoutData) {
905         m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject });
906         return;
907     }
908
909     pageClient().startAssistingNode(information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject);
910 }
911
912 void WebPageProxy::stopAssistingNode()
913 {
914     m_deferredNodeAssistanceArguments = nullptr;
915     pageClient().stopAssistingNode();
916 }
917
918 void WebPageProxy::autofillLoginCredentials(const String& username, const String& password)
919 {
920     m_process->send(Messages::WebPage::AutofillLoginCredentials(username, password), m_pageID);
921 }
922
923 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
924 {
925     pageClient().showInspectorHighlight(highlight);
926 }
927
928 void WebPageProxy::hideInspectorHighlight()
929 {
930     pageClient().hideInspectorHighlight();
931 }
932
933 void WebPageProxy::showInspectorIndication()
934 {
935     pageClient().showInspectorIndication();
936 }
937
938 void WebPageProxy::hideInspectorIndication()
939 {
940     pageClient().hideInspectorIndication();
941 }
942
943 void WebPageProxy::enableInspectorNodeSearch()
944 {
945     pageClient().enableInspectorNodeSearch();
946 }
947
948 void WebPageProxy::disableInspectorNodeSearch()
949 {
950     pageClient().disableInspectorNodeSearch();
951 }
952
953 void WebPageProxy::focusNextAssistedNode(bool isForward, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
954 {
955     if (!isValid()) {
956         callbackFunction(CallbackBase::Error::Unknown);
957         return;
958     }
959     
960     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
961     process().send(Messages::WebPage::FocusNextAssistedNode(isForward, callbackID), m_pageID);
962 }
963
964 void WebPageProxy::setAssistedNodeValue(const String& value)
965 {
966     process().send(Messages::WebPage::SetAssistedNodeValue(value), m_pageID);
967 }
968
969 void WebPageProxy::setAssistedNodeValueAsNumber(double value)
970 {
971     process().send(Messages::WebPage::SetAssistedNodeValueAsNumber(value), m_pageID);
972 }
973
974 void WebPageProxy::setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
975 {
976     process().send(Messages::WebPage::SetAssistedNodeSelectedIndex(index, allowMultipleSelection), m_pageID);
977 }
978
979 void WebPageProxy::didPerformDictionaryLookup(const DictionaryPopupInfo&)
980 {
981     notImplemented();
982 }
983
984 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
985 {
986     notImplemented();
987 }
988
989 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
990 {
991     notImplemented();
992 }
993
994 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
995 {
996     notImplemented();
997 }
998
999 void WebPageProxy::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
1000 {
1001     pageClient().setRemoteLayerTreeRootNode(rootNode);
1002     m_frozenRemoteLayerTreeHost = nullptr;
1003 }
1004
1005 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
1006 {
1007     pageClient().showPlaybackTargetPicker(hasVideo, elementRect, policy, contextUID);
1008 }
1009
1010 void WebPageProxy::commitPotentialTapFailed()
1011 {
1012     pageClient().commitPotentialTapFailed();
1013 }
1014
1015 void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1016 {
1017     pageClient().didNotHandleTapAsClick(point);
1018     m_uiClient->didNotHandleTapAsClick(point);
1019 }
1020     
1021 void WebPageProxy::didCompleteSyntheticClick()
1022 {
1023     pageClient().didCompleteSyntheticClick();
1024 }
1025
1026 void WebPageProxy::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
1027 {
1028     pageClient().disableDoubleTapGesturesDuringTapIfNecessary(requestID);
1029 }
1030
1031 uint32_t WebPageProxy::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, DrawToPDFCallback::CallbackFunction&& callback)
1032 {
1033     if (!isValid()) {
1034         callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
1035         return 0;
1036     }
1037
1038     uint32_t pageCount = 0;
1039     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1040     using Message = Messages::WebPage::ComputePagesForPrintingAndDrawToPDF;
1041     process().sendSync(Message(frameID, printInfo, callbackID), Message::Reply(pageCount), m_pageID, Seconds::infinity());
1042     return pageCount;
1043 }
1044
1045 void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
1046 {
1047     auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
1048     RELEASE_ASSERT(callback);
1049     callback->performCallbackWithReturnValue(pdfData);
1050 }
1051
1052 void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
1053 {
1054     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
1055 }
1056
1057 void WebPageProxy::editorStateChanged(const EditorState& editorState)
1058 {
1059     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
1060     
1061     m_editorState = editorState;
1062     
1063     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
1064     if (couldChangeSecureInputState && !editorState.selectionIsNone)
1065         pageClient().updateSecureInputState();
1066     
1067     if (editorState.shouldIgnoreSelectionChanges)
1068         return;
1069     
1070     // We always need to notify the client on iOS to make sure the selection is redrawn,
1071     // even during composition to support phrase boundary gesture.
1072     pageClient().selectionDidChange();
1073     updateFontAttributesAfterEditorStateChange();
1074 }
1075
1076 void WebPageProxy::showValidationMessage(const IntRect& anchorClientRect, const String& message)
1077 {
1078     m_validationBubble = pageClient().createValidationBubble(message, { m_preferences->minimumFontSize() });
1079     m_validationBubble->setAnchorRect(anchorClientRect, uiClient().presentingViewController());
1080
1081     // If we are currently doing a scrolling / zoom animation, then we'll delay showing the validation
1082     // bubble until the animation is over.
1083     if (!m_isScrollingOrZooming)
1084         m_validationBubble->show();
1085 }
1086
1087 void WebPageProxy::setIsScrollingOrZooming(bool isScrollingOrZooming)
1088 {
1089     m_isScrollingOrZooming = isScrollingOrZooming;
1090
1091     // We finished doing the scrolling / zoom animation so we can now show the validation
1092     // bubble if we're supposed to.
1093     if (!m_isScrollingOrZooming && m_validationBubble)
1094         m_validationBubble->show();
1095 }
1096
1097 void WebPageProxy::hardwareKeyboardAvailabilityChanged()
1098 {
1099     updateCurrentModifierState();
1100     m_process->send(Messages::WebPage::HardwareKeyboardAvailabilityChanged(), m_pageID);
1101 }
1102
1103 #if ENABLE(DATA_INTERACTION)
1104
1105 void WebPageProxy::didHandleStartDataInteractionRequest(bool started)
1106 {
1107     pageClient().didHandleStartDataInteractionRequest(started);
1108 }
1109
1110 void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
1111 {
1112     pageClient().didHandleAdditionalDragItemsRequest(added);
1113 }
1114
1115 void WebPageProxy::requestStartDataInteraction(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition)
1116 {
1117     if (isValid())
1118         m_process->send(Messages::WebPage::RequestStartDataInteraction(clientPosition, globalPosition), m_pageID);
1119 }
1120
1121 void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
1122 {
1123     if (isValid())
1124         m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition), m_pageID);
1125 }
1126
1127 void WebPageProxy::didConcludeEditDataInteraction(std::optional<TextIndicatorData> data)
1128 {
1129     pageClient().didConcludeEditDataInteraction(data);
1130 }
1131
1132 #endif
1133
1134 #if USE(QUICK_LOOK)
1135     
1136 void WebPageProxy::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
1137 {
1138     // Ensure that fileName isn't really a path name
1139     static_assert(notFound + 1 == 0, "The following line assumes WTF::notFound equals -1");
1140     m_navigationClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
1141 }
1142
1143 void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
1144 {
1145     m_navigationClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
1146 }
1147
1148 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrame(const String& fileName)
1149 {
1150     pageClient().requestPasswordForQuickLookDocument(fileName, [protectedThis = makeRef(*this)](const String& password) {
1151         protectedThis->process().send(Messages::WebPage::DidReceivePasswordForQuickLookDocument(password), protectedThis->m_pageID);
1152     });
1153 }
1154
1155 #endif
1156
1157 } // namespace WebKit
1158
1159 #endif // PLATFORM(IOS_FAMILY)