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