[Apple Pay] Use PKPaymentAuthorizationController to present the Apple Pay UI remotely...
[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 "PaymentAuthorizationViewController.h"
42 #import "PrintInfo.h"
43 #import "RemoteLayerTreeDrawingAreaProxy.h"
44 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
45 #import "RemoteLayerTreeTransaction.h"
46 #import "UIKitSPI.h"
47 #import "UserData.h"
48 #import "VideoFullscreenManagerProxy.h"
49 #import "ViewUpdateDispatcherMessages.h"
50 #import "WKBrowsingContextControllerInternal.h"
51 #import "WebAutocorrectionContext.h"
52 #import "WebPageMessages.h"
53 #import "WebProcessPool.h"
54 #import "WebProcessProxy.h"
55 #import <WebCore/FrameView.h>
56 #import <WebCore/NotImplemented.h>
57 #import <WebCore/PlatformScreen.h>
58 #import <WebCore/SharedBuffer.h>
59 #import <WebCore/UserAgent.h>
60 #import <WebCore/ValidationBubble.h>
61 #import <wtf/text/TextStream.h>
62
63 #if USE(QUICK_LOOK)
64 #import "APILoaderClient.h"
65 #import "APINavigationClient.h"
66 #import <wtf/text/WTFString.h>
67 #endif
68
69 namespace WebKit {
70 using namespace WebCore;
71
72 void WebPageProxy::platformInitialize()
73 {
74 }
75
76 String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
77 {
78     return standardUserAgentWithApplicationName(applicationNameForUserAgent);
79 }
80
81 void WebPageProxy::getIsSpeaking(bool&)
82 {
83     notImplemented();
84 }
85
86 void WebPageProxy::speak(const String&)
87 {
88     notImplemented();
89 }
90
91 void WebPageProxy::stopSpeaking()
92 {
93     notImplemented();
94 }
95
96 void WebPageProxy::searchWithSpotlight(const String&)
97 {
98     notImplemented();
99 }
100
101 void WebPageProxy::searchTheWeb(const String&)
102 {
103     notImplemented();
104 }
105
106 void WebPageProxy::windowAndViewFramesChanged(const FloatRect&, const FloatPoint&)
107 {
108     notImplemented();
109 }
110
111 String WebPageProxy::stringSelectionForPasteboard()
112 {
113     notImplemented();
114     return String();
115 }
116
117 RefPtr<WebCore::SharedBuffer> WebPageProxy::dataSelectionForPasteboard(const String&)
118 {
119     notImplemented();
120     return nullptr;
121 }
122
123 bool WebPageProxy::readSelectionFromPasteboard(const String&)
124 {
125     notImplemented();
126     return false;
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 WebAutocorrectionContext& context, 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(context);
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::focusedElementInformationCallback(const FocusedElementInformation& info, CallbackID callbackID)
196 {
197     auto callback = m_callbacks.take<FocusedElementInformationCallback>(callbackID);
198     if (!callback) {
199         ASSERT_NOT_REACHED();
200         return;
201     }
202
203     callback->performCallbackWithReturnValue(info);
204 }
205
206 void WebPageProxy::requestFocusedElementInformation(Function<void(const FocusedElementInformation&, CallbackBase::Error)>&& callback)
207 {
208     if (!isValid()) {
209         callback({ }, CallbackBase::Error::OwnerWasInvalidated);
210         return;
211     }
212
213     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
214     m_process->send(Messages::WebPage::RequestFocusedElementInformation(callbackID), m_pageID);
215 }
216
217 void WebPageProxy::updateVisibleContentRects(const VisibleContentRectUpdateInfo& visibleContentRectUpdate)
218 {
219     if (!isValid())
220         return;
221
222     if (visibleContentRectUpdate == m_lastVisibleContentRectUpdate)
223         return;
224
225     m_lastVisibleContentRectUpdate = visibleContentRectUpdate;
226     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdate), 0);
227 }
228
229 void WebPageProxy::resendLastVisibleContentRects()
230 {
231     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
232 }
233
234 void WebPageProxy::updateStringForFind(const String& string)
235 {
236     if (!isValid())
237         return;
238
239     WebKit::updateStringForFind(string);
240 }
241
242 static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
243 {
244     if (exposedRectEdge < documentEdge)
245         return documentEdge - factor * (documentEdge - exposedRectEdge);
246     
247     return exposedRectEdge;
248 }
249
250 static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
251 {
252     if (exposedRectEdge > documentEdge)
253         return documentEdge + factor * (exposedRectEdge - documentEdge);
254     
255     return exposedRectEdge;
256 }
257
258 // FIXME: rename this when visual viewports are the default.
259 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& unobscuredContentRectRespectingInputViewBounds, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, FrameView::LayoutViewportConstraint constraint) const
260 {
261     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
262     FloatRect documentRect = pageClient().documentRect();
263
264     if (constraint == FrameView::LayoutViewportConstraint::ConstrainedToDocumentRect)
265         constrainedUnobscuredRect.intersect(documentRect);
266
267     double minimumScale = pageClient().minimumZoomScale();
268     bool isBelowMinimumScale = displayedContentScale < minimumScale;
269     if (isBelowMinimumScale) {
270         const CGFloat slope = 12;
271         CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
272             
273         constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
274         constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
275         constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
276         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
277     }
278
279     FloatSize constrainedSize = isBelowMinimumScale ? constrainedUnobscuredRect.size() : unobscuredContentRect.size();
280     FloatRect unobscuredContentRectForViewport = isBelowMinimumScale ? constrainedUnobscuredRect : unobscuredContentRectRespectingInputViewBounds;
281
282     auto layoutViewportSize = FrameView::expandedLayoutViewportSize(m_baseLayoutViewportSize, LayoutSize(documentRect.size()), m_preferences->layoutViewportHeightExpansionFactor());
283     FloatRect layoutViewportRect = FrameView::computeUpdatedLayoutViewportRect(LayoutRect(currentCustomFixedPositionRect), LayoutRect(documentRect), LayoutSize(constrainedSize), LayoutRect(unobscuredContentRectForViewport), layoutViewportSize, m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, constraint);
284     
285     if (layoutViewportRect != currentCustomFixedPositionRect)
286         LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
287     return layoutViewportRect;
288 }
289
290 void WebPageProxy::scrollingNodeScrollViewWillStartPanGesture()
291 {
292     pageClient().scrollingNodeScrollViewWillStartPanGesture();
293 }
294
295 void WebPageProxy::scrollingNodeScrollViewDidScroll()
296 {
297     pageClient().scrollingNodeScrollViewDidScroll();
298 }
299
300 void WebPageProxy::scrollingNodeScrollWillStartScroll()
301 {
302     pageClient().scrollingNodeScrollWillStartScroll();
303 }
304
305 void WebPageProxy::scrollingNodeScrollDidEndScroll()
306 {
307     pageClient().scrollingNodeScrollDidEndScroll();
308 }
309
310 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)
311 {
312     if (!isValid())
313         return;
314
315     hideValidationMessage();
316
317     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(viewLayoutSize,
318         maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect,
319         targetUnobscuredRectInScrollViewCoordinates, unobscuredSafeAreaInsets,
320         targetScale, deviceOrientation, dynamicViewportSizeUpdateID), m_pageID);
321 }
322
323 void WebPageProxy::setViewportConfigurationViewLayoutSize(const WebCore::FloatSize& size, double scaleFactor, double minimumEffectiveDeviceWidth)
324 {
325     m_viewportConfigurationViewLayoutSize = size;
326     m_viewportConfigurationLayoutSizeScaleFactor = scaleFactor;
327
328     if (isValid())
329         m_process->send(Messages::WebPage::SetViewportConfigurationViewLayoutSize(size, scaleFactor, minimumEffectiveDeviceWidth), m_pageID);
330 }
331
332 void WebPageProxy::setForceAlwaysUserScalable(bool userScalable)
333 {
334     if (m_forceAlwaysUserScalable == userScalable)
335         return;
336     m_forceAlwaysUserScalable = userScalable;
337
338     if (isValid())
339         m_process->send(Messages::WebPage::SetForceAlwaysUserScalable(userScalable), m_pageID);
340 }
341
342 void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
343 {
344     m_maximumUnobscuredSize = size;
345
346     if (isValid())
347         m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
348 }
349
350 void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
351 {
352     if (deviceOrientation != m_deviceOrientation) {
353         m_deviceOrientation = deviceOrientation;
354         if (isValid())
355             m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
356     }
357 }
358
359 void WebPageProxy::setOverrideViewportArguments(const Optional<ViewportArguments>& viewportArguments)
360 {
361     if (isValid())
362         m_process->send(Messages::WebPage::SetOverrideViewportArguments(viewportArguments), m_pageID);
363 }
364
365 static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t committedSize)
366 {
367     const double thesholdSizeFraction = 0.5; // Empirically-derived.
368     return committedSize > thresholdSize * thesholdSizeFraction;
369 }
370
371 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
372 {
373     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
374
375     if (!m_hasReceivedLayerTreeTransactionAfterDidCommitLoad) {
376         if (layerTreeTransaction.transactionID() >= m_firstLayerTreeTransactionIdAfterDidCommitLoad) {
377             m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = true;
378             m_lastVisibleContentRectUpdate = VisibleContentRectUpdateInfo();
379         }
380     }
381
382     pageClient().didCommitLayerTree(layerTreeTransaction);
383
384     // FIXME: Remove this special mechanism and fold it into the transaction's layout milestones.
385     if (m_observedLayoutMilestones.contains(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold) && !m_hitRenderTreeSizeThreshold
386         && exceedsRenderTreeSizeSizeThreshold(m_sessionRestorationRenderTreeSize, layerTreeTransaction.renderTreeSize())) {
387         m_hitRenderTreeSizeThreshold = true;
388         didReachLayoutMilestone(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
389     }
390
391     if (auto arguments = std::exchange(m_deferredElementDidFocusArguments, nullptr))
392         pageClient().elementDidFocus(arguments->information, arguments->userIsInteracting, arguments->blurPreviousNode, arguments->changingActivityState, arguments->userData.get());
393 }
394
395 bool WebPageProxy::updateLayoutViewportParameters(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
396 {
397     if (m_baseLayoutViewportSize == layerTreeTransaction.baseLayoutViewportSize()
398         && m_minStableLayoutViewportOrigin == layerTreeTransaction.minStableLayoutViewportOrigin()
399         && m_maxStableLayoutViewportOrigin == layerTreeTransaction.maxStableLayoutViewportOrigin())
400         return false;
401
402     m_baseLayoutViewportSize = layerTreeTransaction.baseLayoutViewportSize();
403     m_minStableLayoutViewportOrigin = layerTreeTransaction.minStableLayoutViewportOrigin();
404     m_maxStableLayoutViewportOrigin = layerTreeTransaction.maxStableLayoutViewportOrigin();
405
406     LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::updateLayoutViewportParameters: baseLayoutViewportSize: " << m_baseLayoutViewportSize << " minStableLayoutViewportOrigin: " << m_minStableLayoutViewportOrigin << " maxStableLayoutViewportOrigin: " << m_maxStableLayoutViewportOrigin);
407
408     return true;
409 }
410
411 void WebPageProxy::layerTreeCommitComplete()
412 {
413     pageClient().layerTreeCommitComplete();
414 }
415
416 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)
417 {
418     if (!isValid()) {
419         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
420         return;
421     }
422
423     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
424     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, isInteractingWithFocusedElement, callbackID), m_pageID);
425 }
426
427 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)
428 {
429     if (!isValid()) {
430         callbackFunction(WebCore::IntPoint(), 0, 0, CallbackBase::Error::Unknown);
431         return;
432     }
433
434     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
435     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
436 }
437     
438 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
439 {
440     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
441 }
442
443 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
444 {
445     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
446 }
447
448 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, WTF::Function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)>&& callbackFunction)
449 {
450     if (!isValid()) {
451         callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, CallbackBase::Error::Unknown);
452         return;
453     }
454
455     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
456     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
457 }
458
459 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, WTF::Function<void (const String&, CallbackBase::Error)>&& callbackFunction)
460 {
461     if (!isValid()) {
462         callbackFunction(String(), CallbackBase::Error::Unknown);
463         return;
464     }
465
466     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
467     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
468 }
469
470 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
471 {
472     bool autocorrectionApplied = false;
473     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
474     return autocorrectionApplied;
475 }
476
477 void WebPageProxy::selectTextWithGranularityAtPoint(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
478 {
479     if (!isValid()) {
480         callbackFunction(CallbackBase::Error::Unknown);
481         return;
482     }
483     
484     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
485     m_process->send(Messages::WebPage::SelectTextWithGranularityAtPoint(point, static_cast<uint32_t>(granularity), isInteractingWithFocusedElement, callbackID), m_pageID);
486 }
487
488 void WebPageProxy::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint point, WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
489 {
490     if (!isValid()) {
491         callbackFunction(CallbackBase::Error::Unknown);
492         return;
493     }
494     
495     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
496     m_process->send(Messages::WebPage::SelectPositionAtBoundaryWithDirection(point, static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), isInteractingWithFocusedElement, callbackID), m_pageID);
497 }
498
499 void WebPageProxy::moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
500 {
501     if (!isValid()) {
502         callbackFunction(CallbackBase::Error::Unknown);
503         return;
504     }
505     
506     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
507     m_process->send(Messages::WebPage::MoveSelectionAtBoundaryWithDirection(static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), callbackID), m_pageID);
508 }
509     
510 void WebPageProxy::selectPositionAtPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
511 {
512     if (!isValid()) {
513         callbackFunction(CallbackBase::Error::Unknown);
514         return;
515     }
516     
517     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
518     m_process->send(Messages::WebPage::SelectPositionAtPoint(point, isInteractingWithFocusedElement, callbackID), m_pageID);
519 }
520
521 void WebPageProxy::beginSelectionInDirection(WebCore::SelectionDirection direction, WTF::Function<void (uint64_t, CallbackBase::Error)>&& callbackFunction)
522 {
523     if (!isValid()) {
524         callbackFunction(0, CallbackBase::Error::Unknown);
525         return;
526     }
527     
528     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
529     m_process->send(Messages::WebPage::BeginSelectionInDirection(direction, callbackID), m_pageID);
530 }
531
532 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithFocusedElement, WTF::Function<void(uint64_t, CallbackBase::Error)>&& callbackFunction)
533 {
534     if (!isValid()) {
535         callbackFunction(0, CallbackBase::Error::Unknown);
536         return;
537     }
538     
539     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
540     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithFocusedElement, callbackID), m_pageID);
541     
542 }
543
544 void WebPageProxy::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithFocusedElement, 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::UpdateSelectionWithExtentPointAndBoundary(point, granularity, isInteractingWithFocusedElement, callbackID), m_pageID);
553     
554 }
555
556 void WebPageProxy::requestDictationContext(WTF::Function<void (const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
557 {
558     if (!isValid()) {
559         callbackFunction(String(), String(), String(), 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::RequestDictationContext(callbackID), m_pageID);
565 }
566
567 void WebPageProxy::requestAutocorrectionContext()
568 {
569     m_process->send(Messages::WebPage::RequestAutocorrectionContext(), m_pageID);
570 }
571
572 void WebPageProxy::handleAutocorrectionContext(const WebAutocorrectionContext& context)
573 {
574     pageClient().handleAutocorrectionContext(context);
575 }
576
577 void WebPageProxy::getSelectionContext(WTF::Function<void(const String&, const String&, const String&, CallbackBase::Error)>&& callbackFunction)
578 {
579     if (!isValid()) {
580         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
581         return;
582     }
583     
584     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
585     m_process->send(Messages::WebPage::GetSelectionContext(callbackID), m_pageID);
586 }
587
588 void WebPageProxy::handleTwoFingerTapAtPoint(const WebCore::IntPoint& point, OptionSet<WebEvent::Modifier> modifiers, uint64_t requestID)
589 {
590     process().send(Messages::WebPage::HandleTwoFingerTapAtPoint(point, modifiers, requestID), m_pageID);
591 }
592
593 void WebPageProxy::handleStylusSingleTapAtPoint(const WebCore::IntPoint& point, uint64_t requestID)
594 {
595     process().send(Messages::WebPage::HandleStylusSingleTapAtPoint(point, requestID), m_pageID);
596 }
597
598 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)
599 {
600     if (!isValid()) {
601         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
602         return;
603     }
604
605     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
606     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
607 }
608
609 void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition& info)
610 {
611     pageClient().positionInformationDidChange(info);
612 }
613
614 void WebPageProxy::requestPositionInformation(const InteractionInformationRequest& request)
615 {
616     m_process->send(Messages::WebPage::RequestPositionInformation(request), m_pageID);
617 }
618
619 void WebPageProxy::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)
620 {
621     m_process->send(Messages::WebPage::StartInteractionWithElementAtPosition(point), m_pageID);
622 }
623
624 void WebPageProxy::stopInteraction()
625 {
626     m_process->send(Messages::WebPage::StopInteraction(), m_pageID);
627 }
628
629 void WebPageProxy::performActionOnElement(uint32_t action)
630 {
631     m_process->send(Messages::WebPage::PerformActionOnElement(action), m_pageID);
632 }
633
634 void WebPageProxy::saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize)
635 {
636     auto sharedMemoryBuffer = SharedMemory::map(imageHandle, SharedMemory::Protection::ReadOnly);
637     auto buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
638     pageClient().saveImageToLibrary(WTFMove(buffer));
639 }
640
641 void WebPageProxy::applicationDidEnterBackground()
642 {
643     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
644
645 #if !PLATFORM(WATCHOS)
646     // We normally delay process suspension when the app is backgrounded until the current page load completes. However,
647     // we do not want to do so when the screen is locked for power reasons.
648     if (isSuspendedUnderLock)
649         NavigationState::fromWebPage(*this).releaseNetworkActivityToken(NavigationState::NetworkActivityTokenReleaseReason::ScreenLocked);
650 #endif
651     m_process->send(Messages::WebPage::ApplicationDidEnterBackground(isSuspendedUnderLock), m_pageID);
652 }
653
654 void WebPageProxy::applicationDidFinishSnapshottingAfterEnteringBackground()
655 {
656     if (m_drawingArea) {
657         m_drawingArea->prepareForAppSuspension();
658         m_drawingArea->hideContentUntilPendingUpdate();
659     }
660     m_process->send(Messages::WebPage::ApplicationDidFinishSnapshottingAfterEnteringBackground(), m_pageID);
661 }
662
663 void WebPageProxy::applicationWillEnterForeground()
664 {
665     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
666     m_process->send(Messages::WebPage::ApplicationWillEnterForeground(isSuspendedUnderLock), m_pageID);
667     m_process->setKeyboardIsAttached([UIKeyboard isInHardwareKeyboardMode]);
668     m_process->send(Messages::WebPage::HardwareKeyboardAvailabilityChanged(m_process->keyboardIsAttached()), m_pageID);
669 }
670
671 void WebPageProxy::applicationWillResignActive()
672 {
673     m_process->send(Messages::WebPage::ApplicationWillResignActive(), m_pageID);
674 }
675
676 void WebPageProxy::applicationDidBecomeActive()
677 {
678 #if HAVE(AVKIT)
679     if (m_videoFullscreenManager)
680         m_videoFullscreenManager->applicationDidBecomeActive();
681 #endif
682     m_process->send(Messages::WebPage::ApplicationDidBecomeActive(), m_pageID);
683 }
684
685 void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
686 {
687     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
688 }
689
690 void WebPageProxy::selectWordBackward()
691 {
692     m_process->send(Messages::WebPage::SelectWordBackward(), m_pageID);
693 }
694
695 void WebPageProxy::requestRectsForGranularityWithSelectionOffset(WebCore::TextGranularity granularity, uint32_t offset, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
696 {
697     if (!isValid()) {
698         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
699         return;
700     }
701     
702     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
703     m_process->send(Messages::WebPage::GetRectsForGranularityWithSelectionOffset(static_cast<uint32_t>(granularity), offset, callbackID), m_pageID);
704 }
705
706 void WebPageProxy::requestRectsAtSelectionOffsetWithText(int32_t offset, const String& text, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&& callbackFunction)
707 {
708     if (!isValid()) {
709         callbackFunction(Vector<WebCore::SelectionRect>(), CallbackBase::Error::Unknown);
710         return;
711     }
712     
713     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
714     m_process->send(Messages::WebPage::GetRectsAtSelectionOffsetWithText(offset, text, callbackID), m_pageID);
715 }
716
717 void WebPageProxy::storeSelectionForAccessibility(bool shouldStore)
718 {
719     m_process->send(Messages::WebPage::StoreSelectionForAccessibility(shouldStore), m_pageID);
720 }
721
722 void WebPageProxy::startAutoscrollAtPosition(const WebCore::FloatPoint& positionInWindow)
723 {
724     m_process->send(Messages::WebPage::StartAutoscrollAtPosition(positionInWindow), m_pageID);
725 }
726     
727 void WebPageProxy::cancelAutoscroll()
728 {
729     m_process->send(Messages::WebPage::CancelAutoscroll(), m_pageID);
730 }
731
732 void WebPageProxy::moveSelectionByOffset(int32_t offset, WTF::Function<void (CallbackBase::Error)>&& callbackFunction)
733 {
734     if (!isValid()) {
735         callbackFunction(CallbackBase::Error::Unknown);
736         return;
737     }
738     
739     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
740     m_process->send(Messages::WebPage::MoveSelectionByOffset(offset, callbackID), m_pageID);
741 }
742
743 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
744 {
745     m_editorState = state;
746     handled = pageClient().interpretKeyEvent(m_keyEventQueue.first(), isCharEvent);
747 }
748
749 // Complex text input support for plug-ins.
750 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t, const String&)
751 {
752     notImplemented();
753 }
754
755 void WebPageProxy::setSmartInsertDeleteEnabled(bool)
756 {
757     notImplemented();
758 }
759
760 void WebPageProxy::registerWebProcessAccessibilityToken(const IPC::DataReference& data)
761 {
762     pageClient().accessibilityWebProcessTokenReceived(data);
763 }    
764
765 void WebPageProxy::assistiveTechnologyMakeFirstResponder()
766 {
767     notImplemented();
768 }
769     
770 void WebPageProxy::makeFirstResponder()
771 {
772     notImplemented();
773 }
774
775 void WebPageProxy::registerUIProcessAccessibilityTokens(const IPC::DataReference& elementToken, const IPC::DataReference& windowToken)
776 {
777     if (!isValid())
778         return;
779     
780     process().send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
781 }
782
783 void WebPageProxy::pluginFocusOrWindowFocusChanged(uint64_t, bool)
784 {
785     notImplemented();
786 }
787
788 void WebPageProxy::setPluginComplexTextInputState(uint64_t, uint64_t)
789 {
790     notImplemented();
791 }
792
793 void WebPageProxy::executeSavedCommandBySelector(const String&, bool&)
794 {
795     notImplemented();
796 }
797
798 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent&)
799 {
800     notImplemented();
801     return false;
802 }
803
804 bool WebPageProxy::acceptsFirstMouse(int, const WebKit::WebMouseEvent&)
805 {
806     notImplemented();
807     return false;
808 }
809
810 void WebPageProxy::willStartUserTriggeredZooming()
811 {
812     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
813 }
814
815 void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
816 {
817     hideValidationMessage();
818     process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID);
819 }
820
821 void WebPageProxy::commitPotentialTap(OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart)
822 {
823     process().send(Messages::WebPage::CommitPotentialTap(modifiers, layerTreeTransactionIdAtLastTouchStart), m_pageID);
824 }
825
826 void WebPageProxy::cancelPotentialTap()
827 {
828     process().send(Messages::WebPage::CancelPotentialTap(), m_pageID);
829 }
830
831 void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
832 {
833     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
834 }
835
836 void WebPageProxy::handleTap(const FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers, uint64_t layerTreeTransactionIdAtLastTouchStart)
837 {
838     process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), modifiers, layerTreeTransactionIdAtLastTouchStart), m_pageID);
839 }
840
841 void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position)
842 {
843     process().send(Messages::WebPage::InspectorNodeSearchMovedToPosition(position), m_pageID);
844 }
845
846 void WebPageProxy::inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint& position)
847 {
848     process().send(Messages::WebPage::InspectorNodeSearchEndedAtPosition(position), m_pageID);
849 }
850
851 void WebPageProxy::blurFocusedElement()
852 {
853     process().send(Messages::WebPage::BlurFocusedElement(), m_pageID);
854 }
855
856 FloatSize WebPageProxy::screenSize()
857 {
858     return WebCore::screenSize();
859 }
860
861 FloatSize WebPageProxy::availableScreenSize()
862 {
863     return WebCore::availableScreenSize();
864 }
865
866 FloatSize WebPageProxy::overrideScreenSize()
867 {
868     return WebCore::overrideScreenSize();
869 }
870
871 float WebPageProxy::textAutosizingWidth()
872 {
873     return WebCore::screenSize().width();
874 }
875
876 void WebPageProxy::couldNotRestorePageState()
877 {
878     pageClient().couldNotRestorePageState();
879 }
880
881 void WebPageProxy::restorePageState(Optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatBoxExtent& obscuredInsetsOnSave, double scale)
882 {
883     pageClient().restorePageState(scrollPosition, scrollOrigin, obscuredInsetsOnSave, scale);
884 }
885
886 void WebPageProxy::restorePageCenterAndScale(Optional<WebCore::FloatPoint> center, double scale)
887 {
888     pageClient().restorePageCenterAndScale(center, scale);
889 }
890
891 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)
892 {
893     pageClient().didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, nodeHasBuiltInClickHandling);
894 }
895
896 void WebPageProxy::elementDidFocus(const FocusedElementInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData)
897 {
898     m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = true;
899
900     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
901     if (m_editorState.isMissingPostLayoutData) {
902         // FIXME: We should try to eliminate m_deferredElementDidFocusArguments altogether, in favor of only deferring actions that are dependent on post-layout editor state information.
903         m_deferredElementDidFocusArguments = std::make_unique<ElementDidFocusArguments>(ElementDidFocusArguments { information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject });
904         return;
905     }
906
907     pageClient().elementDidFocus(information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject);
908 }
909
910 void WebPageProxy::elementDidBlur()
911 {
912     m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
913     m_deferredElementDidFocusArguments = nullptr;
914     pageClient().elementDidBlur();
915 }
916
917 void WebPageProxy::focusedElementDidChangeInputMode(WebCore::InputMode mode)
918 {
919     pageClient().focusedElementDidChangeInputMode(mode);
920 }
921
922 void WebPageProxy::autofillLoginCredentials(const String& username, const String& password)
923 {
924     m_process->send(Messages::WebPage::AutofillLoginCredentials(username, password), m_pageID);
925 }
926
927 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
928 {
929     pageClient().showInspectorHighlight(highlight);
930 }
931
932 void WebPageProxy::hideInspectorHighlight()
933 {
934     pageClient().hideInspectorHighlight();
935 }
936
937 void WebPageProxy::showInspectorIndication()
938 {
939     pageClient().showInspectorIndication();
940 }
941
942 void WebPageProxy::hideInspectorIndication()
943 {
944     pageClient().hideInspectorIndication();
945 }
946
947 void WebPageProxy::enableInspectorNodeSearch()
948 {
949     pageClient().enableInspectorNodeSearch();
950 }
951
952 void WebPageProxy::disableInspectorNodeSearch()
953 {
954     pageClient().disableInspectorNodeSearch();
955 }
956
957 void WebPageProxy::focusNextFocusedElement(bool isForward, WTF::Function<void(CallbackBase::Error)>&& callbackFunction)
958 {
959     if (!isValid()) {
960         callbackFunction(CallbackBase::Error::Unknown);
961         return;
962     }
963     
964     auto callbackID = m_callbacks.put(WTFMove(callbackFunction), m_process->throttler().backgroundActivityToken());
965     process().send(Messages::WebPage::FocusNextFocusedElement(isForward, callbackID), m_pageID);
966 }
967
968 void WebPageProxy::setFocusedElementValue(const String& value)
969 {
970     process().send(Messages::WebPage::SetFocusedElementValue(value), m_pageID);
971 }
972
973 void WebPageProxy::setFocusedElementValueAsNumber(double value)
974 {
975     process().send(Messages::WebPage::SetFocusedElementValueAsNumber(value), m_pageID);
976 }
977
978 void WebPageProxy::setFocusedElementSelectedIndex(uint32_t index, bool allowMultipleSelection)
979 {
980     process().send(Messages::WebPage::SetFocusedElementSelectedIndex(index, allowMultipleSelection), m_pageID);
981 }
982
983 void WebPageProxy::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
984 {
985     pageClient().didPerformDictionaryLookup(dictionaryPopupInfo);
986 }
987
988 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
989 {
990     notImplemented();
991 }
992
993 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
994 {
995     notImplemented();
996 }
997
998 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
999 {
1000     notImplemented();
1001 }
1002
1003 void WebPageProxy::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
1004 {
1005     pageClient().setRemoteLayerTreeRootNode(rootNode);
1006     m_frozenRemoteLayerTreeHost = nullptr;
1007 }
1008
1009 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
1010 {
1011     pageClient().showPlaybackTargetPicker(hasVideo, elementRect, policy, contextUID);
1012 }
1013
1014 void WebPageProxy::commitPotentialTapFailed()
1015 {
1016     pageClient().commitPotentialTapFailed();
1017 }
1018
1019 void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
1020 {
1021     pageClient().didNotHandleTapAsClick(point);
1022     m_uiClient->didNotHandleTapAsClick(point);
1023 }
1024     
1025 void WebPageProxy::didCompleteSyntheticClick()
1026 {
1027     pageClient().didCompleteSyntheticClick();
1028 }
1029
1030 void WebPageProxy::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
1031 {
1032     pageClient().disableDoubleTapGesturesDuringTapIfNecessary(requestID);
1033 }
1034
1035 uint32_t WebPageProxy::computePagesForPrintingAndDrawToPDF(uint64_t frameID, const PrintInfo& printInfo, DrawToPDFCallback::CallbackFunction&& callback)
1036 {
1037     if (!isValid()) {
1038         callback(IPC::DataReference(), CallbackBase::Error::OwnerWasInvalidated);
1039         return 0;
1040     }
1041
1042     uint32_t pageCount = 0;
1043     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
1044     using Message = Messages::WebPage::ComputePagesForPrintingAndDrawToPDF;
1045     process().sendSync(Message(frameID, printInfo, callbackID), Message::Reply(pageCount), m_pageID, Seconds::infinity());
1046     return pageCount;
1047 }
1048
1049 void WebPageProxy::drawToPDFCallback(const IPC::DataReference& pdfData, CallbackID callbackID)
1050 {
1051     auto callback = m_callbacks.take<DrawToPDFCallback>(callbackID);
1052     RELEASE_ASSERT(callback);
1053     callback->performCallbackWithReturnValue(pdfData);
1054 }
1055
1056 void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
1057 {
1058     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
1059 }
1060
1061 void WebPageProxy::editorStateChanged(const EditorState& editorState)
1062 {
1063     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
1064     
1065     m_editorState = editorState;
1066
1067     if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
1068         pageClient().didReceiveEditorStateUpdateAfterFocus();
1069         m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
1070     }
1071     
1072     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
1073     if (couldChangeSecureInputState && !editorState.selectionIsNone)
1074         pageClient().updateSecureInputState();
1075     
1076     if (editorState.shouldIgnoreSelectionChanges)
1077         return;
1078     
1079     // We always need to notify the client on iOS to make sure the selection is redrawn,
1080     // even during composition to support phrase boundary gesture.
1081     pageClient().selectionDidChange();
1082     updateFontAttributesAfterEditorStateChange();
1083 }
1084
1085 void WebPageProxy::showValidationMessage(const IntRect& anchorClientRect, const String& message)
1086 {
1087     m_validationBubble = pageClient().createValidationBubble(message, { m_preferences->minimumFontSize() });
1088     m_validationBubble->setAnchorRect(anchorClientRect, uiClient().presentingViewController());
1089
1090     // If we are currently doing a scrolling / zoom animation, then we'll delay showing the validation
1091     // bubble until the animation is over.
1092     if (!m_isScrollingOrZooming)
1093         m_validationBubble->show();
1094 }
1095
1096 void WebPageProxy::setIsScrollingOrZooming(bool isScrollingOrZooming)
1097 {
1098     m_isScrollingOrZooming = isScrollingOrZooming;
1099
1100     // We finished doing the scrolling / zoom animation so we can now show the validation
1101     // bubble if we're supposed to.
1102     if (!m_isScrollingOrZooming && m_validationBubble)
1103         m_validationBubble->show();
1104 }
1105
1106 void WebPageProxy::hardwareKeyboardAvailabilityChanged(bool keyboardIsAttached)
1107 {
1108     updateCurrentModifierState();
1109     m_process->send(Messages::WebPage::HardwareKeyboardAvailabilityChanged(keyboardIsAttached), m_pageID);
1110 }
1111
1112 void WebPageProxy::requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&& callback)
1113 {
1114     if (!isValid()) {
1115         callback({ });
1116         return;
1117     }
1118
1119     m_process->connection()->sendWithAsyncReply(Messages::WebPage::RequestEvasionRectsAboveSelection(), WTFMove(callback), m_pageID);
1120 }
1121
1122 #if ENABLE(DATA_INTERACTION)
1123
1124 void WebPageProxy::didHandleDragStartRequest(bool started)
1125 {
1126     pageClient().didHandleDragStartRequest(started);
1127 }
1128
1129 void WebPageProxy::didHandleAdditionalDragItemsRequest(bool added)
1130 {
1131     pageClient().didHandleAdditionalDragItemsRequest(added);
1132 }
1133
1134 void WebPageProxy::requestDragStart(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition)
1135 {
1136     if (isValid())
1137         m_process->send(Messages::WebPage::RequestDragStart(clientPosition, globalPosition), m_pageID);
1138 }
1139
1140 void WebPageProxy::requestAdditionalItemsForDragSession(const IntPoint& clientPosition, const IntPoint& globalPosition)
1141 {
1142     if (isValid())
1143         m_process->send(Messages::WebPage::RequestAdditionalItemsForDragSession(clientPosition, globalPosition), m_pageID);
1144 }
1145
1146 void WebPageProxy::didConcludeEditDrag(Optional<TextIndicatorData> data)
1147 {
1148     pageClient().didConcludeEditDrag(data);
1149 }
1150
1151 #endif
1152
1153 #if USE(QUICK_LOOK)
1154     
1155 void WebPageProxy::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
1156 {
1157     // Ensure that fileName isn't really a path name
1158     static_assert(notFound + 1 == 0, "The following line assumes WTF::notFound equals -1");
1159     m_navigationClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
1160 }
1161
1162 void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
1163 {
1164     m_navigationClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
1165 }
1166
1167 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrame(const String& fileName)
1168 {
1169     didRequestPasswordForQuickLookDocumentInMainFrameShared(m_process.copyRef(), fileName);
1170 }
1171
1172 void WebPageProxy::didRequestPasswordForQuickLookDocumentInMainFrameShared(Ref<WebProcessProxy>&& process, const String& fileName)
1173 {
1174     pageClient().requestPasswordForQuickLookDocument(fileName, [process = WTFMove(process), pageID = m_pageID](const String& password) {
1175         process->send(Messages::WebPage::DidReceivePasswordForQuickLookDocument(password), pageID);
1176     });
1177 }
1178
1179 #endif
1180
1181 #if ENABLE(APPLE_PAY)
1182
1183 std::unique_ptr<PaymentAuthorizationPresenter> WebPageProxy::paymentCoordinatorAuthorizationPresenter(WebPaymentCoordinatorProxy& paymentCoordinatorProxy, PKPaymentRequest *paymentRequest)
1184 {
1185     return std::make_unique<PaymentAuthorizationViewController>(paymentCoordinatorProxy, paymentRequest);
1186 }
1187
1188 UIViewController *WebPageProxy::paymentCoordinatorPresentingViewController(const WebPaymentCoordinatorProxy&)
1189 {
1190     return uiClient().presentingViewController();
1191 }
1192
1193 const String& WebPageProxy::paymentCoordinatorCTDataConnectionServiceType(const WebPaymentCoordinatorProxy&, PAL::SessionID sessionID)
1194 {
1195     ASSERT_UNUSED(sessionID, sessionID == websiteDataStore().sessionID());
1196     return process().processPool().configuration().ctDataConnectionServiceType();
1197 }
1198
1199 #endif
1200
1201 } // namespace WebKit
1202
1203 #endif // PLATFORM(IOS_FAMILY)