blob: 370b2fc5563bda0f1e7fac35111ef7b365390020 [file] [log] [blame]
/*
* Copyright (C) 2010-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "PageClientImplMac.h"
#if PLATFORM(MAC)
#import "APIHitTestResult.h"
#import "ColorSpaceData.h"
#import "DataReference.h"
#import "DownloadProxy.h"
#import "DrawingAreaProxy.h"
#import "Logging.h"
#import "NativeWebGestureEvent.h"
#import "NativeWebKeyboardEvent.h"
#import "NativeWebMouseEvent.h"
#import "NativeWebWheelEvent.h"
#import "NavigationState.h"
#import "StringUtilities.h"
#import "UndoOrRedo.h"
#import "ViewGestureController.h"
#import "ViewSnapshotStore.h"
#import "WKAPICast.h"
#import "WKFullScreenWindowController.h"
#import "WKStringCF.h"
#import "WKViewInternal.h"
#import "WKWebViewInternal.h"
#import "WKWebViewPrivateForTestingMac.h"
#import "WebColorPickerMac.h"
#import "WebContextMenuProxyMac.h"
#import "WebDataListSuggestionsDropdownMac.h"
#import "WebEditCommandProxy.h"
#import "WebPageProxy.h"
#import "WebPopupMenuProxyMac.h"
#import "WebViewImpl.h"
#import "WindowServerConnection.h"
#import "_WKDownloadInternal.h"
#import "_WKHitTestResultInternal.h"
#import "_WKThumbnailView.h"
#import <WebCore/AlternativeTextUIController.h>
#import <WebCore/BitmapImage.h>
#import <WebCore/ColorMac.h>
#import <WebCore/Cursor.h>
#import <WebCore/DictionaryLookup.h>
#import <WebCore/DragItem.h>
#import <WebCore/FloatRect.h>
#import <WebCore/GraphicsContext.h>
#import <WebCore/Image.h>
#import <WebCore/KeyboardEvent.h>
#import <WebCore/NotImplemented.h>
#import <WebCore/PlatformScreen.h>
#import <WebCore/PromisedAttachmentInfo.h>
#import <WebCore/SharedBuffer.h>
#import <WebCore/TextIndicator.h>
#import <WebCore/TextIndicatorWindow.h>
#import <WebCore/TextUndoInsertionMarkupMac.h>
#import <WebCore/ValidationBubble.h>
#import <WebCore/WebCoreCALayerExtras.h>
#import <pal/spi/mac/NSApplicationSPI.h>
#import <wtf/ProcessPrivilege.h>
#import <wtf/RetainPtr.h>
#import <wtf/text/CString.h>
#import <wtf/text/WTFString.h>
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
#import <WebCore/WebMediaSessionManager.h>
#endif
static NSString * const kAXLoadCompleteNotification = @"AXLoadComplete";
@interface NSApplication (WebNSApplicationDetails)
- (NSCursor *)_cursorRectCursor;
@end
#if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
@interface NSWindow (WebNSWindowLayerHostingDetails)
- (BOOL)_hostsLayersInWindowServer;
@end
#endif
namespace WebKit {
using namespace WebCore;
PageClientImpl::PageClientImpl(NSView *view, WKWebView *webView)
: PageClientImplCocoa(webView)
, m_view(view)
{
}
PageClientImpl::~PageClientImpl() = default;
void PageClientImpl::setImpl(WebViewImpl& impl)
{
m_impl = makeWeakPtr(impl);
}
std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
{
return m_impl->createDrawingAreaProxy(process);
}
void PageClientImpl::setViewNeedsDisplay(const WebCore::Region&)
{
ASSERT_NOT_REACHED();
}
void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, const IntPoint& scrollOrigin)
{
}
WebCore::FloatPoint PageClientImpl::viewScrollPosition()
{
return { };
}
IntSize PageClientImpl::viewSize()
{
return IntSize([m_view bounds].size);
}
NSView *PageClientImpl::activeView() const
{
return (m_impl && m_impl->thumbnailView()) ? (NSView *)m_impl->thumbnailView() : m_view;
}
NSWindow *PageClientImpl::activeWindow() const
{
if (m_impl && m_impl->thumbnailView())
return m_impl->thumbnailView().window;
if (m_impl && m_impl->targetWindowForMovePreparation())
return m_impl->targetWindowForMovePreparation();
return m_view.window;
}
bool PageClientImpl::isViewWindowActive()
{
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
NSWindow *activeViewWindow = activeWindow();
return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
}
bool PageClientImpl::isViewFocused()
{
// FIXME: This is called from the WebPageProxy constructor before we have a WebViewImpl.
// Once WebViewImpl and PageClient merge, this won't be a problem.
if (!m_impl)
return NO;
return m_impl->isFocused();
}
void PageClientImpl::assistiveTechnologyMakeFirstResponder()
{
[[m_view window] makeFirstResponder:m_view];
}
void PageClientImpl::makeFirstResponder()
{
if (m_shouldSuppressFirstResponderChanges)
return;
[[m_view window] makeFirstResponder:m_view];
}
bool PageClientImpl::isViewVisible()
{
NSView *activeView = this->activeView();
NSWindow *activeViewWindow = activeWindow();
auto windowIsOccluded = [&]()->bool {
return m_impl && m_impl->windowOcclusionDetectionEnabled() && (activeViewWindow.occlusionState & NSWindowOcclusionStateVisible) != NSWindowOcclusionStateVisible;
};
LOG_WITH_STREAM(ActivityState, stream << "PageClientImpl " << this << " isViewVisible(): activeViewWindow " << activeViewWindow
<< " (window visible " << activeViewWindow.isVisible << ", view hidden " << activeView.isHiddenOrHasHiddenAncestor << ", window occluded " << windowIsOccluded() << ")");
if (!activeViewWindow)
return false;
if (!activeViewWindow.isVisible)
return false;
if (activeView.isHiddenOrHasHiddenAncestor)
return false;
if (windowIsOccluded())
return false;
return true;
}
bool PageClientImpl::isViewVisibleOrOccluded()
{
return activeWindow().isVisible;
}
bool PageClientImpl::isViewInWindow()
{
return activeWindow();
}
bool PageClientImpl::isVisuallyIdle()
{
return WindowServerConnection::singleton().applicationWindowModificationsHaveStopped() || !isViewVisible();
}
LayerHostingMode PageClientImpl::viewLayerHostingMode()
{
#if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
if ([activeWindow() _hostsLayersInWindowServer])
return LayerHostingMode::OutOfProcess;
#endif
return LayerHostingMode::InProcess;
}
void PageClientImpl::viewWillMoveToAnotherWindow()
{
clearAllEditCommands();
}
ColorSpaceData PageClientImpl::colorSpace()
{
return m_impl->colorSpace();
}
void PageClientImpl::processWillSwap()
{
m_impl->processWillSwap();
}
void PageClientImpl::processDidExit()
{
m_impl->processDidExit();
m_impl->setAcceleratedCompositingRootLayer(nil);
}
void PageClientImpl::pageClosed()
{
m_impl->pageClosed();
PageClientImplCocoa::pageClosed();
}
void PageClientImpl::didRelaunchProcess()
{
m_impl->didRelaunchProcess();
}
void PageClientImpl::preferencesDidChange()
{
m_impl->preferencesDidChange();
}
void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
{
m_impl->toolTipChanged(oldToolTip, newToolTip);
}
void PageClientImpl::didCommitLoadForMainFrame(const String&, bool)
{
m_impl->updateSupportsArbitraryLayoutModes();
m_impl->dismissContentRelativeChildWindowsWithAnimation(true);
m_impl->clearPromisedDragImage();
}
void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
{
}
void PageClientImpl::handleDownloadRequest(DownloadProxy&)
{
}
void PageClientImpl::didChangeContentSize(const WebCore::IntSize& newSize)
{
m_impl->didChangeContentSize(newSize);
}
void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
{
ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
// FIXME: Would be nice to share this code with WebKit1's WebChromeClient.
// The Web process may have asked to change the cursor when the view was in an active window, but
// if it is no longer in a window or the window is not active, then the cursor should not change.
if (!isViewWindowActive())
return;
if ([NSApp _cursorRectCursor])
return;
if (!m_view)
return;
NSWindow *window = [m_view window];
if (!window)
return;
if ([window windowNumber] != [NSWindow windowNumberAtPoint:[NSEvent mouseLocation] belowWindowWithWindowNumber:0])
return;
NSCursor *platformCursor = cursor.platformCursor();
if ([NSCursor currentCursor] == platformCursor)
return;
[platformCursor set];
}
void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
{
[NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
}
void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
{
}
void PageClientImpl::registerEditCommand(Ref<WebEditCommandProxy>&& command, UndoOrRedo undoOrRedo)
{
m_impl->registerEditCommand(WTFMove(command), undoOrRedo);
}
void PageClientImpl::registerInsertionUndoGrouping()
{
registerInsertionUndoGroupingWithUndoManager([m_view undoManager]);
}
void PageClientImpl::clearAllEditCommands()
{
m_impl->clearAllEditCommands();
}
bool PageClientImpl::canUndoRedo(UndoOrRedo undoOrRedo)
{
return (undoOrRedo == UndoOrRedo::Undo) ? [[m_view undoManager] canUndo] : [[m_view undoManager] canRedo];
}
void PageClientImpl::executeUndoRedo(UndoOrRedo undoOrRedo)
{
return (undoOrRedo == UndoOrRedo::Undo) ? [[m_view undoManager] undo] : [[m_view undoManager] redo];
}
void PageClientImpl::startDrag(const WebCore::DragItem& item, const ShareableBitmap::Handle& image)
{
m_impl->startDrag(item, image);
}
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)
{
auto image = BitmapImage::create();
image->setData(WTFMove(imageBuffer), true);
m_impl->setPromisedDataForImage(image.ptr(), filename, extension, title, url, visibleURL, archiveBuffer.get(), pasteboardName);
}
void PageClientImpl::updateSecureInputState()
{
m_impl->updateSecureInputState();
}
void PageClientImpl::resetSecureInputState()
{
m_impl->resetSecureInputState();
}
void PageClientImpl::notifyInputContextAboutDiscardedComposition()
{
m_impl->notifyInputContextAboutDiscardedComposition();
}
FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
{
return toDeviceSpace(rect, [m_view window]);
}
FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
{
return toUserSpace(rect, [m_view window]);
}
void PageClientImpl::pinnedStateWillChange()
{
[m_webView willChangeValueForKey:@"_pinnedState"];
}
void PageClientImpl::pinnedStateDidChange()
{
[m_webView didChangeValueForKey:@"_pinnedState"];
}
IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
{
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
NSPoint windowCoord = [[m_view window] convertScreenToBase:point];
ALLOW_DEPRECATED_DECLARATIONS_END
return IntPoint([m_view convertPoint:windowCoord fromView:nil]);
}
IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
{
NSRect tempRect = rect;
tempRect = [m_view convertRect:tempRect toView:nil];
ALLOW_DEPRECATED_DECLARATIONS_BEGIN
tempRect.origin = [[m_view window] convertBaseToScreen:tempRect.origin];
ALLOW_DEPRECATED_DECLARATIONS_END
return enclosingIntRect(tempRect);
}
IntRect PageClientImpl::rootViewToWindow(const WebCore::IntRect& rect)
{
NSRect tempRect = rect;
tempRect = [m_view convertRect:tempRect toView:nil];
return enclosingIntRect(tempRect);
}
IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
{
return screenToRootView(point);
}
IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
{
return rootViewToScreen(rect);
}
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
{
m_impl->doneWithKeyEvent(event.nativeEvent(), eventWasHandled);
}
RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy& page)
{
return WebPopupMenuProxyMac::create(m_view, page);
}
#if ENABLE(CONTEXT_MENUS)
Ref<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy& page, ContextMenuContextData&& context, const UserData& userData)
{
return WebContextMenuProxyMac::create(m_view, page, WTFMove(context), userData);
}
#endif
#if ENABLE(INPUT_TYPE_COLOR)
RefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& initialColor, const WebCore::IntRect& rect, Vector<WebCore::Color>&& suggestions)
{
return WebColorPickerMac::create(page, initialColor, rect, WTFMove(suggestions), m_view);
}
#endif
#if ENABLE(DATALIST_ELEMENT)
RefPtr<WebDataListSuggestionsDropdown> PageClientImpl::createDataListSuggestionsDropdown(WebPageProxy& page)
{
return WebDataListSuggestionsDropdownMac::create(page, m_view);
}
#endif
Ref<ValidationBubble> PageClientImpl::createValidationBubble(const String& message, const ValidationBubble::Settings& settings)
{
return ValidationBubble::create(m_view, message, settings);
}
void PageClientImpl::showSafeBrowsingWarning(const SafeBrowsingWarning& warning, CompletionHandler<void(Variant<WebKit::ContinueUnsafeLoad, URL>&&)>&& completionHandler)
{
if (!m_impl)
return completionHandler(ContinueUnsafeLoad::Yes);
m_impl->showSafeBrowsingWarning(warning, WTFMove(completionHandler));
}
bool PageClientImpl::hasSafeBrowsingWarning() const
{
if (!m_impl)
return false;
return !!m_impl->safeBrowsingWarning();
}
void PageClientImpl::clearSafeBrowsingWarning()
{
m_impl->clearSafeBrowsingWarning();
}
void PageClientImpl::clearSafeBrowsingWarningIfForMainFrameNavigation()
{
m_impl->clearSafeBrowsingWarningIfForMainFrameNavigation();
}
void PageClientImpl::setTextIndicator(Ref<TextIndicator> textIndicator, WebCore::TextIndicatorWindowLifetime lifetime)
{
m_impl->setTextIndicator(textIndicator.get(), lifetime);
}
void PageClientImpl::clearTextIndicator(WebCore::TextIndicatorWindowDismissalAnimation dismissalAnimation)
{
m_impl->clearTextIndicatorWithAnimation(dismissalAnimation);
}
void PageClientImpl::setTextIndicatorAnimationProgress(float progress)
{
m_impl->setTextIndicatorAnimationProgress(progress);
}
void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
{
m_impl->setAccessibilityWebProcessToken([NSData dataWithBytes:data.data() length:data.size()]);
}
void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
{
ASSERT(!layerTreeContext.isEmpty());
CALayer *renderLayer = [CALayer _web_renderLayerWithContextID:layerTreeContext.contextID];
m_impl->enterAcceleratedCompositingWithRootLayer(renderLayer);
}
void PageClientImpl::didFirstLayerFlush(const LayerTreeContext& layerTreeContext)
{
ASSERT(!layerTreeContext.isEmpty());
CALayer *renderLayer = [CALayer _web_renderLayerWithContextID:layerTreeContext.contextID];
m_impl->setAcceleratedCompositingRootLayer(renderLayer);
}
void PageClientImpl::exitAcceleratedCompositingMode()
{
m_impl->setAcceleratedCompositingRootLayer(nil);
}
void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
{
ASSERT(!layerTreeContext.isEmpty());
CALayer *renderLayer = [CALayer _web_renderLayerWithContextID:layerTreeContext.contextID];
m_impl->setAcceleratedCompositingRootLayer(renderLayer);
}
void PageClientImpl::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
{
m_impl->setAcceleratedCompositingRootLayer(rootNode ? rootNode->layer() : nil);
}
CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
{
return m_impl->acceleratedCompositingRootLayer();
}
RefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot(Optional<WebCore::IntRect>&&)
{
return m_impl->takeViewSnapshot();
}
void PageClientImpl::selectionDidChange()
{
m_impl->selectionDidChange();
}
bool PageClientImpl::showShareSheet(const ShareDataWithParsedURL& shareData, WTF::CompletionHandler<void(bool)>&& completionHandler)
{
m_impl->showShareSheet(shareData, WTFMove(completionHandler), m_webView.get().get());
return true;
}
void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
{
if (auto gestureController = m_impl->gestureController())
gestureController->wheelEventWasNotHandledByWebCore(event.nativeEvent());
}
#if ENABLE(MAC_GESTURE_EVENTS)
void PageClientImpl::gestureEventWasNotHandledByWebCore(const NativeWebGestureEvent& event)
{
m_impl->gestureEventWasNotHandledByWebCore(event.nativeEvent());
}
#endif
void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
{
m_impl->pluginFocusOrWindowFocusChanged(pluginHasFocusAndWindowHasFocus, pluginComplexTextInputIdentifier);
}
void PageClientImpl::setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, PluginComplexTextInputState pluginComplexTextInputState)
{
m_impl->setPluginComplexTextInputStateAndIdentifier(pluginComplexTextInputState, pluginComplexTextInputIdentifier);
}
void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
{
m_impl->prepareForDictionaryLookup();
DictionaryLookup::showPopup(dictionaryPopupInfo, m_view, [this](TextIndicator& textIndicator) {
m_impl->setTextIndicator(textIndicator, TextIndicatorWindowLifetime::Permanent);
}, nullptr, [this]() {
m_impl->clearTextIndicatorWithAnimation(WebCore::TextIndicatorWindowDismissalAnimation::None);
});
}
void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
{
#if USE(AUTOCORRECTION_PANEL)
if (!isViewVisible() || !isViewInWindow())
return;
m_correctionPanel.show(m_view, *m_impl, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
#endif
}
void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason)
{
#if USE(AUTOCORRECTION_PANEL)
m_correctionPanel.dismiss(reason);
#endif
}
String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason)
{
#if USE(AUTOCORRECTION_PANEL)
return m_correctionPanel.dismiss(reason);
#else
return String();
#endif
}
static inline NSCorrectionResponse toCorrectionResponse(AutocorrectionResponse response)
{
switch (response) {
case WebCore::AutocorrectionResponse::Reverted:
return NSCorrectionResponseReverted;
case WebCore::AutocorrectionResponse::Edited:
return NSCorrectionResponseEdited;
case WebCore::AutocorrectionResponse::Accepted:
return NSCorrectionResponseAccepted;
}
ASSERT_NOT_REACHED();
return NSCorrectionResponseAccepted;
}
void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponse response, const String& replacedString, const String& replacementString)
{
CorrectionPanel::recordAutocorrectionResponse(*m_impl, m_impl->spellCheckerDocumentTag(), toCorrectionResponse(response), replacedString, replacementString);
}
void PageClientImpl::recommendedScrollbarStyleDidChange(ScrollbarStyle newStyle)
{
// Now re-create a tracking area with the appropriate options given the new scrollbar style
NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingCursorUpdate;
if (newStyle == ScrollbarStyle::AlwaysVisible)
options |= NSTrackingActiveAlways;
else
options |= NSTrackingActiveInKeyWindow;
RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_view frame] options:options owner:m_view userInfo:nil]);
m_impl->setPrimaryTrackingArea(trackingArea.get());
}
void PageClientImpl::intrinsicContentSizeDidChange(const IntSize& intrinsicContentSize)
{
m_impl->setIntrinsicContentSize(intrinsicContentSize);
}
bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString)
{
return m_impl->executeSavedCommandBySelector(NSSelectorFromString(selectorString));
}
void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, WebCore::DictationContext dictationContext)
{
if (!isViewVisible() || !isViewInWindow())
return;
m_alternativeTextUIController->showAlternatives(m_view, boundingBoxOfDictatedText, dictationContext, ^(NSString *acceptedAlternative) {
m_impl->handleAcceptedAlternativeText(acceptedAlternative);
});
}
void PageClientImpl::setEditableElementIsFocused(bool editableElementIsFocused)
{
m_impl->setEditableElementIsFocused(editableElementIsFocused);
}
#if ENABLE(FULLSCREEN_API)
WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
{
return *this;
}
// WebFullScreenManagerProxyClient
void PageClientImpl::closeFullScreenManager()
{
m_impl->closeFullScreenWindowController();
}
bool PageClientImpl::isFullScreen()
{
if (!m_impl->hasFullScreenWindowController())
return false;
return m_impl->fullScreenWindowController().isFullScreen;
}
void PageClientImpl::enterFullScreen()
{
[m_impl->fullScreenWindowController() enterFullScreen:nil];
}
void PageClientImpl::exitFullScreen()
{
[m_impl->fullScreenWindowController() exitFullScreen];
}
void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
{
[m_impl->fullScreenWindowController() beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
m_impl->updateSupportsArbitraryLayoutModes();
}
void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
{
[m_impl->fullScreenWindowController() beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
m_impl->updateSupportsArbitraryLayoutModes();
}
#endif // ENABLE(FULLSCREEN_API)
void PageClientImpl::navigationGestureDidBegin()
{
m_impl->dismissContentRelativeChildWindowsWithAnimation(true);
if (auto webView = m_webView.get())
NavigationState::fromWebPage(*webView->_page).navigationGestureDidBegin();
}
void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
{
if (auto webView = m_webView.get())
NavigationState::fromWebPage(*webView->_page).navigationGestureWillEnd(willNavigate, item);
}
void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
{
if (auto webView = m_webView.get())
NavigationState::fromWebPage(*webView->_page).navigationGestureDidEnd(willNavigate, item);
}
void PageClientImpl::navigationGestureDidEnd()
{
}
void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
{
if (auto webView = m_webView.get())
NavigationState::fromWebPage(*webView->_page).willRecordNavigationSnapshot(item);
}
void PageClientImpl::didRemoveNavigationGestureSnapshot()
{
if (auto webView = m_webView.get())
NavigationState::fromWebPage(*webView->_page).navigationGestureSnapshotWasRemoved();
}
void PageClientImpl::didStartProvisionalLoadForMainFrame()
{
if (auto gestureController = m_impl->gestureController())
gestureController->didStartProvisionalLoadForMainFrame();
}
void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
{
if (auto gestureController = m_impl->gestureController())
gestureController->didFirstVisuallyNonEmptyLayoutForMainFrame();
}
void PageClientImpl::didFinishNavigation(API::Navigation* navigation)
{
if (auto gestureController = m_impl->gestureController())
gestureController->didFinishNavigation(navigation);
NSAccessibilityPostNotification(NSAccessibilityUnignoredAncestor(m_view), kAXLoadCompleteNotification);
}
void PageClientImpl::didFailNavigation(API::Navigation* navigation)
{
if (auto gestureController = m_impl->gestureController())
gestureController->didFailNavigation(navigation);
NSAccessibilityPostNotification(NSAccessibilityUnignoredAncestor(m_view), kAXLoadCompleteNotification);
}
void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
{
if (auto gestureController = m_impl->gestureController())
gestureController->didSameDocumentNavigationForMainFrame(type);
}
void PageClientImpl::handleControlledElementIDResponse(const String& identifier)
{
[m_webView _handleControlledElementIDResponse:nsStringFromWebCoreString(identifier)];
}
void PageClientImpl::didChangeBackgroundColor()
{
notImplemented();
}
CGRect PageClientImpl::boundsOfLayerInLayerBackedWindowCoordinates(CALayer *layer) const
{
CALayer *windowContentLayer = static_cast<NSView *>(m_view.window.contentView).layer;
ASSERT(windowContentLayer);
return [windowContentLayer convertRect:layer.bounds fromLayer:layer];
}
void PageClientImpl::didPerformImmediateActionHitTest(const WebHitTestResultData& result, bool contentPreventsDefault, API::Object* userData)
{
m_impl->didPerformImmediateActionHitTest(result, contentPreventsDefault, userData);
}
NSObject *PageClientImpl::immediateActionAnimationControllerForHitTestResult(RefPtr<API::HitTestResult> hitTestResult, uint64_t type, RefPtr<API::Object> userData)
{
return m_impl->immediateActionAnimationControllerForHitTestResult(hitTestResult.get(), type, userData.get());
}
void PageClientImpl::didHandleAcceptedCandidate()
{
m_impl->didHandleAcceptedCandidate();
}
void PageClientImpl::videoControlsManagerDidChange()
{
m_impl->videoControlsManagerDidChange();
}
void PageClientImpl::showPlatformContextMenu(NSMenu *menu, IntPoint location)
{
[menu popUpMenuPositioningItem:nil atLocation:location inView:m_view];
}
#if ENABLE(WIRELESS_PLAYBACK_TARGET)
WebCore::WebMediaSessionManager& PageClientImpl::mediaSessionManager()
{
return WebMediaSessionManager::shared();
}
#endif
void PageClientImpl::refView()
{
CFRetain((__bridge CFTypeRef)m_view);
}
void PageClientImpl::derefView()
{
CFRelease((__bridge CFTypeRef)m_view);
}
void PageClientImpl::startWindowDrag()
{
m_impl->startWindowDrag();
}
NSWindow *PageClientImpl::platformWindow()
{
return m_impl->window();
}
#if ENABLE(DRAG_SUPPORT)
void PageClientImpl::didPerformDragOperation(bool handled)
{
m_impl->didPerformDragOperation(handled);
}
#endif
NSView *PageClientImpl::inspectorAttachmentView()
{
return m_impl->inspectorAttachmentView();
}
_WKRemoteObjectRegistry *PageClientImpl::remoteObjectRegistry()
{
return m_impl->remoteObjectRegistry();
}
void PageClientImpl::didRestoreScrollPosition()
{
m_impl->didRestoreScrollPosition();
}
bool PageClientImpl::windowIsFrontWindowUnderMouse(const NativeWebMouseEvent& event)
{
return m_impl->windowIsFrontWindowUnderMouse(event.nativeEvent());
}
WebCore::UserInterfaceLayoutDirection PageClientImpl::userInterfaceLayoutDirection()
{
if (!m_view)
return WebCore::UserInterfaceLayoutDirection::LTR;
return (m_view.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionLeftToRight) ? WebCore::UserInterfaceLayoutDirection::LTR : WebCore::UserInterfaceLayoutDirection::RTL;
}
bool PageClientImpl::effectiveAppearanceIsDark() const
{
return m_impl->effectiveAppearanceIsDark();
}
bool PageClientImpl::effectiveUserInterfaceLevelIsElevated() const
{
return m_impl->effectiveUserInterfaceLevelIsElevated();
}
void PageClientImpl::takeFocus(WebCore::FocusDirection direction)
{
m_impl->takeFocus(direction);
}
void PageClientImpl::requestDOMPasteAccess(const WebCore::IntRect& elementRect, const String& originIdentifier, CompletionHandler<void(WebCore::DOMPasteAccessResponse)>&& completion)
{
m_impl->requestDOMPasteAccess(elementRect, originIdentifier, WTFMove(completion));
}
#if HAVE(APP_ACCENT_COLORS)
WebCore::Color PageClientImpl::accentColor()
{
return WebCore::colorFromNSColor([NSApp _accentColor]);
}
#endif
} // namespace WebKit
#endif // PLATFORM(MAC)