[iOS] Implement safe browsing in WebKit
[WebKit-https.git] / Source / WebKit / UIProcess / mac / PageClientImplMac.mm
1 /*
2  * Copyright (C) 2010-2018 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 "PageClientImplMac.h"
28
29 #if PLATFORM(MAC)
30
31 #import "APIHitTestResult.h"
32 #import "ColorSpaceData.h"
33 #import "DataReference.h"
34 #import "DownloadProxy.h"
35 #import "DrawingAreaProxy.h"
36 #import "Logging.h"
37 #import "NativeWebGestureEvent.h"
38 #import "NativeWebKeyboardEvent.h"
39 #import "NativeWebMouseEvent.h"
40 #import "NativeWebWheelEvent.h"
41 #import "NavigationState.h"
42 #import "StringUtilities.h"
43 #import "UndoOrRedo.h"
44 #import "ViewGestureController.h"
45 #import "ViewSnapshotStore.h"
46 #import "WKAPICast.h"
47 #import "WKFullScreenWindowController.h"
48 #import "WKStringCF.h"
49 #import "WKViewInternal.h"
50 #import "WKWebViewInternal.h"
51 #import "WebColorPickerMac.h"
52 #import "WebContextMenuProxyMac.h"
53 #import "WebDataListSuggestionsDropdownMac.h"
54 #import "WebEditCommandProxy.h"
55 #import "WebPageProxy.h"
56 #import "WebPopupMenuProxyMac.h"
57 #import "WebViewImpl.h"
58 #import "WindowServerConnection.h"
59 #import "_WKDownloadInternal.h"
60 #import "_WKHitTestResultInternal.h"
61 #import "_WKThumbnailView.h"
62 #import <WebCore/AlternativeTextUIController.h>
63 #import <WebCore/BitmapImage.h>
64 #import <WebCore/Cursor.h>
65 #import <WebCore/DictionaryLookup.h>
66 #import <WebCore/DragItem.h>
67 #import <WebCore/FloatRect.h>
68 #import <WebCore/GraphicsContext.h>
69 #import <WebCore/Image.h>
70 #import <WebCore/KeyboardEvent.h>
71 #import <WebCore/NotImplemented.h>
72 #import <WebCore/PlatformScreen.h>
73 #import <WebCore/PromisedAttachmentInfo.h>
74 #import <WebCore/SharedBuffer.h>
75 #import <WebCore/TextIndicator.h>
76 #import <WebCore/TextIndicatorWindow.h>
77 #import <WebCore/TextUndoInsertionMarkupMac.h>
78 #import <WebCore/ValidationBubble.h>
79 #import <WebCore/WebCoreCALayerExtras.h>
80 #import <wtf/ProcessPrivilege.h>
81 #import <wtf/text/CString.h>
82 #import <wtf/text/WTFString.h>
83
84 #if USE(DICTATION_ALTERNATIVES)
85 #import <AppKit/NSTextAlternatives.h>
86 #endif
87
88 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
89 #include <WebCore/WebMediaSessionManager.h>
90 #endif
91
92 @interface NSApplication (WebNSApplicationDetails)
93 - (NSCursor *)_cursorRectCursor;
94 @end
95
96 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
97 @interface NSWindow (WebNSWindowDetails)
98 - (BOOL)_hostsLayersInWindowServer;
99 @end
100 #endif
101
102 namespace WebKit {
103 using namespace WebCore;
104
105 PageClientImpl::PageClientImpl(NSView* view, WKWebView *webView)
106     : PageClientImplCocoa(webView)
107     , m_view(view)
108 #if USE(DICTATION_ALTERNATIVES)
109     , m_alternativeTextUIController(std::make_unique<AlternativeTextUIController>())
110 #endif
111 {
112 #if !WK_API_ENABLED
113     ASSERT_UNUSED(m_webView, !m_webView);
114 #endif
115 }
116
117 PageClientImpl::~PageClientImpl()
118 {
119 }
120
121 void PageClientImpl::setImpl(WebViewImpl& impl)
122 {
123     m_impl = makeWeakPtr(impl);
124 }
125
126 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
127 {
128     return m_impl->createDrawingAreaProxy();
129 }
130
131 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region&)
132 {
133     ASSERT_NOT_REACHED();
134 }
135
136 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin, bool isProgrammaticScroll)
137 {
138 }
139
140 WebCore::FloatPoint PageClientImpl::viewScrollPosition()
141 {
142     return { };
143 }
144
145 IntSize PageClientImpl::viewSize()
146 {
147     return IntSize([m_view bounds].size);
148 }
149
150 NSView *PageClientImpl::activeView() const
151 {
152 #if WK_API_ENABLED
153     return (m_impl && m_impl->thumbnailView()) ? (NSView *)m_impl->thumbnailView() : m_view;
154 #else
155     return m_view;
156 #endif
157 }
158
159 NSWindow *PageClientImpl::activeWindow() const
160 {
161 #if WK_API_ENABLED
162     if (m_impl && m_impl->thumbnailView())
163         return m_impl->thumbnailView().window;
164 #endif
165     if (m_impl && m_impl->targetWindowForMovePreparation())
166         return m_impl->targetWindowForMovePreparation();
167     return m_view.window;
168 }
169
170 bool PageClientImpl::isViewWindowActive()
171 {
172     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
173     NSWindow *activeViewWindow = activeWindow();
174     return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
175 }
176
177 bool PageClientImpl::isViewFocused()
178 {
179     // FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl.
180     // Once WebViewImpl and PageClient merge, this won't be a problem.
181     if (!m_impl)
182         return NO;
183
184     return m_impl->isFocused();
185 }
186
187 void PageClientImpl::assistiveTechnologyMakeFirstResponder()
188 {
189     [[m_view window] makeFirstResponder:m_view];
190 }
191     
192 void PageClientImpl::makeFirstResponder()
193 {
194     if (m_shouldSuppressFirstResponderChanges)
195         return;
196
197     [[m_view window] makeFirstResponder:m_view];
198 }
199     
200 bool PageClientImpl::isViewVisible()
201 {
202     NSView *activeView = this->activeView();
203     NSWindow *activeViewWindow = activeWindow();
204
205     auto windowIsOccluded = [&]()->bool {
206         return m_impl && m_impl->windowOcclusionDetectionEnabled() && (activeViewWindow.occlusionState & NSWindowOcclusionStateVisible) != NSWindowOcclusionStateVisible;
207     };
208
209     LOG_WITH_STREAM(ActivityState, stream << "PageClientImpl " << this << " isViewVisible(): activeViewWindow " << activeViewWindow
210         << " (window visible " << activeViewWindow.isVisible << ", view hidden " << activeView.isHiddenOrHasHiddenAncestor << ", window occluded " << windowIsOccluded() << ")");
211
212     if (!activeViewWindow)
213         return false;
214
215     if (!activeViewWindow.isVisible)
216         return false;
217
218     if (activeView.isHiddenOrHasHiddenAncestor)
219         return false;
220
221     if (windowIsOccluded())
222         return false;
223
224     return true;
225 }
226
227 bool PageClientImpl::isViewVisibleOrOccluded()
228 {
229     return activeWindow().isVisible;
230 }
231
232 bool PageClientImpl::isViewInWindow()
233 {
234     return activeWindow();
235 }
236
237 bool PageClientImpl::isVisuallyIdle()
238 {
239     return WindowServerConnection::singleton().applicationWindowModificationsHaveStopped() || !isViewVisible();
240 }
241
242 LayerHostingMode PageClientImpl::viewLayerHostingMode()
243 {
244 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
245     if ([activeWindow() _hostsLayersInWindowServer])
246         return LayerHostingMode::OutOfProcess;
247 #endif
248     return LayerHostingMode::InProcess;
249 }
250
251 void PageClientImpl::viewWillMoveToAnotherWindow()
252 {
253     clearAllEditCommands();
254 }
255
256 ColorSpaceData PageClientImpl::colorSpace()
257 {
258     return m_impl->colorSpace();
259 }
260
261 void PageClientImpl::processWillSwap()
262 {
263     m_impl->processWillSwap();
264 }
265
266 void PageClientImpl::processDidExit()
267 {
268     m_impl->processDidExit();
269     m_impl->setAcceleratedCompositingRootLayer(nil);
270 }
271
272 void PageClientImpl::pageClosed()
273 {
274     m_impl->pageClosed();
275 #if USE(DICTATION_ALTERNATIVES)
276     m_alternativeTextUIController->clear();
277 #endif
278 }
279
280 void PageClientImpl::didRelaunchProcess()
281 {
282     m_impl->didRelaunchProcess();
283 }
284
285 void PageClientImpl::preferencesDidChange()
286 {
287     m_impl->preferencesDidChange();
288 }
289
290 void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
291 {
292     m_impl->toolTipChanged(oldToolTip, newToolTip);
293 }
294
295 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
296 {
297     m_impl->updateSupportsArbitraryLayoutModes();
298     m_impl->dismissContentRelativeChildWindowsWithAnimation(true);
299 }
300
301 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
302 {
303 }
304
305 void PageClientImpl::handleDownloadRequest(DownloadProxy*)
306 {
307 }
308
309 void PageClientImpl::didChangeContentSize(const WebCore::IntSize& newSize)
310 {
311     m_impl->didChangeContentSize(newSize);
312 }
313
314 void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
315 {
316     ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
317     // FIXME: Would be nice to share this code with WebKit1's WebChromeClient.
318
319     // The Web process may have asked to change the cursor when the view was in an active window, but
320     // if it is no longer in a window or the window is not active, then the cursor should not change.
321     if (!isViewWindowActive())
322         return;
323
324     if ([NSApp _cursorRectCursor])
325         return;
326
327     if (!m_view)
328         return;
329
330     NSWindow *window = [m_view window];
331     if (!window)
332         return;
333
334     if ([window windowNumber] != [NSWindow windowNumberAtPoint:[NSEvent mouseLocation] belowWindowWithWindowNumber:0])
335         return;
336
337     NSCursor *platformCursor = cursor.platformCursor();
338     if ([NSCursor currentCursor] == platformCursor)
339         return;
340
341     [platformCursor set];
342 }
343
344 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
345 {
346     [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
347 }
348
349 void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
350 {
351 }
352
353 void PageClientImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo)
354 {
355     m_impl->registerEditCommand(WTFMove(command), undoOrRedo);
356 }
357
358 #if USE(INSERTION_UNDO_GROUPING)
359 void PageClientImpl::registerInsertionUndoGrouping()
360 {
361     registerInsertionUndoGroupingWithUndoManager([m_view undoManager]);
362 }
363 #endif
364
365 void PageClientImpl::clearAllEditCommands()
366 {
367     m_impl->clearAllEditCommands();
368 }
369
370 bool PageClientImpl::canUndoRedo(UndoOrRedo undoOrRedo)
371 {
372     return (undoOrRedo == UndoOrRedo::Undo) ? [[m_view undoManager] canUndo] : [[m_view undoManager] canRedo];
373 }
374
375 void PageClientImpl::executeUndoRedo(UndoOrRedo undoOrRedo)
376 {
377     return (undoOrRedo == UndoOrRedo::Undo) ? [[m_view undoManager] undo] : [[m_view undoManager] redo];
378 }
379
380 void PageClientImpl::startDrag(const WebCore::DragItem& item, const ShareableBitmap::Handle& image)
381 {
382     m_impl->startDrag(item, image);
383 }
384
385 void PageClientImpl::setPromisedDataForImage(const String& pasteboardName, Ref<SharedBuffer>&& imageBuffer, const String& filename, const String& extension, const String& title, const String& url, const String& visibleURL, RefPtr<SharedBuffer>&& archiveBuffer)
386 {
387     RefPtr<Image> image = BitmapImage::create();
388     image->setData(WTFMove(imageBuffer), true);
389     m_impl->setPromisedDataForImage(image.get(), filename, extension, title, url, visibleURL, archiveBuffer.get(), pasteboardName);
390 }
391
392 void PageClientImpl::updateSecureInputState()
393 {
394     m_impl->updateSecureInputState();
395 }
396
397 void PageClientImpl::resetSecureInputState()
398 {
399     m_impl->resetSecureInputState();
400 }
401
402 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
403 {
404     m_impl->notifyInputContextAboutDiscardedComposition();
405 }
406
407 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
408 {
409     return toDeviceSpace(rect, [m_view window]);
410 }
411
412 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
413 {
414     return toUserSpace(rect, [m_view window]);
415 }
416
417 void PageClientImpl::pinnedStateWillChange()
418 {
419 #if WK_API_ENABLED
420     [m_webView willChangeValueForKey:@"_pinnedState"];
421 #endif
422 }
423
424 void PageClientImpl::pinnedStateDidChange()
425 {
426 #if WK_API_ENABLED
427     [m_webView didChangeValueForKey:@"_pinnedState"];
428 #endif
429 }
430     
431 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
432 {
433     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
434     NSPoint windowCoord = [[m_view window] convertScreenToBase:point];
435     ALLOW_DEPRECATED_DECLARATIONS_END
436     return IntPoint([m_view convertPoint:windowCoord fromView:nil]);
437 }
438     
439 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
440 {
441     NSRect tempRect = rect;
442     tempRect = [m_view convertRect:tempRect toView:nil];
443     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
444     tempRect.origin = [[m_view window] convertBaseToScreen:tempRect.origin];
445     ALLOW_DEPRECATED_DECLARATIONS_END
446     return enclosingIntRect(tempRect);
447 }
448
449 IntRect PageClientImpl::rootViewToWindow(const WebCore::IntRect& rect)
450 {
451     NSRect tempRect = rect;
452     tempRect = [m_view convertRect:tempRect toView:nil];
453     return enclosingIntRect(tempRect);
454 }
455
456 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
457 {
458     m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled);
459 }
460
461 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page)
462 {
463     return WebPopupMenuProxyMac::create(m_view, page);
464 }
465
466 #if ENABLE(CONTEXT_MENUS)
467 Ref<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
468 {
469     return WebContextMenuProxyMac::create(m_view, page, WTFMove(context), userData);
470 }
471 #endif
472
473 #if ENABLE(INPUT_TYPE_COLOR)
474 RefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& initialColor, const WebCore::IntRect& rect, Vector<WebCore::Color>&& suggestions)
475 {
476     return WebColorPickerMac::create(page, initialColor, rect, WTFMove(suggestions), m_view);
477 }
478 #endif
479
480 #if ENABLE(DATALIST_ELEMENT)
481 RefPtr<WebDataListSuggestionsDropdown> PageClientImpl::createDataListSuggestionsDropdown(WebPageProxy& page)
482 {
483     return WebDataListSuggestionsDropdownMac::create(page, m_view);
484 }
485 #endif
486
487 Ref<ValidationBubble> PageClientImpl::createValidationBubble(const String& message, const ValidationBubble::Settings& settings)
488 {
489     return ValidationBubble::create(m_view, message, settings);
490 }
491
492 void PageClientImpl::showSafeBrowsingWarning(const SafeBrowsingResult& result, CompletionHandler<void(Variant<WebKit::ContinueUnsafeLoad, WebCore::URL>&&)>&& completionHandler)
493 {
494     if (!m_impl)
495         return completionHandler(ContinueUnsafeLoad::Yes);
496     m_impl->showSafeBrowsingWarning(result, WTFMove(completionHandler));
497 }
498
499 void PageClientImpl::clearSafeBrowsingWarning()
500 {
501     m_impl->clearSafeBrowsingWarning();
502 }
503
504 void PageClientImpl::setTextIndicator(Ref<TextIndicator> textIndicator, WebCore::TextIndicatorWindowLifetime lifetime)
505 {
506     m_impl->setTextIndicator(textIndicator.get(), lifetime);
507 }
508
509 void PageClientImpl::clearTextIndicator(WebCore::TextIndicatorWindowDismissalAnimation dismissalAnimation)
510 {
511     m_impl->clearTextIndicatorWithAnimation(dismissalAnimation);
512 }
513
514 void PageClientImpl::setTextIndicatorAnimationProgress(float progress)
515 {
516     m_impl->setTextIndicatorAnimationProgress(progress);
517 }
518
519 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
520 {
521     m_impl->setAccessibilityWebProcessToken([NSData dataWithBytes:data.data() length:data.size()]);
522 }
523     
524 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
525 {
526     ASSERT(!layerTreeContext.isEmpty());
527
528     CALayer *renderLayer = [CALayer _web_renderLayerWithContextID:layerTreeContext.contextID];
529     m_impl->setAcceleratedCompositingRootLayer(renderLayer);
530 }
531
532 void PageClientImpl::exitAcceleratedCompositingMode()
533 {
534     m_impl->setAcceleratedCompositingRootLayer(nil);
535 }
536
537 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
538 {
539     ASSERT(!layerTreeContext.isEmpty());
540
541     CALayer *renderLayer = [CALayer _web_renderLayerWithContextID:layerTreeContext.contextID];
542     m_impl->setAcceleratedCompositingRootLayer(renderLayer);
543 }
544
545 void PageClientImpl::setAcceleratedCompositingRootLayer(CALayer *rootLayer)
546 {
547     m_impl->setAcceleratedCompositingRootLayer(rootLayer);
548 }
549
550 CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
551 {
552     return m_impl->acceleratedCompositingRootLayer();
553 }
554
555 RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
556 {
557     return m_impl->takeViewSnapshot();
558 }
559
560 void PageClientImpl::selectionDidChange()
561 {
562     m_impl->selectionDidChange();
563 }
564 #if WK_API_ENABLED
565 bool PageClientImpl::showShareSheet(const ShareDataWithParsedURL& shareData, WTF::CompletionHandler<void(bool)>&& completionHandler)
566 {
567     m_impl->showShareSheet(shareData, WTFMove(completionHandler), m_webView.get().get());
568     return true;
569 }
570 #endif
571
572 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
573 {
574     if (auto gestureController = m_impl->gestureController())
575         gestureController->wheelEventWasNotHandledByWebCore(event.nativeEvent());
576 }
577
578 #if ENABLE(MAC_GESTURE_EVENTS)
579 void PageClientImpl::gestureEventWasNotHandledByWebCore(const NativeWebGestureEvent& event)
580 {
581     m_impl->gestureEventWasNotHandledByWebCore(event.nativeEvent());
582 }
583 #endif
584
585 void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
586 {
587     m_impl->pluginFocusOrWindowFocusChanged(pluginHasFocusAndWindowHasFocus, pluginComplexTextInputIdentifier);
588 }
589
590 void PageClientImpl::setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, PluginComplexTextInputState pluginComplexTextInputState)
591 {
592     m_impl->setPluginComplexTextInputStateAndIdentifier(pluginComplexTextInputState, pluginComplexTextInputIdentifier);
593 }
594
595 void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
596 {
597     m_impl->prepareForDictionaryLookup();
598
599     DictionaryLookup::showPopup(dictionaryPopupInfo, m_view, [this](TextIndicator& textIndicator) {
600         m_impl->setTextIndicator(textIndicator, TextIndicatorWindowLifetime::Permanent);
601     }, nullptr, [this]() {
602         m_impl->clearTextIndicatorWithAnimation(WebCore::TextIndicatorWindowDismissalAnimation::None);
603     });
604 }
605
606 void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
607 {
608 #if USE(AUTOCORRECTION_PANEL)
609     if (!isViewVisible() || !isViewInWindow())
610         return;
611     m_correctionPanel.show(m_view, *m_impl, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
612 #endif
613 }
614
615 void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason)
616 {
617 #if USE(AUTOCORRECTION_PANEL)
618     m_correctionPanel.dismiss(reason);
619 #endif
620 }
621
622 String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason)
623 {
624 #if USE(AUTOCORRECTION_PANEL)
625     return m_correctionPanel.dismiss(reason);
626 #else
627     return String();
628 #endif
629 }
630
631 static inline NSCorrectionResponse toCorrectionResponse(AutocorrectionResponse response)
632 {
633     switch (response) {
634     case WebCore::AutocorrectionResponse::Reverted:
635         return NSCorrectionResponseReverted;
636     case WebCore::AutocorrectionResponse::Edited:
637         return NSCorrectionResponseEdited;
638     case WebCore::AutocorrectionResponse::Accepted:
639         return NSCorrectionResponseAccepted;
640     }
641
642     ASSERT_NOT_REACHED();
643     return NSCorrectionResponseAccepted;
644 }
645
646 void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponse response, const String& replacedString, const String& replacementString)
647 {
648     CorrectionPanel::recordAutocorrectionResponse(*m_impl, m_impl->spellCheckerDocumentTag(), toCorrectionResponse(response), replacedString, replacementString);
649 }
650
651 void PageClientImpl::recommendedScrollbarStyleDidChange(ScrollbarStyle newStyle)
652 {
653     // Now re-create a tracking area with the appropriate options given the new scrollbar style
654     NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingCursorUpdate;
655     if (newStyle == ScrollbarStyle::AlwaysVisible)
656         options |= NSTrackingActiveAlways;
657     else
658         options |= NSTrackingActiveInKeyWindow;
659
660     RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_view frame] options:options owner:m_view userInfo:nil]);
661     m_impl->setPrimaryTrackingArea(trackingArea.get());
662 }
663
664 void PageClientImpl::intrinsicContentSizeDidChange(const IntSize& intrinsicContentSize)
665 {
666     m_impl->setIntrinsicContentSize(intrinsicContentSize);
667 }
668
669 bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString)
670 {
671     return m_impl->executeSavedCommandBySelector(NSSelectorFromString(selectorString));
672 }
673
674 #if USE(DICTATION_ALTERNATIVES)
675 uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr<NSTextAlternatives>& alternatives)
676 {
677     return m_alternativeTextUIController->addAlternatives(alternatives);
678 }
679
680 void PageClientImpl::removeDictationAlternatives(uint64_t dictationContext)
681 {
682     m_alternativeTextUIController->removeAlternatives(dictationContext);
683 }
684
685 void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
686 {
687     if (!isViewVisible() || !isViewInWindow())
688         return;
689     m_alternativeTextUIController->showAlternatives(m_view, boundingBoxOfDictatedText, dictationContext, ^(NSString *acceptedAlternative) {
690         m_impl->handleAcceptedAlternativeText(acceptedAlternative);
691     });
692 }
693
694 Vector<String> PageClientImpl::dictationAlternatives(uint64_t dictationContext)
695 {
696     return m_alternativeTextUIController->alternativesForContext(dictationContext);
697 }
698 #endif
699
700 void PageClientImpl::setEditableElementIsFocused(bool editableElementIsFocused)
701 {
702     m_impl->setEditableElementIsFocused(editableElementIsFocused);
703 }
704
705 #if ENABLE(FULLSCREEN_API)
706
707 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
708 {
709     return *this;
710 }
711
712 // WebFullScreenManagerProxyClient
713
714 void PageClientImpl::closeFullScreenManager()
715 {
716     m_impl->closeFullScreenWindowController();
717 }
718
719 bool PageClientImpl::isFullScreen()
720 {
721     if (!m_impl->hasFullScreenWindowController())
722         return false;
723
724     return m_impl->fullScreenWindowController().isFullScreen;
725 }
726
727 void PageClientImpl::enterFullScreen()
728 {
729     [m_impl->fullScreenWindowController() enterFullScreen:nil];
730 }
731
732 void PageClientImpl::exitFullScreen()
733 {
734     [m_impl->fullScreenWindowController() exitFullScreen];
735 }
736
737 void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
738 {
739     [m_impl->fullScreenWindowController() beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
740     m_impl->updateSupportsArbitraryLayoutModes();
741 }
742
743 void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
744 {
745     [m_impl->fullScreenWindowController() beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
746     m_impl->updateSupportsArbitraryLayoutModes();
747 }
748
749 #endif // ENABLE(FULLSCREEN_API)
750
751 void PageClientImpl::navigationGestureDidBegin()
752 {
753     m_impl->dismissContentRelativeChildWindowsWithAnimation(true);
754
755 #if WK_API_ENABLED
756     if (auto webView = m_webView.get())
757         NavigationState::fromWebPage(*webView->_page).navigationGestureDidBegin();
758 #endif
759 }
760
761 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
762 {
763 #if WK_API_ENABLED
764     if (auto webView = m_webView.get())
765         NavigationState::fromWebPage(*webView->_page).navigationGestureWillEnd(willNavigate, item);
766 #else
767     UNUSED_PARAM(willNavigate);
768     UNUSED_PARAM(item);
769 #endif
770 }
771
772 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
773 {
774 #if WK_API_ENABLED
775     if (auto webView = m_webView.get())
776         NavigationState::fromWebPage(*webView->_page).navigationGestureDidEnd(willNavigate, item);
777 #else
778     UNUSED_PARAM(willNavigate);
779     UNUSED_PARAM(item);
780 #endif
781 }
782
783 void PageClientImpl::navigationGestureDidEnd()
784 {
785 }
786
787 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
788 {
789 #if WK_API_ENABLED
790     if (auto webView = m_webView.get())
791         NavigationState::fromWebPage(*webView->_page).willRecordNavigationSnapshot(item);
792 #else
793     UNUSED_PARAM(item);
794 #endif
795 }
796
797 void PageClientImpl::didRemoveNavigationGestureSnapshot()
798 {
799 #if WK_API_ENABLED
800     if (auto webView = m_webView.get())
801         NavigationState::fromWebPage(*webView->_page).navigationGestureSnapshotWasRemoved();
802 #endif
803 }
804
805 void PageClientImpl::didStartProvisionalLoadForMainFrame()
806 {
807     if (auto gestureController = m_impl->gestureController())
808         gestureController->didStartProvisionalLoadForMainFrame();
809 }
810
811 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
812 {
813     if (auto gestureController = m_impl->gestureController())
814         gestureController->didFirstVisuallyNonEmptyLayoutForMainFrame();
815 }
816
817 void PageClientImpl::didFinishLoadForMainFrame()
818 {
819     if (auto gestureController = m_impl->gestureController())
820         gestureController->didFinishLoadForMainFrame();
821 }
822
823 void PageClientImpl::didFailLoadForMainFrame()
824 {
825     if (auto gestureController = m_impl->gestureController())
826         gestureController->didFailLoadForMainFrame();
827 }
828
829 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
830 {
831     if (auto gestureController = m_impl->gestureController())
832         gestureController->didSameDocumentNavigationForMainFrame(type);
833 }
834
835 void PageClientImpl::handleControlledElementIDResponse(const String& identifier)
836 {
837 #if WK_API_ENABLED
838     [m_webView _handleControlledElementIDResponse:nsStringFromWebCoreString(identifier)];
839 #endif
840 }
841
842 void PageClientImpl::didChangeBackgroundColor()
843 {
844     notImplemented();
845 }
846
847 CGRect PageClientImpl::boundsOfLayerInLayerBackedWindowCoordinates(CALayer *layer) const
848 {
849     CALayer *windowContentLayer = static_cast<NSView *>(m_view.window.contentView).layer;
850     ASSERT(windowContentLayer);
851
852     return [windowContentLayer convertRect:layer.bounds fromLayer:layer];
853 }
854
855 void PageClientImpl::didPerformImmediateActionHitTest(const WebHitTestResultData& result, bool contentPreventsDefault, API::Object* userData)
856 {
857     m_impl->didPerformImmediateActionHitTest(result, contentPreventsDefault, userData);
858 }
859
860 NSObject *PageClientImpl::immediateActionAnimationControllerForHitTestResult(RefPtr<API::HitTestResult> hitTestResult, uint64_t type, RefPtr<API::Object> userData)
861 {
862     return m_impl->immediateActionAnimationControllerForHitTestResult(hitTestResult.get(), type, userData.get());
863 }
864
865 void PageClientImpl::didHandleAcceptedCandidate()
866 {
867     m_impl->didHandleAcceptedCandidate();
868 }
869
870 void PageClientImpl::videoControlsManagerDidChange()
871 {
872     m_impl->videoControlsManagerDidChange();
873 }
874
875 void PageClientImpl::showPlatformContextMenu(NSMenu *menu, IntPoint location)
876 {
877     [menu popUpMenuPositioningItem:nil atLocation:location inView:m_view];
878 }
879
880 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
881 WebCore::WebMediaSessionManager& PageClientImpl::mediaSessionManager()
882 {
883     return WebMediaSessionManager::shared();
884 }
885 #endif
886
887 void PageClientImpl::refView()
888 {
889     CFRetain((__bridge CFTypeRef)m_view);
890 }
891
892 void PageClientImpl::derefView()
893 {
894     CFRelease((__bridge CFTypeRef)m_view);
895 }
896
897 void PageClientImpl::startWindowDrag()
898 {
899     m_impl->startWindowDrag();
900 }
901
902 NSWindow *PageClientImpl::platformWindow()
903 {
904     return m_impl->window();
905 }
906
907 #if ENABLE(DRAG_SUPPORT)
908
909 void PageClientImpl::didPerformDragOperation(bool handled)
910 {
911     m_impl->didPerformDragOperation(handled);
912 }
913
914 #endif
915
916 #if WK_API_ENABLED
917 NSView *PageClientImpl::inspectorAttachmentView()
918 {
919     return m_impl->inspectorAttachmentView();
920 }
921
922 _WKRemoteObjectRegistry *PageClientImpl::remoteObjectRegistry()
923 {
924     return m_impl->remoteObjectRegistry();
925 }
926 #endif
927
928 void PageClientImpl::didFinishProcessingAllPendingMouseEvents()
929 {
930     m_impl->didFinishProcessingAllPendingMouseEvents();
931 }
932
933 void PageClientImpl::didRestoreScrollPosition()
934 {
935     m_impl->didRestoreScrollPosition();
936 }
937
938 bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event)
939 {
940     return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent());
941 }
942
943 WebCore::UserInterfaceLayoutDirection PageClientImpl::userInterfaceLayoutDirection()
944 {
945     if (!m_view)
946         return WebCore::UserInterfaceLayoutDirection::LTR;
947     return (m_view.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionLeftToRight) ? WebCore::UserInterfaceLayoutDirection::LTR : WebCore::UserInterfaceLayoutDirection::RTL;
948 }
949
950 bool PageClientImpl::effectiveAppearanceIsDark() const
951 {
952     return m_impl->effectiveAppearanceIsDark();
953 }
954
955 } // namespace WebKit
956
957 #endif // PLATFORM(MAC)