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