[iOS] Replace "node assistance" terminology in WebKit with "focused element"
[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     return (isViewInWindow() && ![m_webView _isBackground] && [m_webView _contentViewIsFirstResponder]) || [m_webView _isRetainingActiveFocusedState];
170 }
171
172 bool PageClientImpl::isViewVisible()
173 {
174     if (isViewInWindow() && ![m_webView _isBackground])
175         return true;
176     
177     if ([m_webView _isShowingVideoPictureInPicture])
178         return true;
179     
180     if ([m_webView _mayAutomaticallyShowVideoPictureInPicture])
181         return true;
182     
183     return false;
184 }
185
186 bool PageClientImpl::isViewInWindow()
187 {
188     // FIXME: in WebKitTestRunner, m_webView is nil, so check the content view instead.
189     if (auto webView = m_webView.get())
190         return [webView window];
191
192     return [m_contentView window];
193 }
194
195 bool PageClientImpl::isViewVisibleOrOccluded()
196 {
197     return isViewVisible();
198 }
199
200 bool PageClientImpl::isVisuallyIdle()
201 {
202     return !isViewVisible();
203 }
204
205 void PageClientImpl::processDidExit()
206 {
207     [m_contentView _processDidExit];
208     [m_webView _processDidExit];
209 }
210
211 void PageClientImpl::processWillSwap()
212 {
213     [m_contentView _processWillSwap];
214     [m_webView _processWillSwap];
215 }
216
217 void PageClientImpl::didRelaunchProcess()
218 {
219     [m_contentView _didRelaunchProcess];
220     [m_webView _didRelaunchProcess];
221 }
222
223 void PageClientImpl::pageClosed()
224 {
225     notImplemented();
226 }
227
228 void PageClientImpl::preferencesDidChange()
229 {
230     notImplemented();
231 }
232
233 void PageClientImpl::toolTipChanged(const String&, const String&)
234 {
235     notImplemented();
236 }
237
238 void PageClientImpl::didNotHandleTapAsClick(const WebCore::IntPoint& point)
239 {
240     [m_contentView _didNotHandleTapAsClick:point];
241 }
242     
243 void PageClientImpl::didCompleteSyntheticClick()
244 {
245     [m_contentView _didCompleteSyntheticClick];
246 }
247
248 void PageClientImpl::decidePolicyForGeolocationPermissionRequest(WebFrameProxy& frame, API::SecurityOrigin& origin, Function<void(bool)>& completionHandler)
249 {
250     [[wrapper(m_webView.get()->_page->process().processPool()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:origin.securityOrigin() frame:frame completionHandler:std::exchange(completionHandler, nullptr) view:m_webView.get().get()];
251 }
252
253 void PageClientImpl::didStartProvisionalLoadForMainFrame()
254 {
255     [m_webView _didStartProvisionalLoadForMainFrame];
256     [m_webView _hidePasswordView];
257 }
258
259 void PageClientImpl::didFailProvisionalLoadForMainFrame()
260 {
261     [m_webView _hidePasswordView];
262 }
263
264 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
265 {
266     [m_webView _hidePasswordView];
267     [m_webView _setHasCustomContentView:useCustomContentProvider loadedMIMEType:mimeType];
268     [m_contentView _didCommitLoadForMainFrame];
269 }
270
271 void PageClientImpl::handleDownloadRequest(DownloadProxy*)
272 {
273 }
274
275 void PageClientImpl::didChangeContentSize(const WebCore::IntSize&)
276 {
277     notImplemented();
278 }
279
280 void PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
281 {
282     [m_contentView _disableDoubleTapGesturesDuringTapIfNecessary:requestID];
283 }
284
285 double PageClientImpl::minimumZoomScale() const
286 {
287     if (UIScrollView *scroller = [m_webView scrollView])
288         return scroller.minimumZoomScale;
289
290     return 1;
291 }
292
293 WebCore::FloatRect PageClientImpl::documentRect() const
294 {
295     return [m_contentView bounds];
296 }
297
298 void PageClientImpl::setCursor(const Cursor&)
299 {
300     notImplemented();
301 }
302
303 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool)
304 {
305     notImplemented();
306 }
307
308 void PageClientImpl::didChangeViewportProperties(const ViewportAttributes&)
309 {
310     notImplemented();
311 }
312
313 void PageClientImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo)
314 {
315     RetainPtr<WKEditCommandObjC> commandObjC = adoptNS([[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command.copyRef()]);
316     String actionName = WebEditCommandProxy::nameForEditAction(command->editAction());
317     
318     NSUndoManager *undoManager = [m_contentView undoManager];
319     [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == UndoOrRedo::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
320     if (!actionName.isEmpty())
321         [undoManager setActionName:(NSString *)actionName];
322 }
323
324 #if USE(INSERTION_UNDO_GROUPING)
325 void PageClientImpl::registerInsertionUndoGrouping()
326 {
327     notImplemented();
328 }
329 #endif
330
331 void PageClientImpl::clearAllEditCommands()
332 {
333     [[m_contentView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
334 }
335
336 bool PageClientImpl::canUndoRedo(UndoOrRedo undoOrRedo)
337 {
338     return (undoOrRedo == UndoOrRedo::Undo) ? [[m_contentView undoManager] canUndo] : [[m_contentView undoManager] canRedo];
339 }
340
341 void PageClientImpl::executeUndoRedo(UndoOrRedo undoOrRedo)
342 {
343     return (undoOrRedo == UndoOrRedo::Undo) ? [[m_contentView undoManager] undo] : [[m_contentView undoManager] redo];
344 }
345
346 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
347 {
348     NSData *remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
349     [m_contentView _setAccessibilityWebProcessToken:remoteToken];
350 }
351
352 bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, bool isCharEvent)
353 {
354     return [m_contentView _interpretKeyEvent:event.nativeEvent() isCharEvent:isCharEvent];
355 }
356
357 void PageClientImpl::positionInformationDidChange(const InteractionInformationAtPosition& info)
358 {
359     [m_contentView _positionInformationDidChange:info];
360 }
361
362 void PageClientImpl::saveImageToLibrary(Ref<SharedBuffer>&& imageBuffer)
363 {
364     RetainPtr<NSData> imageData = imageBuffer->createNSData();
365     UIImageDataWriteToSavedPhotosAlbum(imageData.get(), nil, NULL, NULL);
366 }
367
368 bool PageClientImpl::executeSavedCommandBySelector(const String&)
369 {
370     notImplemented();
371     return false;
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::assistiveTechnologyMakeFirstResponder()
395 {
396     notImplemented();
397 }
398
399 void PageClientImpl::makeFirstResponder()
400 {
401     notImplemented();
402 }
403
404 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
405 {
406     notImplemented();
407     return FloatRect();
408 }
409
410 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
411 {
412     notImplemented();
413     return FloatRect();
414 }
415
416 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
417 {
418     return IntPoint([m_contentView convertPoint:point fromView:nil]);
419 }
420
421 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
422 {
423     return enclosingIntRect([m_contentView convertRect:rect toView:nil]);
424 }
425     
426 IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
427 {
428     CGPoint rootViewPoint = point;
429     if ([m_contentView respondsToSelector:@selector(accessibilityConvertPointFromSceneReferenceCoordinates:)])
430         rootViewPoint = [m_contentView accessibilityConvertPointFromSceneReferenceCoordinates:rootViewPoint];
431     return IntPoint(rootViewPoint);
432 }
433     
434 IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
435 {
436     CGRect rootViewRect = rect;
437     if ([m_contentView respondsToSelector:@selector(accessibilityConvertRectToSceneReferenceCoordinates:)])
438         rootViewRect = [m_contentView accessibilityConvertRectToSceneReferenceCoordinates:rootViewRect];
439     return enclosingIntRect(rootViewRect);
440 }
441     
442 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
443 {
444     [m_contentView _didHandleKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
445 }
446
447 #if ENABLE(TOUCH_EVENTS)
448 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& nativeWebtouchEvent, bool eventHandled)
449 {
450     [m_contentView _webTouchEvent:nativeWebtouchEvent preventsNativeGestures:eventHandled];
451 }
452 #endif
453
454 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy&)
455 {
456     return nullptr;
457 }
458
459 void PageClientImpl::setTextIndicator(Ref<TextIndicator> textIndicator, TextIndicatorWindowLifetime)
460 {
461 }
462
463 void PageClientImpl::clearTextIndicator(TextIndicatorWindowDismissalAnimation)
464 {
465 }
466
467 void PageClientImpl::setTextIndicatorAnimationProgress(float)
468 {
469 }
470
471 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
472 {
473 }
474
475 void PageClientImpl::showSafeBrowsingWarning(const SafeBrowsingWarning& warning, CompletionHandler<void(Variant<WebKit::ContinueUnsafeLoad, URL>&&)>&& completionHandler)
476 {
477     if (auto webView = m_webView.get())
478         [webView _showSafeBrowsingWarning:warning completionHandler:WTFMove(completionHandler)];
479     else
480         completionHandler(ContinueUnsafeLoad::No);
481 }
482
483 void PageClientImpl::clearSafeBrowsingWarning()
484 {
485     [m_webView _clearSafeBrowsingWarning];
486 }
487
488 void PageClientImpl::clearSafeBrowsingWarningIfForMainFrameNavigation()
489 {
490     [m_webView _clearSafeBrowsingWarningIfForMainFrameNavigation];
491 }
492
493 void PageClientImpl::exitAcceleratedCompositingMode()
494 {
495     notImplemented();
496 }
497
498 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&)
499 {
500 }
501
502 void PageClientImpl::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
503 {
504     [m_contentView _setAcceleratedCompositingRootView:rootNode ? rootNode->uiView() : nil];
505 }
506
507 CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
508 {
509     notImplemented();
510     return nullptr;
511 }
512
513 RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
514 {
515     return [m_webView _takeViewSnapshot];
516 }
517
518 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
519 {
520     notImplemented();
521 }
522
523 void PageClientImpl::commitPotentialTapFailed()
524 {
525     [m_contentView _commitPotentialTapFailed];
526 }
527
528 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)
529 {
530     [m_contentView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
531 }
532
533 void PageClientImpl::didCommitLayerTree(const RemoteLayerTreeTransaction& layerTreeTransaction)
534 {
535     [m_contentView _didCommitLayerTree:layerTreeTransaction];
536 }
537
538 void PageClientImpl::layerTreeCommitComplete()
539 {
540     [m_contentView _layerTreeCommitComplete];
541 }
542
543 void PageClientImpl::couldNotRestorePageState()
544 {
545     [m_webView _couldNotRestorePageState];
546 }
547
548 void PageClientImpl::restorePageState(Optional<WebCore::FloatPoint> scrollPosition, const WebCore::FloatPoint& scrollOrigin, const WebCore::FloatBoxExtent& obscuredInsetsOnSave, double scale)
549 {
550     [m_webView _restorePageScrollPosition:scrollPosition scrollOrigin:scrollOrigin previousObscuredInset:obscuredInsetsOnSave scale:scale];
551 }
552
553 void PageClientImpl::restorePageCenterAndScale(Optional<WebCore::FloatPoint> center, double scale)
554 {
555     [m_webView _restorePageStateToUnobscuredCenter:center scale:scale];
556 }
557
558 void PageClientImpl::elementDidFocus(const FocusedElementInformation& nodeInformation, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, API::Object* userData)
559 {
560     MESSAGE_CHECK(!userData || userData->type() == API::Object::Type::Data);
561
562     NSObject <NSSecureCoding> *userObject = nil;
563     if (API::Data* data = static_cast<API::Data*>(userData)) {
564         auto nsData = adoptNS([[NSData alloc] initWithBytesNoCopy:const_cast<void*>(static_cast<const void*>(data->bytes())) length:data->size() freeWhenDone:NO]);
565         auto unarchiver = secureUnarchiverFromData(nsData.get());
566         @try {
567             userObject = [unarchiver decodeObjectOfClass:[NSObject class] forKey:@"userObject"];
568         } @catch (NSException *exception) {
569             LOG_ERROR("Failed to decode user data: %@", exception);
570         }
571     }
572
573     [m_contentView _elementDidFocus:nodeInformation userIsInteracting:userIsInteracting blurPreviousNode:blurPreviousNode changingActivityState:changingActivityState userObject:userObject];
574 }
575
576 bool PageClientImpl::isFocusingElement()
577 {
578     return [m_contentView isFocusingElement];
579 }
580
581 void PageClientImpl::elementDidBlur()
582 {
583     [m_contentView _elementDidBlur];
584 }
585
586 void PageClientImpl::didReceiveEditorStateUpdateAfterFocus()
587 {
588     [m_contentView _didReceiveEditorStateUpdateAfterFocus];
589 }
590
591 void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
592 {
593     [m_contentView _showPlaybackTargetPicker:hasVideo fromRect:elementRect routeSharingPolicy:policy routingContextUID:contextUID];
594 }
595
596 bool PageClientImpl::handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, API::OpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener)
597 {
598     [m_contentView _showRunOpenPanel:parameters resultListener:listener];
599     return true;
600 }
601
602 bool PageClientImpl::showShareSheet(const ShareDataWithParsedURL& shareData, WTF::CompletionHandler<void(bool)>&& completionHandler)
603 {
604     [m_contentView _showShareSheet:shareData completionHandler:WTFMove(completionHandler)];
605     return true;
606 }
607
608 void PageClientImpl::showInspectorHighlight(const WebCore::Highlight& highlight)
609 {
610     [m_contentView _showInspectorHighlight:highlight];
611 }
612
613 void PageClientImpl::hideInspectorHighlight()
614 {
615     [m_contentView _hideInspectorHighlight];
616 }
617
618 void PageClientImpl::showInspectorIndication()
619 {
620     [m_contentView setShowingInspectorIndication:YES];
621 }
622
623 void PageClientImpl::hideInspectorIndication()
624 {
625     [m_contentView setShowingInspectorIndication:NO];
626 }
627
628 void PageClientImpl::enableInspectorNodeSearch()
629 {
630     [m_contentView _enableInspectorNodeSearch];
631 }
632
633 void PageClientImpl::disableInspectorNodeSearch()
634 {
635     [m_contentView _disableInspectorNodeSearch];
636 }
637
638 #if ENABLE(FULLSCREEN_API)
639
640 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
641 {
642     return *this;
643 }
644
645 // WebFullScreenManagerProxyClient
646
647 void PageClientImpl::closeFullScreenManager()
648 {
649     [m_webView closeFullScreenWindowController];
650 }
651
652 bool PageClientImpl::isFullScreen()
653 {
654     if (![m_webView hasFullScreenWindowController])
655         return false;
656
657     return [m_webView fullScreenWindowController].isFullScreen;
658 }
659
660 void PageClientImpl::enterFullScreen()
661 {
662     [[m_webView fullScreenWindowController] enterFullScreen];
663 }
664
665 void PageClientImpl::exitFullScreen()
666 {
667     [[m_webView fullScreenWindowController] exitFullScreen];
668 }
669
670 void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
671 {
672     [[m_webView fullScreenWindowController] beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
673 }
674
675 void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
676 {
677     [[m_webView fullScreenWindowController] beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
678 }
679
680 #endif // ENABLE(FULLSCREEN_API)
681
682 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
683 {
684     RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytes:dataReference.data() length:dataReference.size()]);
685     [m_webView _didFinishLoadingDataForCustomContentProviderWithSuggestedFilename:suggestedFilename data:data.get()];
686 }
687
688 void PageClientImpl::scrollingNodeScrollViewWillStartPanGesture()
689 {
690     [m_contentView scrollViewWillStartPanOrPinchGesture];
691 }
692
693 void PageClientImpl::scrollingNodeScrollViewDidScroll()
694 {
695     [m_contentView _didScroll];
696 }
697
698 void PageClientImpl::scrollingNodeScrollWillStartScroll()
699 {
700     [m_contentView _scrollingNodeScrollingWillBegin];
701 }
702
703 void PageClientImpl::scrollingNodeScrollDidEndScroll()
704 {
705     [m_contentView _scrollingNodeScrollingDidEnd];
706 }
707
708 Vector<String> PageClientImpl::mimeTypesWithCustomContentProviders()
709 {
710     return [m_webView _contentProviderRegistry]._mimeTypesWithCustomContentProviders;
711 }
712
713 void PageClientImpl::navigationGestureDidBegin()
714 {
715     [m_webView _navigationGestureDidBegin];
716     NavigationState::fromWebPage(*m_webView.get()->_page).navigationGestureDidBegin();
717 }
718
719 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
720 {
721     NavigationState::fromWebPage(*m_webView.get()->_page).navigationGestureWillEnd(willNavigate, item);
722 }
723
724 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
725 {
726     NavigationState::fromWebPage(*m_webView.get()->_page).navigationGestureDidEnd(willNavigate, item);
727     [m_webView _navigationGestureDidEnd];
728 }
729
730 void PageClientImpl::navigationGestureDidEnd()
731 {
732     [m_webView _navigationGestureDidEnd];
733 }
734
735 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
736 {
737     NavigationState::fromWebPage(*m_webView.get()->_page).willRecordNavigationSnapshot(item);
738 }
739
740 void PageClientImpl::didRemoveNavigationGestureSnapshot()
741 {
742     NavigationState::fromWebPage(*m_webView.get()->_page).navigationGestureSnapshotWasRemoved();
743 }
744
745 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
746 {
747 }
748
749 void PageClientImpl::didFinishLoadForMainFrame()
750 {
751     [m_webView _didFinishLoadForMainFrame];
752 }
753
754 void PageClientImpl::didFailLoadForMainFrame()
755 {
756     [m_webView _didFailLoadForMainFrame];
757 }
758
759 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType navigationType)
760 {
761     [m_webView _didSameDocumentNavigationForMainFrame:navigationType];
762 }
763
764 void PageClientImpl::didChangeBackgroundColor()
765 {
766     [m_webView _updateScrollViewBackground];
767 }
768
769 void PageClientImpl::videoControlsManagerDidChange()
770 {
771     [m_webView _videoControlsManagerDidChange];
772 }
773
774 void PageClientImpl::refView()
775 {
776     [m_contentView retain];
777     [m_webView retain];
778 }
779
780 void PageClientImpl::derefView()
781 {
782     [m_contentView release];
783     [m_webView release];
784 }
785
786 void PageClientImpl::didRestoreScrollPosition()
787 {
788 }
789
790 WebCore::UserInterfaceLayoutDirection PageClientImpl::userInterfaceLayoutDirection()
791 {
792     if (!m_webView)
793         return WebCore::UserInterfaceLayoutDirection::LTR;
794     return ([UIView userInterfaceLayoutDirectionForSemanticContentAttribute:[m_webView semanticContentAttribute]] == UIUserInterfaceLayoutDirectionLeftToRight) ? WebCore::UserInterfaceLayoutDirection::LTR : WebCore::UserInterfaceLayoutDirection::RTL;
795 }
796
797 Ref<ValidationBubble> PageClientImpl::createValidationBubble(const String& message, const ValidationBubble::Settings& settings)
798 {
799     return ValidationBubble::create(m_contentView, message, settings);
800 }
801
802 #if ENABLE(INPUT_TYPE_COLOR)
803 RefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy*, const WebCore::Color& initialColor, const WebCore::IntRect&, Vector<WebCore::Color>&&)
804 {
805     return nullptr;
806 }
807 #endif
808
809 #if ENABLE(DATALIST_ELEMENT)
810 RefPtr<WebDataListSuggestionsDropdown> PageClientImpl::createDataListSuggestionsDropdown(WebPageProxy& page)
811 {
812     return WebDataListSuggestionsDropdownIOS::create(page, m_contentView);
813 }
814 #endif
815
816 #if ENABLE(DATA_INTERACTION)
817 void PageClientImpl::didPerformDragOperation(bool handled)
818 {
819     [m_contentView _didPerformDragOperation:handled];
820 }
821
822 void PageClientImpl::didHandleStartDataInteractionRequest(bool started)
823 {
824     [m_contentView _didHandleStartDataInteractionRequest:started];
825 }
826
827 void PageClientImpl::didHandleAdditionalDragItemsRequest(bool added)
828 {
829     [m_contentView _didHandleAdditionalDragItemsRequest:added];
830 }
831
832 void PageClientImpl::startDrag(const DragItem& item, const ShareableBitmap::Handle& image)
833 {
834     [m_contentView _startDrag:ShareableBitmap::create(image)->makeCGImageCopy() item:item];
835 }
836
837 void PageClientImpl::didConcludeEditDataInteraction(Optional<TextIndicatorData> data)
838 {
839     [m_contentView _didConcludeEditDataInteraction:data];
840 }
841
842 void PageClientImpl::didChangeDataInteractionCaretRect(const IntRect& previousCaretRect, const IntRect& caretRect)
843 {
844     [m_contentView _didChangeDataInteractionCaretRect:previousCaretRect currentRect:caretRect];
845 }
846 #endif
847
848 #if USE(QUICK_LOOK)
849 void PageClientImpl::requestPasswordForQuickLookDocument(const String& fileName, WTF::Function<void(const String&)>&& completionHandler)
850 {
851     auto passwordHandler = makeBlockPtr([completionHandler = WTFMove(completionHandler)](NSString *password) {
852         completionHandler(password);
853     });
854
855     if (WKPasswordView *passwordView = [m_webView _passwordView]) {
856         ASSERT(fileName == String { passwordView.documentName });
857         [passwordView showPasswordFailureAlert];
858         passwordView.userDidEnterPassword = passwordHandler.get();
859         return;
860     }
861
862     [m_webView _showPasswordViewWithDocumentName:fileName passwordHandler:passwordHandler.get()];
863     NavigationState::fromWebPage(*m_webView.get()->_page).didRequestPasswordForQuickLookDocument();
864 }
865 #endif
866
867 } // namespace WebKit
868
869 #endif // PLATFORM(IOS_FAMILY)
870
871 #undef MESSAGE_CHECK