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