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