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