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