Unreviewed, rolling out r242222.
[WebKit-https.git] / Source / WebKit / UIProcess / ios / WebPageProxyIOS.mm
1 /*
2  * Copyright (C) 2012-2019 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 "Connection.h"
33 #import "DataReference.h"
34 #import "EditingRange.h"
35 #import "GlobalFindInPageState.h"
36 #import "InteractionInformationAtPosition.h"
37 #import "Logging.h"
38 #import "NativeWebKeyboardEvent.h"
39 #import "NavigationState.h"
40 #import "PageClient.h"
41 #import "PrintInfo.h"
42 #import "RemoteLayerTreeDrawingAreaProxy.h"
43 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
44 #import "RemoteLayerTreeTransaction.h"
45 #import "UIKitSPI.h"
46 #import "UserData.h"
47 #import "VideoFullscreenManagerProxy.h"
48 #import "ViewUpdateDispatcherMessages.h"
49 #import "WKBrowsingContextControllerInternal.h"
50 #import "WebAutocorrectionContext.h"
51 #import "WebPageMessages.h"
52 #import "WebProcessPool.h"
53 #import "WebProcessProxy.h"
54 #import <WebCore/FrameView.h>
55 #import <WebCore/NotImplemented.h>
56 #import <WebCore/PlatformScreen.h>
57 #import <WebCore/SharedBuffer.h>
58 #import <WebCore/UserAgent.h>
59 #import <WebCore/ValidationBubble.h>
60 #import <wtf/text/TextStream.h>
61
62 #if USE(QUICK_LOOK)
63 #import "APILoaderClient.h"
64 #import "APINavigationClient.h"
65 #import <wtf/text/WTFString.h>
66 #endif
67
68 namespace WebKit {
69 using namespace WebCore;
70
71 void WebPageProxy::platformInitialize()
72 {
73 }
74
75 String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
76 {
77     return standardUserAgentWithApplicationName(applicationNameForUserAgent);
78 }
79
80 void WebPageProxy::getIsSpeaking(bool&)
81 {
82     notImplemented();
83 }
84
85 void WebPageProxy::speak(const String&)
86 {
87     notImplemented();
88 }
89
90 void WebPageProxy::stopSpeaking()
91 {
92     notImplemented();
93 }
94
95 void WebPageProxy::searchWithSpotlight(const String&)
96 {
97     notImplemented();
98 }
99
100 void WebPageProxy::searchTheWeb(const String&)
101 {
102     notImplemented();
103 }
104
105 void WebPageProxy::windowAndViewFramesChanged(const FloatRect&, const FloatPoint&)
106 {
107     notImplemented();
108 }
109
110 String WebPageProxy::stringSelectionForPasteboard()
111 {
112     notImplemented();
113     return String();
114 }
115
116 RefPtr<WebCore::SharedBuffer> WebPageProxy::dataSelectionForPasteboard(const String&)
117 {
118     notImplemented();
119     return nullptr;
120 }
121
122 bool WebPageProxy::readSelectionFromPasteboard(const String&)
123 {
124     notImplemented();
125     return false;
126 }
127
128 void WebPageProxy::gestureCallback(const WebCore::IntPoint& point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, CallbackID callbackID)
129 {
130     auto callback = m_callbacks.take<GestureCallback>(callbackID);
131     if (!callback) {
132         ASSERT_NOT_REACHED();
133         return;
134     }
135     
136     callback->performCallbackWithReturnValue(point, gestureType, gestureState, flags);
137 }
138
139 void WebPageProxy::touchesCallback(const WebCore::IntPoint& point, uint32_t touches, uint32_t flags, CallbackID callbackID)
140 {
141     auto callback = m_callbacks.take<TouchesCallback>(callbackID);
142     if (!callback) {
143         ASSERT_NOT_REACHED();
144         return;
145     }
146
147     callback->performCallbackWithReturnValue(point, touches, flags);
148 }
149
150 void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>& rects, const String& fontName, float fontSize, uint64_t fontTraits, CallbackID callbackID)
151 {
152     auto callback = m_callbacks.take<AutocorrectionDataCallback>(callbackID);
153     if (!callback) {
154         ASSERT_NOT_REACHED();
155         return;
156     }
157
158     callback->performCallbackWithReturnValue(rects, fontName, fontSize, fontTraits);
159 }
160
161 void WebPageProxy::selectionContextCallback(const String& selectedText, const String& beforeText, const String& afterText, CallbackID callbackID)
162 {
163     auto callback = m_callbacks.take<SelectionContextCallback>(callbackID);
164     if (!callback) {
165         ASSERT_NOT_REACHED();
166         return;
167     }
168
169     callback->performCallbackWithReturnValue(selectedText, beforeText, afterText);
170 }
171
172 void WebPageProxy::autocorrectionContextCallback(const WebAutocorrectionContext& context, CallbackID callbackID)
173 {
174     auto callback = m_callbacks.take<AutocorrectionContextCallback>(callbackID);
175     if (!callback) {
176         ASSERT_NOT_REACHED();
177         return;
178     }
179
180     callback->performCallbackWithReturnValue(context);
181 }
182
183 void WebPageProxy::selectionRectsCallback(const Vector<WebCore::SelectionRect>& selectionRects, CallbackID callbackID)
184 {
185     auto callback = m_callbacks.take<SelectionRectsCallback>(callbackID);
186     if (!callback) {
187         ASSERT_NOT_REACHED();
188         return;
189     }
190     
191     callback->performCallbackWithReturnValue(selectionRects);
192 }
193
194 void WebPageProxy::focusedElementInformationCallback(const FocusedElementInformation& info, CallbackID callbackID)
195 {
196     auto callback = m_callbacks.take<FocusedElementInformationCallback>(callbackID);
197     if (!callback) {
198         ASSERT_NOT_REACHED();
199         return;
200     }
201
202     callback->performCallbackWithReturnValue(info);
203 }
204
205 void WebPageProxy::requestFocusedElementInformation(Function<void(const FocusedElementInformation&, CallbackBase::Error)>&& callback)
206 {
207     if (!isValid()) {
208         callback({ }, CallbackBase::Error::OwnerWasInvalidated);
209         return;
210     }
211
212     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
213     m_process->send(Messages::WebPage::RequestFocusedElementInformation(callbackID), m_pageID);
214 }
215
216 void WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdate)
217 {
218     if (!isValid())
219         return;
220
221     if (visibleContentRectUpdate == m_lastVisibleContentRectUpdate)
222         return;
223
224     m_lastVisibleContentRectUpdate = visibleContentRectUpdate;
225     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdate), 0);
226 }
227
228 void WebPageProxy::resendLastVisibleContentRects()
229 {
230     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
231 }
232
233 void WebPageProxy::updateStringForFind(const String& string)
234 {
235     if (!isValid())
236         return;
237
238     WebKit::updateStringForFind(string);
239 }
240
241 static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
242 {
243     if (exposedRectEdge < documentEdge)
244         return documentEdge - factor * (documentEdge - exposedRectEdge);
245     
246     return exposedRectEdge;
247 }
248
249 static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
250 {
251     if (exposedRectEdge > documentEdge)
252         return documentEdge + factor * (exposedRectEdge - documentEdge);
253     
254     return exposedRectEdge;
255 }
256
257 // FIXME: rename this when visual viewports are the default.
258 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& unobscuredContentRectRespectingInputViewBounds, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, FrameView::LayoutViewportConstraint constraint) const
259 {
260     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
261     FloatRect documentRect = pageClient().documentRect();
262
263     if (constraint == FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect)
264         constrainedUnobscuredRect.intersect(documentRect);
265
266     double minimumScale = pageClient().minimumZoomScale();
267     bool isBelowMinimumScale = displayedContentScale < minimumScale;
268     if (isBelowMinimumScale) {
269         const CGFloat slope = 12;
270         CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
271             
272         constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
273         constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
274         constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
275         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
276     }
277
278     FloatSize constrainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
279     FloatRect unobscuredContentRectForViewport = isBelowMinimumScale ? constrainedUnobscuredRect : unobscuredContentRectRespectingInputViewBounds;
280
281     auto layoutViewportSize = FrameView::expandedLayoutViewportSize(m_baseLayoutViewportSize, LayoutSize(documentRect.size()), m_preferences->layoutViewportHeightExpansionFactor());
282     FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constrainedSize), LayoutRect(unobscuredContentRectForViewport), layoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
283     
284     if (layoutViewportRect != currentCustomFixedPositionRect)
285         LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
286     return layoutViewportRect;
287 }
288
289 void WebPageProxy::scrollingNodeScrollViewWillStartPanGesture()
290 {
291     pageClient().scrollingNodeScrollViewWillStartPanGesture();
292 }
293
294 void WebPageProxy::scrollingNodeScrollViewDidScroll()
295 {
296     pageClient().scrollingNodeScrollViewDidScroll();
297 }
298
299 void WebPageProxy::scrollingNodeScrollWillStartScroll()
300 {
301     pageClient().scrollingNodeScrollWillStartScroll();
302 }
303
304 void WebPageProxy::scrollingNodeScrollDidEndScroll()
305 {
306     pageClient().scrollingNodeScrollDidEndScroll();
307 }
308
309 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)
310 {
311     if (!isValid())
312         return;
313
314     hideValidationMessage();
315
316     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(viewLayoutSize,
317         maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect,
318         targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets,
319         targetScale, deviceOrientation, dynamicViewportSizeUpdateID), m_pageID);
320 }
321
322 void WebPageProxy::setViewportConfigurationViewLayoutSize(const WebCore::FloatSize& size, double scaleFactor, double minimumEffectiveDeviceWidth)
323 {
324     m_viewportConfigurationViewLayoutSize = size;
325     m_viewportConfigurationLayoutSizeScaleFactor = scaleFactor;
326
327     if (isValid())
328         m_process->send(Messages::WebPage::SetViewportConfigurationViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth), m_pageID);
329 }
330
331 void WebPageProxy::setForceAlwaysUserScalable(bool userScalable)
332 {
333     if (m_forceAlwaysUserScalable == userScalable)
334         return;
335     m_forceAlwaysUserScalable = userScalable;
336
337     if (isValid())
338         m_process->send(Messages::WebPage::SetForceAlwaysUserScalable(userScalable), m_pageID);
339 }
340
341 void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
342 {
343     m_maximumUnobscuredSize = size;
344
345     if (isValid())
346         m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
347 }
348
349 void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
350 {
351     if (deviceOrientation != m_deviceOrientation) {
352         m_deviceOrientation = deviceOrientation;
353         if (isValid())
354             m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
355     }
356 }
357
358 void WebPageProxy::setOverrideViewportArguments(const Optional<ViewportArguments>& viewportArguments)
359 {
360     if (isValid())
361         m_process->send(Messages::WebPage::SetOverrideViewportArguments(viewportArguments), m_pageID);
362 }
363
364 static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t committedSize)
365 {
366     const double thesholdSizeFraction = 0.5; // Empirically-derived.
367     return committedSize > thresholdSize * thesholdSizeFraction;
368 }
369
370 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
371 {
372     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
373
374     if (!m_hasReceivedLayerTreeTransactionAfterDidCommitLoad) {
375         if (layerTreeTransaction.transactionID() >= m_firstLayerTreeTransactionIdAfterDidCommitLoad) {
376             m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = true;
377             m_lastVisibleContentRectUpdate = VisibleContentRectUpdateInfo();
378         }
379     }
380
381     pageClient().didCommitLayerTree(layerTreeTransaction);
382
383     // FIXME: Remove this special mechanism and fold it into the transaction's layout milestones.
384     if (m_observedLayoutMilestones.contains(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold) && !m_hitRenderTreeSizeThreshold
385         && exceedsRenderTreeSizeSizeThreshold(m_sessionRestorationRenderTreeSize, layerTreeTransaction.renderTreeSize())) {
386         m_hitRenderTreeSizeThreshold = true;
387         didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
388     }
389
390     if (auto arguments = std::exchange(m_deferredElementDidFocusArguments, nullptr))
391         pageClient().elementDidFocus(arguments->information, arguments->userIsInteracting, arguments->blurPreviousNode, arguments->changingActivityState, arguments->userData.get());
392 }
393
394 bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
395 {
396     if (m_baseLayoutViewportSize == layerTreeTransaction.baseLayoutViewportSize()
397         && m_minStableLayoutViewportOrigin == layerTreeTransaction.minStableLayoutViewportOrigin()
398         && m_maxStableLayoutViewportOrigin == layerTreeTransaction.maxStableLayoutViewportOrigin())
399         return false;
400
401     m_baseLayoutViewportSize = layerTreeTransaction.baseLayoutViewportSize();
402     m_minStableLayoutViewportOrigin = layerTreeTransaction.minStableLayoutViewportOrigin();
403     m_maxStableLayoutViewportOrigin = layerTreeTransaction.maxStableLayoutViewportOrigin();
404
405     LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::updateLayoutViewportParameters: baseLayoutViewportSize: " << m_baseLayoutViewportSize << " minStableLayoutViewportOrigin: " << m_minStableLayoutViewportOrigin << " maxStableLayoutViewportOrigin: " << m_maxStableLayoutViewportOrigin);
406
407     return true;
408 }
409
410 void WebPageProxy::layerTreeCommitComplete()
411 {
412     pageClient().layerTreeCommitComplete();
413 }
414
415 void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithFocusedElement, WTF::Function<void(const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)>&& callbackFunction)
416 {
417     if (!isValid()) {
418         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
419         return;
420     }
421
422     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
423     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, isInteractingWithFocusedElement, callbackID), m_pageID);
424 }
425
426 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)
427 {
428     if (!isValid()) {
429         callbackFunction(WebCore::IntPoint(), 0, 0, CallbackBase::Error::Unknown);
430         return;
431     }
432
433     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
434     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
435 }
436     
437 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
438 {
439     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
440 }
441
442 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
443 {
444     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
445 }
446
447 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, WTF::Function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)>&& callbackFunction)
448 {
449     if (!isValid()) {
450         callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, CallbackBase::Error::Unknown);
451         return;
452     }
453
454     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
455     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
456 }
457
458 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
459 {
460     if (!isValid()) {
461         callbackFunction(String(), CallbackBase::Error::Unknown);
462         return;
463     }
464
465     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
466     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
467 }
468
469 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
470 {
471     bool autocorrectionApplied = false;
472     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
473     return autocorrectionApplied;
474 }
475
476 void WebPageProxy::selectTextWithGranularityAtPoint(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
477 {
478     if (!isValid()) {
479         callbackFunction(CallbackBase::Error::Unknown);
480         return;
481     }
482     
483     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
484     m_process->send(Messages::WebPage::SelectTextWithGranularityAtPoint(point, static_cast<uint32_t>(granularity), isInteractingWithFocusedElement, callbackID), m_pageID);
485 }
486
487 void WebPageProxy::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint point, WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
488 {
489     if (!isValid()) {
490         callbackFunction(CallbackBase::Error::Unknown);
491         return;
492     }
493     
494     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
495     m_process->send(Messages::WebPage::SelectPositionAtBoundaryWithDirection(point, static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), isInteractingWithFocusedElement, callbackID), m_pageID);
496 }
497
498 void WebPageProxy::moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
499 {
500     if (!isValid()) {
501         callbackFunction(CallbackBase::Error::Unknown);
502         return;
503     }
504     
505     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
506     m_process->send(Messages::WebPage::MoveSelectionAtBoundaryWithDirection(static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), callbackID), m_pageID);
507 }
508     
509 void WebPageProxy::selectPositionAtPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
510 {
511     if (!isValid()) {
512         callbackFunction(CallbackBase::Error::Unknown);
513         return;
514     }
515     
516     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
517     m_process->send(Messages::WebPage::SelectPositionAtPoint(point, isInteractingWithFocusedElement, callbackID), m_pageID);
518 }
519
520 void WebPageProxy::beginSelectionInDirection(WebCore::SelectionDirection direction, WTF::Function<void (uint64_t, CallbackBase::Error)>&& callbackFunction)
521 {
522     if (!isValid()) {
523         callbackFunction(0, CallbackBase::Error::Unknown);
524         return;
525     }
526     
527     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
528     m_process->send(Messages::WebPage::BeginSelectionInDirection(direction, callbackID), m_pageID);
529 }
530
531 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
532 {
533     if (!isValid()) {
534         callbackFunction(0, CallbackBase::Error::Unknown);
535         return;
536     }
537     
538     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
539     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithFocusedElement, callbackID), m_pageID);
540     
541 }
542
543 void WebPageProxy::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
544 {
545     if (!isValid()) {
546         callbackFunction(0, CallbackBase::Error::Unknown);
547         return;
548     }
549     
550     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
551     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPointAndBoundary(point, granularity, isInteractingWithFocusedElement, callbackID), m_pageID);
552     
553 }
554
555 void WebPageProxy::requestDictationContext(WTF::Function<void (const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
556 {
557     if (!isValid()) {
558         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
559         return;
560     }
561
562     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
563     m_process->send(Messages::WebPage::RequestDictationContext(callbackID), m_pageID);
564 }
565
566 void WebPageProxy::requestAutocorrectionContext(Function<void(const WebAutocorrectionContext&, CallbackBase::Error)>&& callback)
567 {
568     if (!isValid()) {
569         callback({ }, CallbackBase::Error::OwnerWasInvalidated);
570         return;
571     }
572
573     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
574     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
575 }
576
577 WebAutocorrectionContext WebPageProxy::autocorrectionContextSync()
578 {
579     WebAutocorrectionContext context;
580     m_process->sendSync(Messages::WebPage::AutocorrectionContextSync(), Messages::WebPage::AutocorrectionContextSync::Reply(context), m_pageID);
581     return context;
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, OptionSet<WebEvent::Modifier> modifiers, uint64_t requestID)
596 {
597     process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, modifiers, 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(OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart)
827 {
828     process().send(Messages::WebPage::CommitPotentialTap(modifiers, 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, OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart)
842 {
843     process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), modifiers, 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::blurFocusedElement()
857 {
858     process().send(Messages::WebPage::BlurFocusedElement(), 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(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(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, bool nodeHasBuiltInClickHandling)
897 {
898     pageClient().didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, nodeHasBuiltInClickHandling);
899 }
900
901 void WebPageProxy::elementDidFocus(const FocusedElementInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData)
902 {
903     m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = true;
904
905     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
906     if (m_editorState.isMissingPostLayoutData) {
907         // FIXME: We should try to eliminate m_deferredElementDidFocusArguments altogether, in favor of only deferring actions that are dependent on post-layout editor state information.
908         m_deferredElementDidFocusArguments = std::make_unique<ElementDidFocusArguments>(ElementDidFocusArguments { information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject });
909         return;
910     }
911
912     pageClient().elementDidFocus(information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject);
913 }
914
915 void WebPageProxy::elementDidBlur()
916 {
917     m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
918     m_deferredElementDidFocusArguments = nullptr;
919     pageClient().elementDidBlur();
920 }
921
922 void WebPageProxy::focusedElementDidChangeInputMode(WebCore::InputMode mode)
923 {
924     pageClient().focusedElementDidChangeInputMode(mode);
925 }
926
927 void WebPageProxy::autofillLoginCredentials(const String& username, const String& password)
928 {
929     m_process->send(Messages::WebPage::AutofillLoginCredentials(username, password), m_pageID);
930 }
931
932 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
933 {
934     pageClient().showInspectorHighlight(highlight);
935 }
936
937 void WebPageProxy::hideInspectorHighlight()
938 {
939     pageClient().hideInspectorHighlight();
940 }
941
942 void WebPageProxy::showInspectorIndication()
943 {
944     pageClient().showInspectorIndication();
945 }
946
947 void WebPageProxy::hideInspectorIndication()
948 {
949     pageClient().hideInspectorIndication();
950 }
951
952 void WebPageProxy::enableInspectorNodeSearch()
953 {
954     pageClient().enableInspectorNodeSearch();
955 }
956
957 void WebPageProxy::disableInspectorNodeSearch()
958 {
959     pageClient().disableInspectorNodeSearch();
960 }
961
962 void WebPageProxy::focusNextFocusedElement(bool isForward, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
963 {
964     if (!isValid()) {
965         callbackFunction(CallbackBase::Error::Unknown);
966         return;
967     }
968     
969     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
970     process().send(Messages::WebPage::FocusNextFocusedElement(isForward, callbackID), m_pageID);
971 }
972
973 void WebPageProxy::setFocusedElementValue(const String& value)
974 {
975     process().send(Messages::WebPage::SetFocusedElementValue(value), m_pageID);
976 }
977
978 void WebPageProxy::setFocusedElementValueAsNumber(double value)
979 {
980     process().send(Messages::WebPage::SetFocusedElementValueAsNumber(value), m_pageID);
981 }
982
983 void WebPageProxy::setFocusedElementSelectedIndex(uint32_t index, bool allowMultipleSelection)
984 {
985     process().send(Messages::WebPage::SetFocusedElementSelectedIndex(index, allowMultipleSelection), m_pageID);
986 }
987
988 void WebPageProxy::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
989 {
990     pageClient().didPerformDictionaryLookup(dictionaryPopupInfo);
991 }
992
993 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
994 {
995     notImplemented();
996 }
997
998 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
999 {
1000     notImplemented();
1001 }
1002
1003 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
1004 {
1005     notImplemented();
1006 }
1007
1008 void WebPageProxy::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
1009 {
1010     pageClient().setRemoteLayerTreeRootNode(rootNode);
1011     m_frozenRemoteLayerTreeHost = nullptr;
1012 }
1013
1014 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
1015 {
1016     pageClient().showPlaybackTargetPicker(hasVideo, elementRect, policy, contextUID);
1017 }
1018
1019 void WebPageProxy::commitPotentialTapFailed()
1020 {
1021     pageClient().commitPotentialTapFailed();
1022 }
1023
1024 void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1025 {
1026     pageClient().didNotHandleTapAsClick(point);
1027     m_uiClient->didNotHandleTapAsClick(point);
1028 }
1029     
1030 void WebPageProxy::didCompleteSyntheticClick()
1031 {
1032     pageClient().didCompleteSyntheticClick();
1033 }
1034
1035 void WebPageProxy::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
1036 {
1037     pageClient().disableDoubleTapGesturesDuringTapIfNecessary(requestID);
1038 }
1039
1040 uint32_t WebPageProxy::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, DrawToPDFCallback::CallbackFunction&& callback)
1041 {
1042     if (!isValid()) {
1043         callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
1044         return 0;
1045     }
1046
1047     uint32_t pageCount = 0;
1048     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1049     using Message = Messages::WebPage::ComputePagesForPrintingAndDrawToPDF;
1050     process().sendSync(Message(frameID, printInfo, callbackID), Message::Reply(pageCount), m_pageID, Seconds::infinity());
1051     return pageCount;
1052 }
1053
1054 void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
1055 {
1056     auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
1057     RELEASE_ASSERT(callback);
1058     callback->performCallbackWithReturnValue(pdfData);
1059 }
1060
1061 void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
1062 {
1063     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
1064 }
1065
1066 void WebPageProxy::editorStateChanged(const EditorState& editorState)
1067 {
1068     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
1069     
1070     m_editorState = editorState;
1071
1072     if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
1073         pageClient().didReceiveEditorStateUpdateAfterFocus();
1074         m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
1075     }
1076     
1077     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
1078     if (couldChangeSecureInputState && !editorState.selectionIsNone)
1079         pageClient().updateSecureInputState();
1080     
1081     if (editorState.shouldIgnoreSelectionChanges)
1082         return;
1083     
1084     // We always need to notify the client on iOS to make sure the selection is redrawn,
1085     // even during composition to support phrase boundary gesture.
1086     pageClient().selectionDidChange();
1087     updateFontAttributesAfterEditorStateChange();
1088 }
1089
1090 void WebPageProxy::showValidationMessage(const IntRect& anchorClientRect, const String& message)
1091 {
1092     m_validationBubble = pageClient().createValidationBubble(message, { m_preferences->minimumFontSize() });
1093     m_validationBubble->setAnchorRect(anchorClientRect, uiClient().presentingViewController());
1094
1095     // If we are currently doing a scrolling / zoom animation, then we'll delay showing the validation
1096     // bubble until the animation is over.
1097     if (!m_isScrollingOrZooming)
1098         m_validationBubble->show();
1099 }
1100
1101 void WebPageProxy::setIsScrollingOrZooming(bool isScrollingOrZooming)
1102 {
1103     m_isScrollingOrZooming = isScrollingOrZooming;
1104
1105     // We finished doing the scrolling / zoom animation so we can now show the validation
1106     // bubble if we're supposed to.
1107     if (!m_isScrollingOrZooming && m_validationBubble)
1108         m_validationBubble->show();
1109 }
1110
1111 void WebPageProxy::hardwareKeyboardAvailabilityChanged()
1112 {
1113     updateCurrentModifierState();
1114     m_process->send(Messages::WebPage::HardwareKeyboardAvailabilityChanged(), m_pageID);
1115 }
1116
1117 void WebPageProxy::requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&& callback)
1118 {
1119     if (!isValid()) {
1120         callback({ });
1121         return;
1122     }
1123
1124     m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestEvasionRectsAboveSelection(), WTFMove(callback), m_pageID);
1125 }
1126
1127 #if ENABLE(DATA_INTERACTION)
1128
1129 void WebPageProxy::didHandleDragStartRequest(bool started)
1130 {
1131     pageClient().didHandleDragStartRequest(started);
1132 }
1133
1134 void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
1135 {
1136     pageClient().didHandleAdditionalDragItemsRequest(added);
1137 }
1138
1139 void WebPageProxy::requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition)
1140 {
1141     if (isValid())
1142         m_process->send(Messages::WebPage::RequestDragStart(clientPosition, globalPosition), m_pageID);
1143 }
1144
1145 void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
1146 {
1147     if (isValid())
1148         m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition), m_pageID);
1149 }
1150
1151 void WebPageProxy::didConcludeEditDrag(Optional<TextIndicatorData> data)
1152 {
1153     pageClient().didConcludeEditDrag(data);
1154 }
1155
1156 #endif
1157
1158 #if USE(QUICK_LOOK)
1159     
1160 void WebPageProxy::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
1161 {
1162     // Ensure that fileName isn't really a path name
1163     static_assert(notFound + 1 == 0, "The following line assumes WTF::notFound equals -1");
1164     m_navigationClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
1165 }
1166
1167 void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
1168 {
1169     m_navigationClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
1170 }
1171
1172 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrame(const String& fileName)
1173 {
1174     didRequestPasswordForQuickLookDocumentInMainFrameShared(m_process.copyRef(), fileName);
1175 }
1176
1177 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrameShared(Ref<WebProcessProxy>&& process, const String& fileName)
1178 {
1179     pageClient().requestPasswordForQuickLookDocument(fileName, [process = WTFMove(process), pageID = m_pageID](const String& password) {
1180         process->send(Messages::WebPage::DidReceivePasswordForQuickLookDocument(password), pageID);
1181     });
1182 }
1183
1184 #endif
1185
1186 #if ENABLE(APPLE_PAY)
1187
1188 UIViewController *WebPageProxy::paymentCoordinatorPresentingViewController(const WebPaymentCoordinatorProxy&)
1189 {
1190     return uiClient().presentingViewController();
1191 }
1192
1193 const String& WebPageProxy::paymentCoordinatorCTDataConnectionServiceType(const WebPaymentCoordinatorProxy&)
1194 {
1195     return process().processPool().configuration().ctDataConnectionServiceType();
1196 }
1197
1198 #endif
1199
1200 } // namespace WebKit
1201
1202 #endif // PLATFORM(IOS_FAMILY)