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