Add support for recognizing data interaction gestures in WebKit2
[WebKit-https.git] / Source / WebKit2 / UIProcess / ios / PageClientImplIOS.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 "PageClientImplIOS.h"
28
29 #if PLATFORM(IOS)
30
31 #import "APIData.h"
32 #import "DataReference.h"
33 #import "DownloadProxy.h"
34 #import "InteractionInformationAtPosition.h"
35 #import "NativeWebKeyboardEvent.h"
36 #import "NavigationState.h"
37 #import "StringUtilities.h"
38 #import "UIKitSPI.h"
39 #import "ViewSnapshotStore.h"
40 #import "WKContentView.h"
41 #import "WKContentViewInteraction.h"
42 #import "WKGeolocationProviderIOS.h"
43 #import "WKPasswordView.h"
44 #import "WKProcessPoolInternal.h"
45 #import "WKWebViewConfigurationInternal.h"
46 #import "WKWebViewContentProviderRegistry.h"
47 #import "WKWebViewInternal.h"
48 #import "WebContextMenuProxy.h"
49 #import "WebEditCommandProxy.h"
50 #import "WebProcessProxy.h"
51 #import "_WKDownloadInternal.h"
52 #import <WebCore/NotImplemented.h>
53 #import <WebCore/PlatformScreen.h>
54 #import <WebCore/SharedBuffer.h>
55 #import <WebCore/TextIndicator.h>
56 #import <WebCore/ValidationBubble.h>
57
58 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_webView->_page->process().connection())
59
60 using namespace WebCore;
61 using namespace WebKit;
62
63 @interface WKEditCommandObjC : NSObject
64 {
65     RefPtr<WebEditCommandProxy> m_command;
66 }
67 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command;
68 - (WebEditCommandProxy*)command;
69 @end
70
71 @interface WKEditorUndoTargetObjC : NSObject
72 - (void)undoEditing:(id)sender;
73 - (void)redoEditing:(id)sender;
74 @end
75
76 @implementation WKEditCommandObjC
77
78 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command
79 {
80     self = [super init];
81     if (!self)
82         return nil;
83     
84     m_command = command;
85     return self;
86 }
87
88 - (WebEditCommandProxy *)command
89 {
90     return m_command.get();
91 }
92
93 @end
94
95 @implementation WKEditorUndoTargetObjC
96
97 - (void)undoEditing:(id)sender
98 {
99     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
100     [sender command]->unapply();
101 }
102
103 - (void)redoEditing:(id)sender
104 {
105     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
106     [sender command]->reapply();
107 }
108
109 @end
110
111 namespace WebKit {
112
113 PageClientImpl::PageClientImpl(WKContentView *contentView, WKWebView *webView)
114     : m_contentView(contentView)
115     , m_webView(webView)
116     , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
117 {
118 }
119
120 PageClientImpl::~PageClientImpl()
121 {
122 }
123
124 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
125 {
126     return [m_contentView _createDrawingAreaProxy];
127 }
128
129 void PageClientImpl::setViewNeedsDisplay(const Region&)
130 {
131     ASSERT_NOT_REACHED();
132 }
133
134 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
135 {
136     UNUSED_PARAM(isProgrammaticScroll);
137     [m_webView _scrollToContentScrollPosition:scrollPosition scrollOrigin:scrollOrigin];
138 }
139
140 IntSize PageClientImpl::viewSize()
141 {
142     if (UIScrollView *scroller = [m_contentView _scroller])
143         return IntSize(scroller.bounds.size);
144
145     return IntSize(m_contentView.bounds.size);
146 }
147
148 bool PageClientImpl::isViewWindowActive()
149 {
150     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
151     return isViewVisible() || (m_webView && m_webView->_activeFocusedStateRetainCount);
152 }
153
154 bool PageClientImpl::isViewFocused()
155 {
156     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
157     return isViewWindowActive() || (m_webView && m_webView->_activeFocusedStateRetainCount);
158 }
159
160 bool PageClientImpl::isViewVisible()
161 {
162     if (isViewInWindow() && !m_webView._isBackground)
163         return true;
164     
165     if ([m_webView _isShowingVideoPictureInPicture])
166         return true;
167     
168     if ([m_webView _mayAutomaticallyShowVideoPictureInPicture])
169         return true;
170     
171     return false;
172 }
173
174 bool PageClientImpl::isViewInWindow()
175 {
176     // FIXME: in WebKitTestRunner, m_webView is nil, so check the content view instead.
177     if (m_webView)
178         return [m_webView window];
179
180     return [m_contentView window];
181 }
182
183 bool PageClientImpl::isViewVisibleOrOccluded()
184 {
185     return isViewVisible();
186 }
187
188 bool PageClientImpl::isVisuallyIdle()
189 {
190     return !isViewVisible();
191 }
192
193 void PageClientImpl::processDidExit()
194 {
195     [m_contentView _processDidExit];
196     [m_webView _processDidExit];
197 }
198
199 void PageClientImpl::didRelaunchProcess()
200 {
201     [m_contentView _didRelaunchProcess];
202     [m_webView _didRelaunchProcess];
203 }
204
205 void PageClientImpl::pageClosed()
206 {
207     notImplemented();
208 }
209
210 void PageClientImpl::preferencesDidChange()
211 {
212     notImplemented();
213 }
214
215 void PageClientImpl::toolTipChanged(const String&, const String&)
216 {
217     notImplemented();
218 }
219
220 void PageClientImpl::didNotHandleTapAsClick(const WebCore::IntPoint& point)
221 {
222     [m_contentView _didNotHandleTapAsClick:point];
223 }
224
225 bool PageClientImpl::decidePolicyForGeolocationPermissionRequest(WebFrameProxy& frame, API::SecurityOrigin& origin, GeolocationPermissionRequestProxy& request)
226 {
227     [[wrapper(m_webView->_page->process().processPool()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:origin.securityOrigin() frame:frame request:request view:m_webView];
228     return true;
229 }
230
231 void PageClientImpl::didStartProvisionalLoadForMainFrame()
232 {
233     [m_webView _hidePasswordView];
234 }
235
236 void PageClientImpl::didFailProvisionalLoadForMainFrame()
237 {
238     [m_webView _hidePasswordView];
239 }
240
241 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
242 {
243     [m_webView _hidePasswordView];
244     [m_webView _setHasCustomContentView:useCustomContentProvider loadedMIMEType:mimeType];
245     [m_contentView _didCommitLoadForMainFrame];
246 }
247
248 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
249 {
250     ASSERT_ARG(download, download);
251     ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
252     [static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
253 }
254
255 void PageClientImpl::didChangeContentSize(const WebCore::IntSize&)
256 {
257     notImplemented();
258 }
259
260 void PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
261 {
262     [m_contentView _disableDoubleTapGesturesDuringTapIfNecessary:requestID];
263 }
264
265 double PageClientImpl::minimumZoomScale() const
266 {
267     if (UIScrollView *scroller = [m_webView scrollView])
268         return scroller.minimumZoomScale;
269
270     return 1;
271 }
272
273 WebCore::FloatRect PageClientImpl::documentRect() const
274 {
275     return [m_contentView bounds];
276 }
277
278 void PageClientImpl::setCursor(const Cursor&)
279 {
280     notImplemented();
281 }
282
283 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool)
284 {
285     notImplemented();
286 }
287
288 void PageClientImpl::didChangeViewportProperties(const ViewportAttributes&)
289 {
290     notImplemented();
291 }
292
293 void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
294 {
295     RefPtr<WebEditCommandProxy> command = prpCommand;
296     
297     RetainPtr<WKEditCommandObjC> commandObjC = adoptNS([[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]);
298     String actionName = WebEditCommandProxy::nameForEditAction(command->editAction());
299     
300     NSUndoManager *undoManager = [m_contentView undoManager];
301     [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
302     if (!actionName.isEmpty())
303         [undoManager setActionName:(NSString *)actionName];
304 }
305
306 #if USE(INSERTION_UNDO_GROUPING)
307 void PageClientImpl::registerInsertionUndoGrouping()
308 {
309     notImplemented();
310 }
311 #endif
312
313 void PageClientImpl::clearAllEditCommands()
314 {
315     [[m_contentView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
316 }
317
318 bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
319 {
320     return (undoOrRedo == WebPageProxy::Undo) ? [[m_contentView undoManager] canUndo] : [[m_contentView undoManager] canRedo];
321 }
322
323 void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
324 {
325     return (undoOrRedo == WebPageProxy::Undo) ? [[m_contentView undoManager] undo] : [[m_contentView undoManager] redo];
326 }
327
328 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
329 {
330     NSData *remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
331     [m_contentView _setAccessibilityWebProcessToken:remoteToken];
332 }
333
334 bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, bool isCharEvent)
335 {
336     return [m_contentView _interpretKeyEvent:event.nativeEvent() isCharEvent:isCharEvent];
337 }
338
339 void PageClientImpl::positionInformationDidChange(const InteractionInformationAtPosition& info)
340 {
341     [m_contentView _positionInformationDidChange:info];
342 }
343
344 void PageClientImpl::saveImageToLibrary(PassRefPtr<SharedBuffer> imageBuffer)
345 {
346     RetainPtr<NSData> imageData = imageBuffer->createNSData();
347     UIImageDataWriteToSavedPhotosAlbum(imageData.get(), nil, NULL, NULL);
348 }
349
350 bool PageClientImpl::executeSavedCommandBySelector(const String&)
351 {
352     notImplemented();
353     return false;
354 }
355
356 void PageClientImpl::setDragImage(const IntPoint&, PassRefPtr<ShareableBitmap>, bool)
357 {
358     notImplemented();
359 }
360
361 void PageClientImpl::selectionDidChange()
362 {
363     [m_contentView _selectionChanged];
364 }
365
366 void PageClientImpl::updateSecureInputState()
367 {
368     notImplemented();
369 }
370
371 void PageClientImpl::resetSecureInputState()
372 {
373     notImplemented();
374 }
375
376 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
377 {
378     notImplemented();
379 }
380
381 void PageClientImpl::makeFirstResponder()
382 {
383     notImplemented();
384 }
385
386 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
387 {
388     notImplemented();
389     return FloatRect();
390 }
391
392 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
393 {
394     notImplemented();
395     return FloatRect();
396 }
397
398 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
399 {
400     return IntPoint([m_contentView convertPoint:point fromView:nil]);
401 }
402
403 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
404 {
405     return enclosingIntRect([m_contentView convertRect:rect toView:nil]);
406 }
407     
408 IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
409 {
410     CGPoint rootViewPoint = point;
411     if ([m_contentView respondsToSelector:@selector(accessibilityConvertPointFromSceneReferenceCoordinates:)])
412         rootViewPoint = [m_contentView accessibilityConvertPointFromSceneReferenceCoordinates:rootViewPoint];
413     return IntPoint(rootViewPoint);
414 }
415     
416 IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
417 {
418     CGRect rootViewRect = rect;
419     if ([m_contentView respondsToSelector:@selector(accessibilityConvertRectToSceneReferenceCoordinates:)])
420         rootViewRect = [m_contentView accessibilityConvertRectToSceneReferenceCoordinates:rootViewRect];
421     return enclosingIntRect(rootViewRect);
422 }
423     
424 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
425 {
426     [m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
427 }
428
429 #if ENABLE(TOUCH_EVENTS)
430 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& nativeWebtouchEvent, bool eventHandled)
431 {
432     [m_contentView _webTouchEvent:nativeWebtouchEvent preventsNativeGestures:eventHandled];
433 }
434 #endif
435
436 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy&)
437 {
438     return nullptr;
439 }
440
441 #if ENABLE(CONTEXT_MENUS)
442 std::unique_ptr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy&, const UserData&)
443 {
444     return nullptr;
445 }
446 #endif
447
448 void PageClientImpl::setTextIndicator(Ref<TextIndicator> textIndicator, TextIndicatorWindowLifetime)
449 {
450 }
451
452 void PageClientImpl::clearTextIndicator(TextIndicatorWindowDismissalAnimation)
453 {
454 }
455
456 void PageClientImpl::setTextIndicatorAnimationProgress(float)
457 {
458 }
459
460 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
461 {
462 }
463
464 void PageClientImpl::exitAcceleratedCompositingMode()
465 {
466     notImplemented();
467 }
468
469 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&)
470 {
471 }
472
473 void PageClientImpl::setAcceleratedCompositingRootLayer(LayerOrView *rootLayer)
474 {
475     [m_contentView _setAcceleratedCompositingRootView:rootLayer];
476 }
477
478 LayerOrView *PageClientImpl::acceleratedCompositingRootLayer() const
479 {
480     notImplemented();
481     return nullptr;
482 }
483
484 PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
485 {
486     return [m_webView _takeViewSnapshot];
487 }
488
489 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
490 {
491     notImplemented();
492 }
493
494 void PageClientImpl::commitPotentialTapFailed()
495 {
496     [m_contentView _commitPotentialTapFailed];
497 }
498
499 void PageClientImpl::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)
500 {
501     [m_contentView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
502 }
503
504 void PageClientImpl::didCommitLayerTree(const RemoteLayerTreeTransaction& layerTreeTransaction)
505 {
506     [m_contentView _didCommitLayerTree:layerTreeTransaction];
507 }
508
509 void PageClientImpl::layerTreeCommitComplete()
510 {
511     [m_contentView _layerTreeCommitComplete];
512 }
513
514 void PageClientImpl::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t nextValidLayerTreeTransactionID)
515 {
516     [m_webView _dynamicViewportUpdateChangedTargetToScale:newScale position:newScrollPosition nextValidLayerTreeTransactionID:nextValidLayerTreeTransactionID];
517 }
518
519 void PageClientImpl::couldNotRestorePageState()
520 {
521     [m_webView _couldNotRestorePageState];
522 }
523
524 void PageClientImpl::restorePageState(const WebCore::FloatPoint& scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatSize& obscuredInsetOnSave, double scale)
525 {
526     [m_webView _restorePageScrollPosition:scrollPosition scrollOrigin:scrollOrigin previousObscuredInset:obscuredInsetOnSave scale:scale];
527 }
528
529 void PageClientImpl::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
530 {
531     [m_webView _restorePageStateToUnobscuredCenter:center scale:scale];
532 }
533
534 void PageClientImpl::startAssistingNode(const AssistedNodeInformation& nodeInformation, bool userIsInteracting, bool blurPreviousNode, API::Object* userData)
535 {
536     MESSAGE_CHECK(!userData || userData->type() == API::Object::Type::Data);
537
538     NSObject <NSSecureCoding> *userObject = nil;
539     if (API::Data* data = static_cast<API::Data*>(userData)) {
540         auto nsData = adoptNS([[NSData alloc] initWithBytesNoCopy:const_cast<void*>(static_cast<const void*>(data->bytes())) length:data->size() freeWhenDone:NO]);
541         auto unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:nsData.get()]);
542         [unarchiver setRequiresSecureCoding:YES];
543         @try {
544             userObject = [unarchiver decodeObjectOfClass:[NSObject class] forKey:@"userObject"];
545         } @catch (NSException *exception) {
546             LOG_ERROR("Failed to decode user data: %@", exception);
547         }
548     }
549
550     [m_contentView _startAssistingNode:nodeInformation userIsInteracting:userIsInteracting blurPreviousNode:blurPreviousNode userObject:userObject];
551 }
552
553 bool PageClientImpl::isAssistingNode()
554 {
555     return [m_contentView isAssistingNode];
556 }
557
558 void PageClientImpl::stopAssistingNode()
559 {
560     [m_contentView _stopAssistingNode];
561 }
562
563 void PageClientImpl::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
564 {
565     [m_contentView _didUpdateBlockSelectionWithTouch:(SelectionTouch)touch withFlags:(SelectionFlags)flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
566 }
567
568 void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
569 {
570     [m_contentView _showPlaybackTargetPicker:hasVideo fromRect:elementRect];
571 }
572
573 bool PageClientImpl::handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, API::OpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener)
574 {
575     [m_contentView _showRunOpenPanel:parameters resultListener:listener];
576     return true;
577 }
578
579 void PageClientImpl::showInspectorHighlight(const WebCore::Highlight& highlight)
580 {
581     [m_contentView _showInspectorHighlight:highlight];
582 }
583
584 void PageClientImpl::hideInspectorHighlight()
585 {
586     [m_contentView _hideInspectorHighlight];
587 }
588
589 void PageClientImpl::showInspectorIndication()
590 {
591     [m_contentView setShowingInspectorIndication:YES];
592 }
593
594 void PageClientImpl::hideInspectorIndication()
595 {
596     [m_contentView setShowingInspectorIndication:NO];
597 }
598
599 void PageClientImpl::enableInspectorNodeSearch()
600 {
601     [m_contentView _enableInspectorNodeSearch];
602 }
603
604 void PageClientImpl::disableInspectorNodeSearch()
605 {
606     [m_contentView _disableInspectorNodeSearch];
607 }
608
609 #if ENABLE(FULLSCREEN_API)
610
611 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
612 {
613     return *this;
614 }
615
616 // WebFullScreenManagerProxyClient
617
618 void PageClientImpl::closeFullScreenManager()
619 {
620 }
621
622 bool PageClientImpl::isFullScreen()
623 {
624     return false;
625 }
626
627 void PageClientImpl::enterFullScreen()
628 {
629 }
630
631 void PageClientImpl::exitFullScreen()
632 {
633 }
634
635 void PageClientImpl::beganEnterFullScreen(const IntRect&, const IntRect&)
636 {
637 }
638
639 void PageClientImpl::beganExitFullScreen(const IntRect&, const IntRect&)
640 {
641 }
642
643 #endif // ENABLE(FULLSCREEN_API)
644
645 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
646 {
647     RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytes:dataReference.data() length:dataReference.size()]);
648     [m_webView _didFinishLoadingDataForCustomContentProviderWithSuggestedFilename:suggestedFilename data:data.get()];
649 }
650
651 void PageClientImpl::zoomToRect(FloatRect rect, double minimumScale, double maximumScale)
652 {
653     [m_contentView _zoomToRect:rect withOrigin:rect.center() fitEntireRect:YES minimumScale:minimumScale maximumScale:maximumScale minimumScrollDistance:0];
654 }
655
656 void PageClientImpl::overflowScrollViewWillStartPanGesture()
657 {
658     [m_contentView scrollViewWillStartPanOrPinchGesture];
659 }
660
661 void PageClientImpl::overflowScrollViewDidScroll()
662 {
663     [m_contentView _didScroll];
664 }
665
666 void PageClientImpl::overflowScrollWillStartScroll()
667 {
668     [m_contentView _overflowScrollingWillBegin];
669 }
670
671 void PageClientImpl::overflowScrollDidEndScroll()
672 {
673     [m_contentView _overflowScrollingDidEnd];
674 }
675
676 Vector<String> PageClientImpl::mimeTypesWithCustomContentProviders()
677 {
678     return m_webView._contentProviderRegistry._mimeTypesWithCustomContentProviders;
679 }
680
681 void PageClientImpl::navigationGestureDidBegin()
682 {
683     [m_webView _navigationGestureDidBegin];
684     NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidBegin();
685 }
686
687 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
688 {
689     NavigationState::fromWebPage(*m_webView->_page).navigationGestureWillEnd(willNavigate, item);
690 }
691
692 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
693 {
694     NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidEnd(willNavigate, item);
695     [m_webView _navigationGestureDidEnd];
696 }
697
698 void PageClientImpl::navigationGestureDidEnd()
699 {
700     [m_webView _navigationGestureDidEnd];
701 }
702
703 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
704 {
705     NavigationState::fromWebPage(*m_webView->_page).willRecordNavigationSnapshot(item);
706 }
707
708 void PageClientImpl::didRemoveNavigationGestureSnapshot()
709 {
710     NavigationState::fromWebPage(*m_webView->_page).navigationGestureSnapshotWasRemoved();
711 }
712
713 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
714 {
715 }
716
717 void PageClientImpl::didFinishLoadForMainFrame()
718 {
719     [m_webView _didFinishLoadForMainFrame];
720 }
721
722 void PageClientImpl::didFailLoadForMainFrame()
723 {
724     [m_webView _didFailLoadForMainFrame];
725 }
726
727 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType navigationType)
728 {
729     [m_webView _didSameDocumentNavigationForMainFrame:navigationType];
730 }
731
732 void PageClientImpl::didChangeBackgroundColor()
733 {
734     [m_webView _updateScrollViewBackground];
735 }
736
737 void PageClientImpl::refView()
738 {
739     [m_contentView retain];
740     [m_webView retain];
741 }
742
743 void PageClientImpl::derefView()
744 {
745     [m_contentView release];
746     [m_webView release];
747 }
748
749 void PageClientImpl::didRestoreScrollPosition()
750 {
751 }
752
753 WebCore::UserInterfaceLayoutDirection PageClientImpl::userInterfaceLayoutDirection()
754 {
755     if (!m_webView)
756         return WebCore::UserInterfaceLayoutDirection::LTR;
757     return ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:[m_webView semanticContentAttribute]] == UIUserInterfaceLayoutDirectionLeftToRight) ? WebCore::UserInterfaceLayoutDirection::LTR : WebCore::UserInterfaceLayoutDirection::RTL;
758 }
759
760 Ref<ValidationBubble> PageClientImpl::createValidationBubble(const String& message)
761 {
762     return ValidationBubble::create(m_contentView, message);
763 }
764
765 #if ENABLE(DATA_INTERACTION)
766 void PageClientImpl::didPerformDataInteractionControllerOperation()
767 {
768     [m_contentView _didPerformDataInteractionControllerOperation];
769 }
770
771 void PageClientImpl::startDataInteractionWithImage(const IntPoint& clientPosition, const ShareableBitmap::Handle& image, bool isLink)
772 {
773     [m_contentView _startDataInteractionWithImage:ShareableBitmap::create(image)->makeCGImageCopy() atClientPosition:CGPointMake(clientPosition.x(), clientPosition.y()) isLink:isLink];
774 }
775 #endif
776
777 void PageClientImpl::handleActiveNowPlayingSessionInfoResponse(bool hasActiveSession, const String& title, double duration, double elapsedTime)
778 {
779     [m_webView _handleActiveNowPlayingSessionInfoResponse:hasActiveSession title:nsStringFromWebCoreString(title) duration:duration elapsedTime:elapsedTime];
780 }
781
782 void PageClientImpl::requestPasswordForQuickLookDocument(const String& fileName, std::function<void(const String&)>&& completionHandler)
783 {
784     auto passwordHandler = [completionHandler = WTFMove(completionHandler)](NSString *password) {
785         completionHandler(password);
786     };
787
788     if (WKPasswordView *passwordView = m_webView._passwordView) {
789         ASSERT(fileName == String { passwordView.documentName });
790         [passwordView showPasswordFailureAlert];
791         passwordView.userDidEnterPassword = passwordHandler;
792     } else
793         [m_webView _showPasswordViewWithDocumentName:fileName passwordHandler:passwordHandler];
794 }
795
796 } // namespace WebKit
797
798 #endif // PLATFORM(IOS)