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