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