Unreviewed, rolling out r191902.
[WebKit-https.git] / Source / WebKit2 / UIProcess / ios / WebPageProxyIOS.mm
1 /*
2  * Copyright (C) 2012 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 "NativeWebKeyboardEvent.h"
35 #import "PageClient.h"
36 #import "RemoteLayerTreeDrawingAreaProxy.h"
37 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
38 #import "RemoteLayerTreeTransaction.h"
39 #import "UIKitSPI.h"
40 #import "UserData.h"
41 #import "ViewUpdateDispatcherMessages.h"
42 #import "WKBrowsingContextControllerInternal.h"
43 #import "WebKitSystemInterfaceIOS.h"
44 #import "WebPageMessages.h"
45 #import "WebProcessProxy.h"
46 #import "WebVideoFullscreenManagerProxy.h"
47 #import <WebCore/FrameView.h>
48 #import <WebCore/NotImplemented.h>
49 #import <WebCore/SharedBuffer.h>
50 #import <WebCore/UserAgent.h>
51
52 #if USE(QUICK_LOOK)
53 #import "APILoaderClient.h"
54 #import "APINavigationClient.h"
55 #import <wtf/text/WTFString.h>
56 #endif
57
58 using namespace WebCore;
59
60 namespace WebKit {
61
62 void WebPageProxy::platformInitialize()
63 {
64 }
65
66 static String webKitBundleVersionString()
67 {
68     return [[NSBundle bundleForClass:NSClassFromString(@"WKWebView")] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
69 }
70
71 String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
72 {
73     return standardUserAgentWithApplicationName(applicationNameForUserAgent, webKitBundleVersionString());
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, uint64_t 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, uint64_t 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);
149 }
150
151 void WebPageProxy::autocorrectionDataCallback(const Vector<WebCore::FloatRect>& rects, const String& fontName, float fontSize, uint64_t fontTraits, uint64_t 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::dictationContextCallback(const String& selectedText, const String& beforeText, const String& afterText, uint64_t callbackID)
163 {
164     auto callback = m_callbacks.take<DictationContextCallback>(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, uint64_t 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::updateVisibleContentRects(const WebCore::FloatRect& exposedRect, const WebCore::FloatRect& unobscuredRect, const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& customFixedPositionRect, double scale, bool inStableState, bool isChangingObscuredInsetsInteractively, double timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate)
185 {
186     if (!isValid())
187         return;
188
189     VisibleContentRectUpdateInfo visibleContentRectUpdateInfo(exposedRect, unobscuredRect, unobscuredRectInScrollViewCoordinates, customFixedPositionRect, scale, inStableState, isChangingObscuredInsetsInteractively, timestamp, horizontalVelocity, verticalVelocity, scaleChangeRate, downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).lastCommittedLayerTreeTransactionID());
190
191     if (visibleContentRectUpdateInfo == m_lastVisibleContentRectUpdate)
192         return;
193
194     m_lastVisibleContentRectUpdate = visibleContentRectUpdateInfo;
195     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, visibleContentRectUpdateInfo), 0);
196 }
197
198 void WebPageProxy::resendLastVisibleContentRects()
199 {
200     m_process->send(Messages::ViewUpdateDispatcher::VisibleContentRectUpdate(m_pageID, m_lastVisibleContentRectUpdate), 0);
201 }
202
203 static inline float adjustedUnexposedEdge(float documentEdge, float exposedRectEdge, float factor)
204 {
205     if (exposedRectEdge < documentEdge)
206         return documentEdge - factor * (documentEdge - exposedRectEdge);
207     
208     return exposedRectEdge;
209 }
210
211 static inline float adjustedUnexposedMaxEdge(float documentEdge, float exposedRectEdge, float factor)
212 {
213     if (exposedRectEdge > documentEdge)
214         return documentEdge + factor * (exposedRectEdge - documentEdge);
215     
216     return exposedRectEdge;
217 }
218
219 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, double displayedContentScale, UnobscuredRectConstraint constraint) const
220 {
221     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
222     FloatRect documentRect = m_pageClient.documentRect();
223
224     if (m_pageClient.isAssistingNode())
225         return documentRect;
226
227     if (constraint == UnobscuredRectConstraint::ConstrainedToDocumentRect)
228         constrainedUnobscuredRect.intersect(documentRect);
229
230     double minimumScale = m_pageClient.minimumZoomScale();
231     
232     if (displayedContentScale < minimumScale) {
233         const CGFloat slope = 12;
234         CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
235             
236         constrainedUnobscuredRect.setX(adjustedUnexposedEdge(documentRect.x(), constrainedUnobscuredRect.x(), factor));
237         constrainedUnobscuredRect.setY(adjustedUnexposedEdge(documentRect.y(), constrainedUnobscuredRect.y(), factor));
238         constrainedUnobscuredRect.setWidth(adjustedUnexposedMaxEdge(documentRect.maxX(), constrainedUnobscuredRect.maxX(), factor) - constrainedUnobscuredRect.x());
239         constrainedUnobscuredRect.setHeight(adjustedUnexposedMaxEdge(documentRect.maxY(), constrainedUnobscuredRect.maxY(), factor) - constrainedUnobscuredRect.y());
240     }
241     
242     return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
243 }
244
245 void WebPageProxy::overflowScrollViewWillStartPanGesture()
246 {
247     m_pageClient.overflowScrollViewWillStartPanGesture();
248 }
249
250 void WebPageProxy::overflowScrollViewDidScroll()
251 {
252     m_pageClient.overflowScrollViewDidScroll();
253 }
254
255 void WebPageProxy::overflowScrollWillStartScroll()
256 {
257     m_pageClient.overflowScrollWillStartScroll();
258 }
259
260 void WebPageProxy::overflowScrollDidEndScroll()
261 {
262     m_pageClient.overflowScrollDidEndScroll();
263 }
264
265 void WebPageProxy::dynamicViewportSizeUpdate(const FloatSize& minimumLayoutSize, const WebCore::FloatSize& maximumUnobscuredSize, const FloatRect& targetExposedContentRect, const FloatRect& targetUnobscuredRect, const FloatRect& targetUnobscuredRectInScrollViewCoordinates,  double targetScale, int32_t deviceOrientation)
266 {
267     if (!isValid())
268         return;
269
270     m_dynamicViewportSizeUpdateWaitingForTarget = true;
271     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = true;
272     m_process->send(Messages::WebPage::DynamicViewportSizeUpdate(minimumLayoutSize, maximumUnobscuredSize, targetExposedContentRect, targetUnobscuredRect, targetUnobscuredRectInScrollViewCoordinates, targetScale, deviceOrientation, ++m_currentDynamicViewportSizeUpdateID), m_pageID);
273 }
274
275 void WebPageProxy::synchronizeDynamicViewportUpdate()
276 {
277     if (!isValid())
278         return;
279
280     if (m_dynamicViewportSizeUpdateWaitingForTarget) {
281         // We do not want the UIProcess to finish animated resize with the old content size, scale, etc.
282         // If that happens, the UIProcess would start pushing new VisibleContentRectUpdateInfo to the WebProcess with
283         // invalid informations.
284         //
285         // Ideally, the animated resize should just be transactional, and the UIProcess would remain in the "resize" state
286         // until both DynamicViewportUpdateChangedTarget and the associated commitLayerTree are finished.
287         // The tricky part with such implementation is if a second animated resize starts before the end of the previous one.
288         // In that case, the values used for the target state needs to be computed from the output of the previous animated resize.
289         //
290         // The following is a workaround to have the UIProcess in a consistent state.
291         // Instead of handling nested resize, we block the UIProcess until the animated resize finishes.
292         double newScale;
293         FloatPoint newScrollPosition;
294         uint64_t nextValidLayerTreeTransactionID;
295         if (m_process->sendSync(Messages::WebPage::SynchronizeDynamicViewportUpdate(), Messages::WebPage::SynchronizeDynamicViewportUpdate::Reply(newScale, newScrollPosition, nextValidLayerTreeTransactionID), m_pageID, std::chrono::seconds(2))) {
296             m_dynamicViewportSizeUpdateWaitingForTarget = false;
297             m_dynamicViewportSizeUpdateLayerTreeTransactionID = nextValidLayerTreeTransactionID;
298             m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, nextValidLayerTreeTransactionID);
299         }
300
301     }
302
303     // If m_dynamicViewportSizeUpdateWaitingForTarget is false, we are waiting for the next valid frame with the hope it is the one for the new target.
304     // If m_dynamicViewportSizeUpdateWaitingForTarget is still true, this is a desesperate attempt to get the valid frame before finishing the animation.
305     if (m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit)
306         m_process->connection()->waitForAndDispatchImmediately<Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree>(m_pageID, std::chrono::seconds(1), IPC::InterruptWaitingIfSyncMessageArrives);
307
308     m_dynamicViewportSizeUpdateWaitingForTarget = false;
309     m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
310 }
311
312 void WebPageProxy::setViewportConfigurationMinimumLayoutSize(const WebCore::FloatSize& size)
313 {
314     m_process->send(Messages::WebPage::SetViewportConfigurationMinimumLayoutSize(size), m_pageID);
315 }
316
317 void WebPageProxy::setMaximumUnobscuredSize(const WebCore::FloatSize& size)
318 {
319     m_process->send(Messages::WebPage::SetMaximumUnobscuredSize(size), m_pageID);
320 }
321
322 void WebPageProxy::setDeviceOrientation(int32_t deviceOrientation)
323 {
324     if (deviceOrientation != m_deviceOrientation) {
325         m_deviceOrientation = deviceOrientation;
326         if (isValid())
327             m_process->send(Messages::WebPage::SetDeviceOrientation(deviceOrientation), m_pageID);
328     }
329 }
330
331 static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t committedSize)
332 {
333     const double thesholdSizeFraction = 0.5; // Empirically-derived.
334     return committedSize > thresholdSize * thesholdSizeFraction;
335 }
336
337 void WebPageProxy::didCommitLayerTree(const WebKit::RemoteLayerTreeTransaction& layerTreeTransaction)
338 {
339     m_pageExtendedBackgroundColor = layerTreeTransaction.pageExtendedBackgroundColor();
340
341     if (!m_hasReceivedLayerTreeTransactionAfterDidCommitLoad) {
342         if (layerTreeTransaction.transactionID() >= m_firstLayerTreeTransactionIdAfterDidCommitLoad) {
343             m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = true;
344             m_lastVisibleContentRectUpdate = VisibleContentRectUpdateInfo();
345         }
346     }
347
348     if (!m_dynamicViewportSizeUpdateWaitingForTarget && m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit) {
349         if (layerTreeTransaction.transactionID() >= m_dynamicViewportSizeUpdateLayerTreeTransactionID)
350             m_dynamicViewportSizeUpdateWaitingForLayerTreeCommit = false;
351     }
352
353     m_pageClient.didCommitLayerTree(layerTreeTransaction);
354
355     // FIXME: Remove this special mechanism and fold it into the transaction's layout milestones.
356     if (m_wantsSessionRestorationRenderTreeSizeThresholdEvent && !m_hitRenderTreeSizeThreshold
357         && exceedsRenderTreeSizeSizeThreshold(m_sessionRestorationRenderTreeSize, layerTreeTransaction.renderTreeSize())) {
358         m_hitRenderTreeSizeThreshold = true;
359         didLayout(WebCore::ReachedSessionRestorationRenderTreeSizeThreshold);
360     }
361
362     if (m_hasDeferredStartAssistingNode) {
363         m_pageClient.startAssistingNode(m_deferredNodeAssistanceArguments->m_nodeInformation, m_deferredNodeAssistanceArguments->m_userIsInteracting, m_deferredNodeAssistanceArguments->m_blurPreviousNode, m_deferredNodeAssistanceArguments->m_userData.get());
364         m_hasDeferredStartAssistingNode = false;
365         m_deferredNodeAssistanceArguments = nullptr;
366     }
367 }
368
369 void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, bool isInteractingWithAssistedNode, std::function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)> callbackFunction)
370 {
371     if (!isValid()) {
372         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
373         return;
374     }
375
376     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
377     m_process->send(Messages::WebPage::SelectWithGesture(point, (uint32_t)granularity, gestureType, gestureState, isInteractingWithAssistedNode, callbackID), m_pageID);
378 }
379
380 void WebPageProxy::updateSelectionWithTouches(const WebCore::IntPoint point, uint32_t touches, bool baseIsStart, std::function<void (const WebCore::IntPoint&, uint32_t, CallbackBase::Error)> callbackFunction)
381 {
382     if (!isValid()) {
383         callbackFunction(WebCore::IntPoint(), 0, CallbackBase::Error::Unknown);
384         return;
385     }
386
387     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
388     m_process->send(Messages::WebPage::UpdateSelectionWithTouches(point, touches, baseIsStart, callbackID), m_pageID);
389 }
390     
391 void WebPageProxy::replaceDictatedText(const String& oldText, const String& newText)
392 {
393     m_process->send(Messages::WebPage::ReplaceDictatedText(oldText, newText), m_pageID);
394 }
395
396 void WebPageProxy::replaceSelectedText(const String& oldText, const String& newText)
397 {
398     m_process->send(Messages::WebPage::ReplaceSelectedText(oldText, newText), m_pageID);
399 }
400
401 void WebPageProxy::requestAutocorrectionData(const String& textForAutocorrection, std::function<void (const Vector<WebCore::FloatRect>&, const String&, double, uint64_t, CallbackBase::Error)> callbackFunction)
402 {
403     if (!isValid()) {
404         callbackFunction(Vector<WebCore::FloatRect>(), String(), 0, 0, CallbackBase::Error::Unknown);
405         return;
406     }
407
408     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
409     m_process->send(Messages::WebPage::RequestAutocorrectionData(textForAutocorrection, callbackID), m_pageID);
410 }
411
412 void WebPageProxy::applyAutocorrection(const String& correction, const String& originalText, std::function<void (const String&, CallbackBase::Error)> callbackFunction)
413 {
414     if (!isValid()) {
415         callbackFunction(String(), CallbackBase::Error::Unknown);
416         return;
417     }
418
419     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
420     m_process->send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
421 }
422
423 void WebPageProxy::executeEditCommand(const String& commandName, std::function<void (CallbackBase::Error)> callbackFunction)
424 {
425     if (!isValid()) {
426         callbackFunction(CallbackBase::Error::Unknown);
427         return;
428     }
429     
430     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
431     m_process->send(Messages::WebPage::ExecuteEditCommandWithCallback(commandName, callbackID), m_pageID);
432 }
433
434 bool WebPageProxy::applyAutocorrection(const String& correction, const String& originalText)
435 {
436     bool autocorrectionApplied = false;
437     m_process->sendSync(Messages::WebPage::SyncApplyAutocorrection(correction, originalText), Messages::WebPage::SyncApplyAutocorrection::Reply(autocorrectionApplied), m_pageID);
438     return autocorrectionApplied;
439 }
440
441 void WebPageProxy::selectTextWithGranularityAtPoint(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithAssistedNode, std::function<void (CallbackBase::Error)> callbackFunction)
442 {
443     if (!isValid()) {
444         callbackFunction(CallbackBase::Error::Unknown);
445         return;
446     }
447     
448     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
449     m_process->send(Messages::WebPage::SelectTextWithGranularityAtPoint(point, static_cast<uint32_t>(granularity), isInteractingWithAssistedNode, callbackID), m_pageID);
450 }
451
452 void WebPageProxy::selectPositionAtBoundaryWithDirection(const WebCore::IntPoint point, WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, bool isInteractingWithAssistedNode, std::function<void (CallbackBase::Error)> callbackFunction)
453 {
454     if (!isValid()) {
455         callbackFunction(CallbackBase::Error::Unknown);
456         return;
457     }
458     
459     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
460     m_process->send(Messages::WebPage::SelectPositionAtBoundaryWithDirection(point, static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), isInteractingWithAssistedNode, callbackID), m_pageID);
461 }
462
463 void WebPageProxy::moveSelectionAtBoundaryWithDirection(WebCore::TextGranularity granularity, WebCore::SelectionDirection direction, std::function<void(CallbackBase::Error)> callbackFunction)
464 {
465     if (!isValid()) {
466         callbackFunction(CallbackBase::Error::Unknown);
467         return;
468     }
469     
470     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
471     m_process->send(Messages::WebPage::MoveSelectionAtBoundaryWithDirection(static_cast<uint32_t>(granularity), static_cast<uint32_t>(direction), callbackID), m_pageID);
472 }
473     
474 void WebPageProxy::selectPositionAtPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, std::function<void (CallbackBase::Error)> callbackFunction)
475 {
476     if (!isValid()) {
477         callbackFunction(CallbackBase::Error::Unknown);
478         return;
479     }
480     
481     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
482     m_process->send(Messages::WebPage::SelectPositionAtPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
483 }
484
485 void WebPageProxy::beginSelectionInDirection(WebCore::SelectionDirection direction, std::function<void (uint64_t, CallbackBase::Error)> callbackFunction)
486 {
487     if (!isValid()) {
488         callbackFunction(0, CallbackBase::Error::Unknown);
489         return;
490     }
491     
492     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
493     m_process->send(Messages::WebPage::BeginSelectionInDirection(direction, callbackID), m_pageID);
494 }
495
496 void WebPageProxy::updateSelectionWithExtentPoint(const WebCore::IntPoint point, bool isInteractingWithAssistedNode, std::function<void (uint64_t, CallbackBase::Error)> callbackFunction)
497 {
498     if (!isValid()) {
499         callbackFunction(0, CallbackBase::Error::Unknown);
500         return;
501     }
502     
503     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
504     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPoint(point, isInteractingWithAssistedNode, callbackID), m_pageID);
505     
506 }
507
508 void WebPageProxy::updateSelectionWithExtentPointAndBoundary(const WebCore::IntPoint point, WebCore::TextGranularity granularity, bool isInteractingWithAssistedNode, std::function<void(uint64_t, CallbackBase::Error)> callbackFunction)
509 {
510     if (!isValid()) {
511         callbackFunction(0, CallbackBase::Error::Unknown);
512         return;
513     }
514     
515     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
516     m_process->send(Messages::WebPage::UpdateSelectionWithExtentPointAndBoundary(point, granularity, isInteractingWithAssistedNode, callbackID), m_pageID);
517     
518 }
519
520 void WebPageProxy::requestDictationContext(std::function<void (const String&, const String&, const String&, CallbackBase::Error)> callbackFunction)
521 {
522     if (!isValid()) {
523         callbackFunction(String(), String(), String(), CallbackBase::Error::Unknown);
524         return;
525     }
526
527     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
528     m_process->send(Messages::WebPage::RequestDictationContext(callbackID), m_pageID);
529 }
530
531 void WebPageProxy::requestAutocorrectionContext(std::function<void (const String&, const String&, const String&, const String&, uint64_t, uint64_t, CallbackBase::Error)> callbackFunction)
532 {
533     if (!isValid()) {
534         callbackFunction(String(), String(), String(), String(), 0, 0, CallbackBase::Error::Unknown);
535         return;
536     }
537
538     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
539     m_process->send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
540 }
541
542 void WebPageProxy::getAutocorrectionContext(String& beforeContext, String& markedText, String& selectedText, String& afterContext, uint64_t& location, uint64_t& length)
543 {
544     m_process->sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
545 }
546
547 void WebPageProxy::getLookupContextAtPoint(const WebCore::IntPoint& point, std::function<void(const String&, CallbackBase::Error)> callbackFunction)
548 {
549     if (!isValid()) {
550         callbackFunction(String(), CallbackBase::Error::Unknown);
551         return;
552     }
553     
554     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
555     m_process->send(Messages::WebPage::GetLookupContextAtPoint(point, callbackID), m_pageID);
556 }
557
558 void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, std::function<void (const WebCore::IntPoint&, uint32_t, uint32_t, uint32_t, CallbackBase::Error)> callbackFunction)
559 {
560     if (!isValid()) {
561         callbackFunction(WebCore::IntPoint(), 0, 0, 0, CallbackBase::Error::Unknown);
562         return;
563     }
564
565     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
566     m_process->send(Messages::WebPage::SelectWithTwoTouches(from, to, gestureType, gestureState, callbackID), m_pageID);
567 }
568
569 void WebPageProxy::updateBlockSelectionWithTouch(const WebCore::IntPoint point, uint32_t touch, uint32_t handlePosition)
570 {
571     m_process->send(Messages::WebPage::UpdateBlockSelectionWithTouch(point, touch, handlePosition), m_pageID);
572 }
573
574 void WebPageProxy::didReceivePositionInformation(const InteractionInformationAtPosition& info)
575 {
576     m_pageClient.positionInformationDidChange(info);
577 }
578
579 void WebPageProxy::getPositionInformation(const WebCore::IntPoint& point, InteractionInformationAtPosition& info)
580 {
581     m_process->sendSync(Messages::WebPage::GetPositionInformation(point), Messages::WebPage::GetPositionInformation::Reply(info), m_pageID);
582 }
583
584 void WebPageProxy::requestPositionInformation(const WebCore::IntPoint& point)
585 {
586     m_process->send(Messages::WebPage::RequestPositionInformation(point), m_pageID);
587 }
588
589 void WebPageProxy::startInteractionWithElementAtPosition(const WebCore::IntPoint& point)
590 {
591     m_process->send(Messages::WebPage::StartInteractionWithElementAtPosition(point), m_pageID);
592 }
593
594 void WebPageProxy::stopInteraction()
595 {
596     m_process->send(Messages::WebPage::StopInteraction(), m_pageID);
597 }
598
599 void WebPageProxy::performActionOnElement(uint32_t action)
600 {
601     m_process->send(Messages::WebPage::PerformActionOnElement(action), m_pageID);
602 }
603
604 void WebPageProxy::saveImageToLibrary(const SharedMemory::Handle& imageHandle, uint64_t imageSize)
605 {
606     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(imageHandle, SharedMemory::Protection::ReadOnly);
607     RefPtr<SharedBuffer> buffer = SharedBuffer::create(static_cast<unsigned char*>(sharedMemoryBuffer->data()), imageSize);
608     m_pageClient.saveImageToLibrary(buffer);
609 }
610
611 void WebPageProxy::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
612 {
613     m_pageClient.didUpdateBlockSelectionWithTouch(touch, flags, growThreshold, shrinkThreshold);
614 }
615
616 void WebPageProxy::applicationDidEnterBackground()
617 {
618     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
619     m_process->send(Messages::WebPage::ApplicationDidEnterBackground(isSuspendedUnderLock), m_pageID);
620 }
621
622 void WebPageProxy::applicationWillEnterForeground()
623 {
624     bool isSuspendedUnderLock = [UIApp isSuspendedUnderLock];
625     m_process->send(Messages::WebPage::ApplicationWillEnterForeground(isSuspendedUnderLock), m_pageID);
626 }
627
628 void WebPageProxy::applicationWillResignActive()
629 {
630     m_process->send(Messages::WebPage::ApplicationWillResignActive(), m_pageID);
631 }
632
633 void WebPageProxy::applicationDidBecomeActive()
634 {
635     m_process->send(Messages::WebPage::ApplicationDidBecomeActive(), m_pageID);
636 }
637
638 void WebPageProxy::extendSelection(WebCore::TextGranularity granularity)
639 {
640     m_process->send(Messages::WebPage::ExtendSelection(static_cast<uint32_t>(granularity)), m_pageID);
641 }
642
643 void WebPageProxy::selectWordBackward()
644 {
645     m_process->send(Messages::WebPage::SelectWordBackward(), m_pageID);
646 }
647
648 void WebPageProxy::moveSelectionByOffset(int32_t offset, std::function<void (CallbackBase::Error)> callbackFunction)
649 {
650     if (!isValid()) {
651         callbackFunction(CallbackBase::Error::Unknown);
652         return;
653     }
654     
655     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
656     m_process->send(Messages::WebPage::MoveSelectionByOffset(offset, callbackID), m_pageID);
657 }
658
659 void WebPageProxy::interpretKeyEvent(const EditorState& state, bool isCharEvent, bool& handled)
660 {
661     m_editorState = state;
662     handled = m_pageClient.interpretKeyEvent(m_keyEventQueue.first(), isCharEvent);
663 }
664
665 // Complex text input support for plug-ins.
666 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t, const String&)
667 {
668     notImplemented();
669 }
670
671 void WebPageProxy::setSmartInsertDeleteEnabled(bool)
672 {
673     notImplemented();
674 }
675
676 void WebPageProxy::registerWebProcessAccessibilityToken(const IPC::DataReference& data)
677 {
678     m_pageClient.accessibilityWebProcessTokenReceived(data);
679 }    
680
681 void WebPageProxy::makeFirstResponder()
682 {
683     notImplemented();
684 }
685
686 void WebPageProxy::registerUIProcessAccessibilityTokens(const IPC::DataReference& elementToken, const IPC::DataReference& windowToken)
687 {
688     if (!isValid())
689         return;
690     
691     process().send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
692 }
693
694 void WebPageProxy::pluginFocusOrWindowFocusChanged(uint64_t, bool)
695 {
696     notImplemented();
697 }
698
699 void WebPageProxy::setPluginComplexTextInputState(uint64_t, uint64_t)
700 {
701     notImplemented();
702 }
703
704 void WebPageProxy::executeSavedCommandBySelector(const String&, bool&)
705 {
706     notImplemented();
707 }
708
709 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent&)
710 {
711     notImplemented();
712     return false;
713 }
714
715 bool WebPageProxy::acceptsFirstMouse(int, const WebKit::WebMouseEvent&)
716 {
717     notImplemented();
718     return false;
719 }
720
721 void WebPageProxy::willStartUserTriggeredZooming()
722 {
723     process().send(Messages::WebPage::WillStartUserTriggeredZooming(), m_pageID);
724 }
725
726 void WebPageProxy::potentialTapAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
727 {
728     process().send(Messages::WebPage::PotentialTapAtPosition(requestID, position), m_pageID);
729 }
730
731 void WebPageProxy::commitPotentialTap()
732 {
733     process().send(Messages::WebPage::CommitPotentialTap(m_layerTreeTransactionIdAtLastTouchStart), m_pageID);
734 }
735
736 void WebPageProxy::cancelPotentialTap()
737 {
738     process().send(Messages::WebPage::CancelPotentialTap(), m_pageID);
739 }
740
741 void WebPageProxy::tapHighlightAtPosition(const WebCore::FloatPoint& position, uint64_t& requestID)
742 {
743     process().send(Messages::WebPage::TapHighlightAtPosition(requestID, position), m_pageID);
744 }
745
746 void WebPageProxy::handleTap(const FloatPoint& location)
747 {
748     process().send(Messages::WebPage::HandleTap(roundedIntPoint(location), m_layerTreeTransactionIdAtLastTouchStart), m_pageID);
749 }
750
751 void WebPageProxy::inspectorNodeSearchMovedToPosition(const WebCore::FloatPoint& position)
752 {
753     process().send(Messages::WebPage::InspectorNodeSearchMovedToPosition(position), m_pageID);
754 }
755
756 void WebPageProxy::inspectorNodeSearchEndedAtPosition(const WebCore::FloatPoint& position)
757 {
758     process().send(Messages::WebPage::InspectorNodeSearchEndedAtPosition(position), m_pageID);
759 }
760
761 void WebPageProxy::blurAssistedNode()
762 {
763     process().send(Messages::WebPage::BlurAssistedNode(), m_pageID);
764 }
765
766 FloatSize WebPageProxy::screenSize()
767 {
768     return FloatSize(WKGetScreenSize());
769 }
770
771 FloatSize WebPageProxy::availableScreenSize()
772 {
773     return FloatSize(WKGetAvailableScreenSize());
774 }
775     
776 float WebPageProxy::textAutosizingWidth()
777 {
778     return WKGetScreenSize().width;
779 }
780
781 void WebPageProxy::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t dynamicViewportSizeUpdateID)
782 {
783     if (dynamicViewportSizeUpdateID != m_currentDynamicViewportSizeUpdateID)
784         return;
785
786     if (m_dynamicViewportSizeUpdateWaitingForTarget) {
787         m_dynamicViewportSizeUpdateLayerTreeTransactionID = downcast<RemoteLayerTreeDrawingAreaProxy>(*drawingArea()).nextLayerTreeTransactionID();
788         m_dynamicViewportSizeUpdateWaitingForTarget = false;
789         m_pageClient.dynamicViewportUpdateChangedTarget(newScale, newScrollPosition, m_dynamicViewportSizeUpdateLayerTreeTransactionID);
790     }
791 }
792
793 void WebPageProxy::couldNotRestorePageState()
794 {
795     m_pageClient.couldNotRestorePageState();
796 }
797
798 void WebPageProxy::restorePageState(const WebCore::FloatRect& exposedRect, double scale)
799 {
800     m_pageClient.restorePageState(exposedRect, scale);
801 }
802
803 void WebPageProxy::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
804 {
805     m_pageClient.restorePageCenterAndScale(center, scale);
806 }
807
808 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)
809 {
810     m_pageClient.didGetTapHighlightGeometries(requestID, color, highlightedQuads, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
811 }
812
813 void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, const UserData& userData)
814 {
815     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
816     if (m_editorState.isMissingPostLayoutData) {
817         m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, userDataObject });
818         m_hasDeferredStartAssistingNode = true;
819         return;
820     }
821
822     m_pageClient.startAssistingNode(information, userIsInteracting, blurPreviousNode, userDataObject);
823 }
824
825 void WebPageProxy::stopAssistingNode()
826 {
827     if (m_hasDeferredStartAssistingNode) {
828         m_hasDeferredStartAssistingNode = false;
829         m_deferredNodeAssistanceArguments = nullptr;
830     }
831     m_pageClient.stopAssistingNode();
832 }
833
834 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
835 {
836     m_pageClient.showInspectorHighlight(highlight);
837 }
838
839 void WebPageProxy::hideInspectorHighlight()
840 {
841     m_pageClient.hideInspectorHighlight();
842 }
843
844 void WebPageProxy::showInspectorIndication()
845 {
846     m_pageClient.showInspectorIndication();
847 }
848
849 void WebPageProxy::hideInspectorIndication()
850 {
851     m_pageClient.hideInspectorIndication();
852 }
853
854 void WebPageProxy::enableInspectorNodeSearch()
855 {
856     m_pageClient.enableInspectorNodeSearch();
857 }
858
859 void WebPageProxy::disableInspectorNodeSearch()
860 {
861     m_pageClient.disableInspectorNodeSearch();
862 }
863
864 void WebPageProxy::focusNextAssistedNode(bool isForward, std::function<void (CallbackBase::Error)> callbackFunction)
865 {
866     if (!isValid()) {
867         callbackFunction(CallbackBase::Error::Unknown);
868         return;
869     }
870     
871     uint64_t callbackID = m_callbacks.put(WTF::move(callbackFunction), m_process->throttler().backgroundActivityToken());
872     process().send(Messages::WebPage::FocusNextAssistedNode(isForward, callbackID), m_pageID);
873 }
874
875 void WebPageProxy::setAssistedNodeValue(const String& value)
876 {
877     process().send(Messages::WebPage::SetAssistedNodeValue(value), m_pageID);
878 }
879
880 void WebPageProxy::setAssistedNodeValueAsNumber(double value)
881 {
882     process().send(Messages::WebPage::SetAssistedNodeValueAsNumber(value), m_pageID);
883 }
884
885 void WebPageProxy::setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
886 {
887     process().send(Messages::WebPage::SetAssistedNodeSelectedIndex(index, allowMultipleSelection), m_pageID);
888 }
889
890 void WebPageProxy::didPerformDictionaryLookup(const DictionaryPopupInfo&)
891 {
892     notImplemented();
893 }
894
895 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, const String&, const IPC::DataReference&, const String&)
896 {
897     notImplemented();
898 }
899
900 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplicationRaw(const String&, const String&, const uint8_t*, unsigned long, const String&)
901 {
902     notImplemented();
903 }
904
905 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(const String&)
906 {
907     notImplemented();
908 }
909
910 void WebPageProxy::setAcceleratedCompositingRootLayer(LayerOrView* rootLayer)
911 {
912     m_pageClient.setAcceleratedCompositingRootLayer(rootLayer);
913 }
914
915 void WebPageProxy::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
916 {
917     m_pageClient.showPlaybackTargetPicker(hasVideo, elementRect);
918 }
919
920 void WebPageProxy::zoomToRect(FloatRect rect, double minimumScale, double maximumScale)
921 {
922     m_pageClient.zoomToRect(rect, minimumScale, maximumScale);
923 }
924
925 void WebPageProxy::commitPotentialTapFailed()
926 {
927     m_pageClient.commitPotentialTapFailed();
928 }
929
930 void WebPageProxy::didNotHandleTapAsClick(const WebCore::IntPoint& point)
931 {
932     m_uiClient->didNotHandleTapAsClick(point);
933 }
934
935 void WebPageProxy::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
936 {
937     m_pageClient.disableDoubleTapGesturesDuringTapIfNecessary(requestID);
938 }
939
940 void WebPageProxy::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
941 {
942     m_pageClient.didFinishDrawingPagesToPDF(pdfData);
943 }
944
945 void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategory)
946 {
947     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
948 }
949
950 void WebPageProxy::editorStateChanged(const EditorState& editorState)
951 {
952     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
953     
954     m_editorState = editorState;
955     
956     // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
957     if (couldChangeSecureInputState && !editorState.selectionIsNone)
958         m_pageClient.updateSecureInputState();
959     
960     if (editorState.shouldIgnoreCompositionSelectionChange)
961         return;
962     
963     // We always need to notify the client on iOS to make sure the selection is redrawn,
964     // even during composition to support phrase boundary gesture.
965     m_pageClient.selectionDidChange();
966 }
967
968 #if USE(QUICK_LOOK)
969     
970 void WebPageProxy::didStartLoadForQuickLookDocumentInMainFrame(const String& fileName, const String& uti)
971 {
972     // Ensure that fileName isn't really a path name
973     static_assert(notFound + 1 == 0, "The following line assumes WTF::notFound equals -1");
974     if (m_navigationClient)
975         m_navigationClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
976     else
977         m_loaderClient->didStartLoadForQuickLookDocumentInMainFrame(fileName.substring(fileName.reverseFind('/') + 1), uti);
978 }
979
980 void WebPageProxy::didFinishLoadForQuickLookDocumentInMainFrame(const QuickLookDocumentData& data)
981 {
982     if (m_navigationClient)
983         m_navigationClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
984     else
985         m_loaderClient->didFinishLoadForQuickLookDocumentInMainFrame(data);
986 }
987 #endif
988
989 } // namespace WebKit
990
991 #endif // PLATFORM(IOS)