WKWebView loses minimum layout size overrides that happen while the process is terminated
[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)
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 "PageClient.h"
38 #import "PrintInfo.h"
39 #import "RemoteLayerTreeDrawingAreaProxy.h"
40 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
41 #import "RemoteLayerTreeTransaction.h"
42 #import "UIKitSPI.h"
43 #import "UserData.h"
44 #import "VideoFullscreenManagerProxy.h"
45 #import "ViewUpdateDispatcherMessages.h"
46 #import "WKBrowsingContextControllerInternal.h"
47 #import "WebPageMessages.h"
48 #import "WebProcessProxy.h"
49 #import <WebCore/FrameView.h>
50 #import <WebCore/NotImplemented.h>
51 #import <WebCore/PlatformScreen.h>
52 #import <WebCore/SharedBuffer.h>
53 #import <WebCore/UserAgent.h>
54 #import <WebCore/ValidationBubble.h>
55 #import <wtf/text/TextStream.h>
56
57 #if USE(QUICK_LOOK)
58 #import "APILoaderClient.h"
59 #import "APINavigationClient.h"
60 #import <wtf/text/WTFString.h>
61 #endif
62
63 using namespace WebCore;
64
65 namespace WebKit {
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::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdate)
196 {
197     if (!isValid())
198         return;
199
200     if (visibleContentRectUpdate == m_lastVisibleContentRectUpdate)
201         return;
202
203     m_lastVisibleContentRectUpdate = visibleContentRectUpdate;
204     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdate), 0);
205 }
206
207 void WebPageProxy::resendLastVisibleContentRects()
208 {
209     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
210 }
211
212 static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
213 {
214     if (exposedRectEdge < documentEdge)
215         return documentEdge - factor * (documentEdge - exposedRectEdge);
216     
217     return exposedRectEdge;
218 }
219
220 static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
221 {
222     if (exposedRectEdge > documentEdge)
223         return documentEdge + factor * (exposedRectEdge - documentEdge);
224     
225     return exposedRectEdge;
226 }
227
228 // FIXME: rename this when visual viewports are the default.
229 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& unobscuredContentRectRespectingInputViewBounds, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, FrameView::LayoutViewportConstraint constraint, bool visualViewportEnabled) const
230 {
231     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
232     FloatRect documentRect = m_pageClient.documentRect();
233
234     if (!visualViewportEnabled && m_pageClient.isAssistingNode())
235         return documentRect;
236
237     if (constraint == FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect)
238         constrainedUnobscuredRect.intersect(documentRect);
239
240     double minimumScale = m_pageClient.minimumZoomScale();
241     bool isBelowMinimumScale = displayedContentScale < minimumScale;
242     if (isBelowMinimumScale) {
243         const CGFloat slope = 12;
244         CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
245             
246         constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
247         constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
248         constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
249         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
250     }
251
252     if (!visualViewportEnabled)
253         return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
254         
255     FloatSize constainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
256     FloatRect unobscuredContentRectForViewport = isBelowMinimumScale ? constrainedUnobscuredRect : unobscuredContentRectRespectingInputViewBounds;
257
258     FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constainedSize), LayoutRect(unobscuredContentRectForViewport), m_baseLayoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
259     
260     if (layoutViewportRect != currentCustomFixedPositionRect)
261         LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
262     return layoutViewportRect;
263 }
264
265 void WebPageProxy::overflowScrollViewWillStartPanGesture()
266 {
267     m_pageClient.overflowScrollViewWillStartPanGesture();
268 }
269
270 void WebPageProxy::overflowScrollViewDidScroll()
271 {
272     m_pageClient.overflowScrollViewDidScroll();
273 }
274
275 void WebPageProxy::overflowScrollWillStartScroll()
276 {
277     m_pageClient.overflowScrollWillStartScroll();
278 }
279
280 void WebPageProxy::overflowScrollDidEndScroll()
281 {
282     m_pageClient.overflowScrollDidEndScroll();
283 }
284
285 void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates, const WebCore::FloatBoxExtent& unobscuredSafeAreaInsets, double targetScale, int32_t deviceOrientation)
286 {
287     if (!isValid())
288         return;
289
290     hideValidationMessage();
291
292     m_dynamicViewportSizeUpdateWaitingForTarget = true;
293     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = true;
294     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect, targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets, targetScale, deviceOrientation, ++m_currentDynamicViewportSizeUpdateID), m_pageID);
295 }
296
297 void WebPageProxy::synchronizeDynamicViewportUpdate()
298 {
299     if (!isValid())
300         return;
301
302     if (m_dynamicViewportSizeUpdateWaitingForTarget) {
303         // We do not want the UIProcess to finish animated resize with the old content size, scale, etc.
304         // If that happens, the UIProcess would start pushing new VisibleContentRectUpdateInfo to the WebProcess with
305         // invalid informations.
306         //
307         // Ideally, the animated resize should just be transactional, and the UIProcess would remain in the "resize" state
308         // until both DynamicViewportUpdateChangedTarget and the associated commitLayerTree are finished.
309         // The tricky part with such implementation is if a second animated resize starts before the end of the previous one.
310         // In that case, the values used for the target state needs to be computed from the output of the previous animated resize.
311         //
312         // The following is a workaround to have the UIProcess in a consistent state.
313         // Instead of handling nested resize, we block the UIProcess until the animated resize finishes.
314         double newScale;
315         FloatPoint newScrollPosition;
316         uint64_t nextValidLayerTreeTransactionID;
317         if (m_process->sendSync(Messages::WebPage::SynchronizeDynamicViewportUpdate(), Messages::WebPage::SynchronizeDynamicViewportUpdate::Reply(newScale, newScrollPosition, nextValidLayerTreeTransactionID), m_pageID, 2_s)) {
318             m_dynamicViewportSizeUpdateWaitingForTarget = false;
319             m_dynamicViewportSizeUpdateLayerTreeTransactionID = nextValidLayerTreeTransactionID;
320             m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, nextValidLayerTreeTransactionID);
321         }
322
323     }
324
325     // If m_dynamicViewportSizeUpdateWaitingForTarget is false, we are waiting for the next valid frame with the hope it is the one for the new target.
326     // If m_dynamicViewportSizeUpdateWaitingForTarget is still true, this is a desperate attempt to get the valid frame before finishing the animation.
327     if (m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit)
328         m_drawingArea->waitForDidUpdateActivityState();
329
330     m_dynamicViewportSizeUpdateWaitingForTarget = false;
331     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
332 }
333
334 void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size)
335 {
336     m_viewportConfigurationMinimumLayoutSize = size;
337
338     if (isValid())
339         m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size), m_pageID);
340 }
341
342 void WebPageProxy::setForceAlwaysUserScalable(bool userScalable)
343 {
344     if (m_forceAlwaysUserScalable == userScalable)
345         return;
346     m_forceAlwaysUserScalable = userScalable;
347
348     if (isValid())
349         m_process->send(Messages::WebPage::SetForceAlwaysUserScalable(userScalable), m_pageID);
350 }
351
352 void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
353 {
354     m_maximumUnobscuredSize = size;
355
356     if (isValid())
357         m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
358 }
359
360 void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
361 {
362     if (deviceOrientation != m_deviceOrientation) {
363         m_deviceOrientation = deviceOrientation;
364         if (isValid())
365             m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
366     }
367 }
368
369 static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t committedSize)
370 {
371     const double thesholdSizeFraction = 0.5; // Empirically-derived.
372     return committedSize > thresholdSize * thesholdSizeFraction;
373 }
374
375 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
376 {
377     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
378
379     if (!m_hasReceivedLayerTreeTransactionAfterDidCommitLoad) {
380         if (layerTreeTransaction.transactionID() >= m_firstLayerTreeTransactionIdAfterDidCommitLoad) {
381             m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = true;
382             m_lastVisibleContentRectUpdate = VisibleContentRectUpdateInfo();
383         }
384     }
385
386     if (!m_dynamicViewportSizeUpdateWaitingForTarget && m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit) {
387         if (layerTreeTransaction.transactionID() >= m_dynamicViewportSizeUpdateLayerTreeTransactionID)
388             m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
389     }
390
391     m_pageClient.didCommitLayerTree(layerTreeTransaction);
392
393     // FIXME: Remove this special mechanism and fold it into the transaction's layout milestones.
394     if ((m_observedLayoutMilestones & WebCore::ReachedSessionRestorationRenderTreeSizeThreshold) && !m_hitRenderTreeSizeThreshold
395         && exceedsRenderTreeSizeSizeThreshold(m_sessionRestorationRenderTreeSize, layerTreeTransaction.renderTreeSize())) {
396         m_hitRenderTreeSizeThreshold = true;
397         didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
398     }
399
400     if (m_hasDeferredStartAssistingNode) {
401         m_pageClient.startAssistingNode(m_deferredNodeAssistanceArguments->m_nodeInformation, m_deferredNodeAssistanceArguments->m_userIsInteracting, m_deferredNodeAssistanceArguments->m_blurPreviousNode, m_deferredNodeAssistanceArguments->m_userData.get());
402         m_hasDeferredStartAssistingNode = false;
403         m_deferredNodeAssistanceArguments = nullptr;
404     }
405 }
406
407 bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
408 {
409     if (m_baseLayoutViewportSize == layerTreeTransaction.baseLayoutViewportSize()
410         && m_minStableLayoutViewportOrigin == layerTreeTransaction.minStableLayoutViewportOrigin()
411         && m_maxStableLayoutViewportOrigin == layerTreeTransaction.maxStableLayoutViewportOrigin())
412         return false;
413
414     m_baseLayoutViewportSize = layerTreeTransaction.baseLayoutViewportSize();
415     m_minStableLayoutViewportOrigin = layerTreeTransaction.minStableLayoutViewportOrigin();
416     m_maxStableLayoutViewportOrigin = layerTreeTransaction.maxStableLayoutViewportOrigin();
417
418     LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::updateLayoutViewportParameters: baseLayoutViewportSize: " << m_baseLayoutViewportSize << " minStableLayoutViewportOrigin: " << m_minStableLayoutViewportOrigin << " maxStableLayoutViewportOrigin: " << m_maxStableLayoutViewportOrigin);
419
420     return true;
421 }
422
423 void WebPageProxy::layerTreeCommitComplete()
424 {
425     m_pageClient.layerTreeCommitComplete();
426 }
427
428 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)
429 {
430     if (!isValid()) {
431         callbackFunction(WebCore::IntPoint(), 0, 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::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, isInteractingWithAssistedNode, callbackID), m_pageID);
437 }
438
439 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)
440 {
441     if (!isValid()) {
442         callbackFunction(WebCore::IntPoint(), 0, 0, CallbackBase::Error::Unknown);
443         return;
444     }
445
446     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
447     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
448 }
449     
450 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
451 {
452     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
453 }
454
455 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
456 {
457     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
458 }
459
460 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, WTF::Function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)>&& callbackFunction)
461 {
462     if (!isValid()) {
463         callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, 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::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
469 }
470
471 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
472 {
473     if (!isValid()) {
474         callbackFunction(String(), CallbackBase::Error::Unknown);
475         return;
476     }
477
478     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
479     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
480 }
481
482 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
483 {
484     bool autocorrectionApplied = false;
485     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
486     return autocorrectionApplied;
487 }
488
489 void WebPageProxy::selectTextWithGranularityAtPoint(const WebCore::IntPoint point, WebCore::TextGranularity granularity, 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::SelectTextWithGranularityAtPoint(point, static_cast<uint32_t>(granularity), isInteractingWithAssistedNode, callbackID), m_pageID);
498 }
499
500 void WebPageProxy::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint point, WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, bool isInteractingWithAssistedNode, 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::SelectPositionAtBoundaryWithDirection(point, static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), isInteractingWithAssistedNode, callbackID), m_pageID);
509 }
510
511 void WebPageProxy::moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, 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::MoveSelectionAtBoundaryWithDirection(static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), callbackID), m_pageID);
520 }
521     
522 void WebPageProxy::selectPositionAtPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
523 {
524     if (!isValid()) {
525         callbackFunction(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::SelectPositionAtPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
531 }
532
533 void WebPageProxy::beginSelectionInDirection(WebCore::SelectionDirection direction, 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::BeginSelectionInDirection(direction, callbackID), m_pageID);
542 }
543
544 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, WTF::Function<void (uint64_t, CallbackBase::Error)>&& callbackFunction)
545 {
546     if (!isValid()) {
547         callbackFunction(0, CallbackBase::Error::Unknown);
548         return;
549     }
550     
551     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
552     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
553     
554 }
555
556 void WebPageProxy::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithAssistedNode, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
557 {
558     if (!isValid()) {
559         callbackFunction(0, CallbackBase::Error::Unknown);
560         return;
561     }
562     
563     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
564     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPointAndBoundary(point, granularity, isInteractingWithAssistedNode, callbackID), m_pageID);
565     
566 }
567
568 void WebPageProxy::requestDictationContext(WTF::Function<void (const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
569 {
570     if (!isValid()) {
571         callbackFunction(String(), String(), String(), 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::RequestDictationContext(callbackID), m_pageID);
577 }
578
579 void WebPageProxy::requestAutocorrectionContext(WTF::Function<void (const String&, const String&, const String&, const String&, uint64_t, uint64_t, CallbackBase::Error)>&& callbackFunction)
580 {
581     if (!isValid()) {
582         callbackFunction(String(), String(), String(), String(), 0, 0, CallbackBase::Error::Unknown);
583         return;
584     }
585
586     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
587     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
588 }
589
590 void WebPageProxy::getAutocorrectionContext(String& beforeContext, String& markedText, String& selectedText, String& afterContext, uint64_t& location, uint64_t& length)
591 {
592     m_process->sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
593 }
594
595 void WebPageProxy::getSelectionContext(WTF::Function<void(const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
596 {
597     if (!isValid()) {
598         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
599         return;
600     }
601     
602     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
603     m_process->send(Messages::WebPage::GetSelectionContext(callbackID), m_pageID);
604 }
605
606 void WebPageProxy::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID)
607 {
608     process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, requestID), m_pageID);
609 }
610
611 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)
612 {
613     if (!isValid()) {
614         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
615         return;
616     }
617
618     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
619     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
620 }
621
622 void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition& info)
623 {
624     m_pageClient.positionInformationDidChange(info);
625 }
626
627 void WebPageProxy::requestPositionInformation(const InteractionInformationRequest& request)
628 {
629     m_process->send(Messages::WebPage::RequestPositionInformation(request), m_pageID);
630 }
631
632 void WebPageProxy::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)
633 {
634     m_process->send(Messages::WebPage::StartInteractionWithElementAtPosition(point), m_pageID);
635 }
636
637 void WebPageProxy::stopInteraction()
638 {
639     m_process->send(Messages::WebPage::StopInteraction(), m_pageID);
640 }
641
642 void WebPageProxy::performActionOnElement(uint32_t action)
643 {
644     m_process->send(Messages::WebPage::PerformActionOnElement(action), m_pageID);
645 }
646
647 void WebPageProxy::saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize)
648 {
649     auto sharedMemoryBuffer = SharedMemory::map(imageHandle, SharedMemory::Protection::ReadOnly);
650     auto buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
651     m_pageClient.saveImageToLibrary(WTFMove(buffer));
652 }
653
654 void WebPageProxy::applicationDidEnterBackground()
655 {
656     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
657     m_process->send(Messages::WebPage::ApplicationDidEnterBackground(isSuspendedUnderLock), m_pageID);
658 }
659
660 void WebPageProxy::applicationDidFinishSnapshottingAfterEnteringBackground()
661 {
662     if (m_drawingArea)
663         m_drawingArea->prepareForAppSuspension();
664     m_process->send(Messages::WebPage::ApplicationDidFinishSnapshottingAfterEnteringBackground(), m_pageID);
665 }
666
667 void WebPageProxy::applicationWillEnterForeground()
668 {
669     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
670     m_process->send(Messages::WebPage::ApplicationWillEnterForeground(isSuspendedUnderLock), m_pageID);
671 }
672
673 void WebPageProxy::applicationWillResignActive()
674 {
675     m_process->send(Messages::WebPage::ApplicationWillResignActive(), m_pageID);
676 }
677
678 void WebPageProxy::applicationDidBecomeActive()
679 {
680 #if HAVE(AVKIT)
681     if (m_videoFullscreenManager)
682         m_videoFullscreenManager->applicationDidBecomeActive();
683 #endif
684     m_process->send(Messages::WebPage::ApplicationDidBecomeActive(), m_pageID);
685 }
686
687 void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
688 {
689     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
690 }
691
692 void WebPageProxy::selectWordBackward()
693 {
694     m_process->send(Messages::WebPage::SelectWordBackward(), m_pageID);
695 }
696
697 void WebPageProxy::requestRectsForGranularityWithSelectionOffset(WebCore::TextGranularity granularity, uint32_t offset, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
698 {
699     if (!isValid()) {
700         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
701         return;
702     }
703     
704     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
705     m_process->send(Messages::WebPage::GetRectsForGranularityWithSelectionOffset(static_cast<uint32_t>(granularity), offset, callbackID), m_pageID);
706 }
707
708 void WebPageProxy::requestRectsAtSelectionOffsetWithText(int32_t offset, const String& text, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
709 {
710     if (!isValid()) {
711         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
712         return;
713     }
714     
715     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
716     m_process->send(Messages::WebPage::GetRectsAtSelectionOffsetWithText(offset, text, callbackID), m_pageID);
717 }
718
719 void WebPageProxy::storeSelectionForAccessibility(bool shouldStore)
720 {
721     m_process->send(Messages::WebPage::StoreSelectionForAccessibility(shouldStore), m_pageID);
722 }
723
724 void WebPageProxy::startAutoscrollAtPosition(const WebCore::FloatPoint& position)
725 {
726     m_process->send(Messages::WebPage::StartAutoscrollAtPosition(position), m_pageID);
727 }
728     
729 void WebPageProxy::cancelAutoscroll()
730 {
731     m_process->send(Messages::WebPage::CancelAutoscroll(), m_pageID);
732 }
733
734 void WebPageProxy::moveSelectionByOffset(int32_t offset, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
735 {
736     if (!isValid()) {
737         callbackFunction(CallbackBase::Error::Unknown);
738         return;
739     }
740     
741     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
742     m_process->send(Messages::WebPage::MoveSelectionByOffset(offset, callbackID), m_pageID);
743 }
744
745 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
746 {
747     m_editorState = state;
748     handled = m_pageClient.interpretKeyEvent(m_keyEventQueue.first(), isCharEvent);
749 }
750
751 // Complex text input support for plug-ins.
752 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t, const String&)
753 {
754     notImplemented();
755 }
756
757 void WebPageProxy::setSmartInsertDeleteEnabled(bool)
758 {
759     notImplemented();
760 }
761
762 void WebPageProxy::registerWebProcessAccessibilityToken(const IPC::DataReference& data)
763 {
764     m_pageClient.accessibilityWebProcessTokenReceived(data);
765 }    
766
767 void WebPageProxy::makeFirstResponder()
768 {
769     notImplemented();
770 }
771
772 void WebPageProxy::registerUIProcessAccessibilityTokens(const IPC::DataReference& elementToken, const IPC::DataReference& windowToken)
773 {
774     if (!isValid())
775         return;
776     
777     process().send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
778 }
779
780 void WebPageProxy::pluginFocusOrWindowFocusChanged(uint64_t, bool)
781 {
782     notImplemented();
783 }
784
785 void WebPageProxy::setPluginComplexTextInputState(uint64_t, uint64_t)
786 {
787     notImplemented();
788 }
789
790 void WebPageProxy::executeSavedCommandBySelector(const String&, bool&)
791 {
792     notImplemented();
793 }
794
795 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent&)
796 {
797     notImplemented();
798     return false;
799 }
800
801 bool WebPageProxy::acceptsFirstMouse(int, const WebKit::WebMouseEvent&)
802 {
803     notImplemented();
804     return false;
805 }
806
807 void WebPageProxy::willStartUserTriggeredZooming()
808 {
809     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
810 }
811
812 void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
813 {
814     hideValidationMessage();
815     process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID);
816 }
817
818 void WebPageProxy::commitPotentialTap(uint64_t layerTreeTransactionIdAtLastTouchStart)
819 {
820     process().send(Messages::WebPage::CommitPotentialTap(layerTreeTransactionIdAtLastTouchStart), m_pageID);
821 }
822
823 void WebPageProxy::cancelPotentialTap()
824 {
825     process().send(Messages::WebPage::CancelPotentialTap(), m_pageID);
826 }
827
828 void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
829 {
830     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
831 }
832
833 void WebPageProxy::handleTap(const FloatPoint& location, uint64_t layerTreeTransactionIdAtLastTouchStart)
834 {
835     process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), layerTreeTransactionIdAtLastTouchStart), m_pageID);
836 }
837
838 void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position)
839 {
840     process().send(Messages::WebPage::InspectorNodeSearchMovedToPosition(position), m_pageID);
841 }
842
843 void WebPageProxy::inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint& position)
844 {
845     process().send(Messages::WebPage::InspectorNodeSearchEndedAtPosition(position), m_pageID);
846 }
847
848 void WebPageProxy::blurAssistedNode()
849 {
850     process().send(Messages::WebPage::BlurAssistedNode(), m_pageID);
851 }
852
853 FloatSize WebPageProxy::screenSize()
854 {
855     return WebCore::screenSize();
856 }
857
858 FloatSize WebPageProxy::availableScreenSize()
859 {
860     return WebCore::availableScreenSize();
861 }
862     
863 float WebPageProxy::textAutosizingWidth()
864 {
865     return WebCore::screenSize().width();
866 }
867
868 void WebPageProxy::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t dynamicViewportSizeUpdateID)
869 {
870     if (dynamicViewportSizeUpdateID != m_currentDynamicViewportSizeUpdateID)
871         return;
872
873     if (m_dynamicViewportSizeUpdateWaitingForTarget) {
874         m_dynamicViewportSizeUpdateLayerTreeTransactionID = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
875         m_dynamicViewportSizeUpdateWaitingForTarget = false;
876         m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, m_dynamicViewportSizeUpdateLayerTreeTransactionID);
877     }
878 }
879
880 void WebPageProxy::couldNotRestorePageState()
881 {
882     m_pageClient.couldNotRestorePageState();
883 }
884
885 void WebPageProxy::restorePageState(std::optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatBoxExtent& obscuredInsetsOnSave, double scale)
886 {
887     m_pageClient.restorePageState(scrollPosition, scrollOrigin, obscuredInsetsOnSave, scale);
888 }
889
890 void WebPageProxy::restorePageCenterAndScale(std::optional<WebCore::FloatPoint> center, double scale)
891 {
892     m_pageClient.restorePageCenterAndScale(center, scale);
893 }
894
895 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)
896 {
897     m_pageClient.didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
898 }
899
900 void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, const UserData& userData)
901 {
902     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
903     if (m_editorState.isMissingPostLayoutData) {
904         m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, userDataObject });
905         m_hasDeferredStartAssistingNode = true;
906         return;
907     }
908
909     m_pageClient.startAssistingNode(information, userIsInteracting, blurPreviousNode, userDataObject);
910 }
911
912 void WebPageProxy::stopAssistingNode()
913 {
914     if (m_hasDeferredStartAssistingNode) {
915         m_hasDeferredStartAssistingNode = false;
916         m_deferredNodeAssistanceArguments = nullptr;
917     }
918     m_pageClient.stopAssistingNode();
919 }
920
921 void WebPageProxy::autofillLoginCredentials(const String& username, const String& password)
922 {
923     m_process->send(Messages::WebPage::AutofillLoginCredentials(username, password), m_pageID);
924 }
925
926 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
927 {
928     m_pageClient.showInspectorHighlight(highlight);
929 }
930
931 void WebPageProxy::hideInspectorHighlight()
932 {
933     m_pageClient.hideInspectorHighlight();
934 }
935
936 void WebPageProxy::showInspectorIndication()
937 {
938     m_pageClient.showInspectorIndication();
939 }
940
941 void WebPageProxy::hideInspectorIndication()
942 {
943     m_pageClient.hideInspectorIndication();
944 }
945
946 void WebPageProxy::enableInspectorNodeSearch()
947 {
948     m_pageClient.enableInspectorNodeSearch();
949 }
950
951 void WebPageProxy::disableInspectorNodeSearch()
952 {
953     m_pageClient.disableInspectorNodeSearch();
954 }
955
956 void WebPageProxy::focusNextAssistedNode(bool isForward, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
957 {
958     if (!isValid()) {
959         callbackFunction(CallbackBase::Error::Unknown);
960         return;
961     }
962     
963     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
964     process().send(Messages::WebPage::FocusNextAssistedNode(isForward, callbackID), m_pageID);
965 }
966
967 void WebPageProxy::setAssistedNodeValue(const String& value)
968 {
969     process().send(Messages::WebPage::SetAssistedNodeValue(value), m_pageID);
970 }
971
972 void WebPageProxy::setAssistedNodeValueAsNumber(double value)
973 {
974     process().send(Messages::WebPage::SetAssistedNodeValueAsNumber(value), m_pageID);
975 }
976
977 void WebPageProxy::setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
978 {
979     process().send(Messages::WebPage::SetAssistedNodeSelectedIndex(index, allowMultipleSelection), m_pageID);
980 }
981
982 void WebPageProxy::didPerformDictionaryLookup(const DictionaryPopupInfo&)
983 {
984     notImplemented();
985 }
986
987 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
988 {
989     notImplemented();
990 }
991
992 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
993 {
994     notImplemented();
995 }
996
997 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
998 {
999     notImplemented();
1000 }
1001
1002 void WebPageProxy::setAcceleratedCompositingRootLayer(LayerOrView* rootLayer)
1003 {
1004     m_pageClient.setAcceleratedCompositingRootLayer(rootLayer);
1005 }
1006
1007 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
1008 {
1009     m_pageClient.showPlaybackTargetPicker(hasVideo, elementRect);
1010 }
1011
1012 void WebPageProxy::commitPotentialTapFailed()
1013 {
1014     m_pageClient.commitPotentialTapFailed();
1015 }
1016
1017 void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1018 {
1019     m_pageClient.didNotHandleTapAsClick(point);
1020     m_uiClient->didNotHandleTapAsClick(point);
1021 }
1022     
1023 void WebPageProxy::didCompleteSyntheticClick()
1024 {
1025     m_pageClient.didCompleteSyntheticClick();
1026 }
1027
1028 void WebPageProxy::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
1029 {
1030     m_pageClient.disableDoubleTapGesturesDuringTapIfNecessary(requestID);
1031 }
1032
1033 uint32_t WebPageProxy::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, DrawToPDFCallback::CallbackFunction&& callback)
1034 {
1035     if (!isValid()) {
1036         callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
1037         return 0;
1038     }
1039
1040     uint32_t pageCount = 0;
1041     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1042     using Message = Messages::WebPage::ComputePagesForPrintingAndDrawToPDF;
1043     process().sendSync(Message(frameID, printInfo, callbackID), Message::Reply(pageCount), m_pageID);
1044     return pageCount;
1045 }
1046
1047 void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
1048 {
1049     auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
1050     RELEASE_ASSERT(callback);
1051     callback->performCallbackWithReturnValue(pdfData);
1052 }
1053
1054 void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
1055 {
1056     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
1057 }
1058
1059 void WebPageProxy::editorStateChanged(const EditorState& editorState)
1060 {
1061     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
1062     
1063     m_editorState = editorState;
1064     
1065     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
1066     if (couldChangeSecureInputState && !editorState.selectionIsNone)
1067         m_pageClient.updateSecureInputState();
1068     
1069     if (editorState.shouldIgnoreSelectionChanges)
1070         return;
1071     
1072     // We always need to notify the client on iOS to make sure the selection is redrawn,
1073     // even during composition to support phrase boundary gesture.
1074     m_pageClient.selectionDidChange();
1075 }
1076
1077 void WebPageProxy::showValidationMessage(const IntRect& anchorClientRect, const String& message)
1078 {
1079     m_validationBubble = m_pageClient.createValidationBubble(message, { m_preferences->minimumFontSize() });
1080     m_validationBubble->setAnchorRect(anchorClientRect, uiClient().presentingViewController());
1081
1082     // If we are currently doing a scrolling / zoom animation, then we'll delay showing the validation
1083     // bubble until the animation is over.
1084     if (!m_isScrollingOrZooming)
1085         m_validationBubble->show();
1086 }
1087
1088 void WebPageProxy::setIsScrollingOrZooming(bool isScrollingOrZooming)
1089 {
1090     m_isScrollingOrZooming = isScrollingOrZooming;
1091
1092     // We finished doing the scrolling / zoom animation so we can now show the validation
1093     // bubble if we're supposed to.
1094     if (!m_isScrollingOrZooming && m_validationBubble)
1095         m_validationBubble->show();
1096 }
1097
1098 #if ENABLE(DATA_INTERACTION)
1099
1100 void WebPageProxy::didPerformDataInteractionControllerOperation(bool handled)
1101 {
1102     m_pageClient.didPerformDataInteractionControllerOperation(handled);
1103 }
1104
1105 void WebPageProxy::didHandleStartDataInteractionRequest(bool started)
1106 {
1107     m_pageClient.didHandleStartDataInteractionRequest(started);
1108 }
1109
1110 void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
1111 {
1112     m_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     m_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     if (m_navigationClient)
1141         m_navigationClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
1142     else
1143         m_loaderClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
1144 }
1145
1146 void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
1147 {
1148     if (m_navigationClient)
1149         m_navigationClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
1150     else
1151         m_loaderClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
1152 }
1153
1154 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrame(const String& fileName)
1155 {
1156     m_pageClient.requestPasswordForQuickLookDocument(fileName, [protectedThis = makeRef(*this)](const String& password) {
1157         protectedThis->process().send(Messages::WebPage::DidReceivePasswordForQuickLookDocument(password), protectedThis->m_pageID);
1158     });
1159 }
1160
1161 #endif
1162
1163 } // namespace WebKit
1164
1165 #endif // PLATFORM(IOS)