/* * Copyright (C) 2008-2017 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 "WebChromeClientIOS.h" #if PLATFORM(IOS_FAMILY) #import "DOMNodeInternal.h" #import "PopupMenuIOS.h" #import "SearchPopupMenuIOS.h" #import "WebDelegateImplementationCaching.h" #import "WebFixedPositionContent.h" #import "WebFixedPositionContentInternal.h" #import "WebFormDelegate.h" #import "WebFrameIOS.h" #import "WebFrameInternal.h" #import "WebHistoryItemInternal.h" #import "WebOpenPanelResultListener.h" #import "WebUIDelegate.h" #import "WebUIDelegatePrivate.h" #import "WebUIKitDelegate.h" #import "WebView.h" #import "WebViewInternal.h" #import "WebViewPrivate.h" #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import NSString * const WebOpenPanelConfigurationAllowMultipleFilesKey = @"WebOpenPanelConfigurationAllowMultipleFilesKey"; NSString * const WebOpenPanelConfigurationMediaCaptureTypeKey = @"WebOpenPanelConfigurationMediaCaptureTypeKey"; NSString * const WebOpenPanelConfigurationMimeTypesKey = @"WebOpenPanelConfigurationMimeTypesKey"; using namespace WebCore; #if ENABLE(MEDIA_CAPTURE) static WebMediaCaptureType webMediaCaptureType(MediaCaptureType type) { switch (type) { case MediaCaptureTypeNone: return WebMediaCaptureTypeNone; case MediaCaptureTypeUser: return WebMediaCaptureTypeUser; case MediaCaptureTypeEnvironment: return WebMediaCaptureTypeEnvironment; } ASSERT_NOT_REACHED(); return WebMediaCaptureTypeNone; } #endif void WebChromeClientIOS::setWindowRect(const WebCore::FloatRect& r) { [[webView() _UIDelegateForwarder] webView:webView() setFrame:r]; } FloatRect WebChromeClientIOS::windowRect() { CGRect windowRect = [[webView() _UIDelegateForwarder] webViewFrame:webView()]; return enclosingIntRect(windowRect); } void WebChromeClientIOS::focus() { [[webView() _UIDelegateForwarder] webViewFocus:webView()]; } void WebChromeClientIOS::runJavaScriptAlert(Frame& frame, const WTF::String& message) { WebThreadLockPushModal(); [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptAlertPanelWithMessage:message initiatedByFrame:kit(&frame)]; WebThreadLockPopModal(); } bool WebChromeClientIOS::runJavaScriptConfirm(Frame& frame, const WTF::String& message) { WebThreadLockPushModal(); bool result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:kit(&frame)]; WebThreadLockPopModal(); return result; } bool WebChromeClientIOS::runJavaScriptPrompt(Frame& frame, const WTF::String& prompt, const WTF::String& defaultText, WTF::String& result) { WebThreadLockPushModal(); result = [[webView() _UIDelegateForwarder] webView:webView() runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:kit(&frame)]; WebThreadLockPopModal(); return !result.isNull(); } void WebChromeClientIOS::runOpenPanel(Frame&, FileChooser& chooser) { auto& settings = chooser.settings(); BOOL allowMultipleFiles = settings.allowsMultipleFiles; auto listener = adoptNS([[WebOpenPanelResultListener alloc] initWithChooser:chooser]); WebMediaCaptureType captureType = WebMediaCaptureTypeNone; #if ENABLE(MEDIA_CAPTURE) captureType = webMediaCaptureType(settings.mediaCaptureType); #endif NSDictionary *configuration = @{ WebOpenPanelConfigurationAllowMultipleFilesKey: @(allowMultipleFiles), WebOpenPanelConfigurationMimeTypesKey: createNSArray(settings.acceptMIMETypes).get(), WebOpenPanelConfigurationMediaCaptureTypeKey: @(captureType) }; if (WebThreadIsCurrent()) { RunLoop::main().dispatch([this, listener = WTFMove(listener), configuration = retainPtr(configuration)] { [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener.get() configuration:configuration.get()]; }); } else [[webView() _UIKitDelegateForwarder] webView:webView() runOpenPanelForFileButtonWithResultListener:listener.get() configuration:configuration]; } void WebChromeClientIOS::showShareSheet(ShareDataWithParsedURL&, CompletionHandler&&) { } #if ENABLE(IOS_TOUCH_EVENTS) void WebChromeClientIOS::didPreventDefaultForEvent() { [[webView() _UIKitDelegateForwarder] webViewDidPreventDefaultForEvent:webView()]; } #endif void WebChromeClientIOS::didReceiveMobileDocType(bool isMobileDoctype) { if (isMobileDoctype) [[webView() _UIKitDelegateForwarder] webViewDidReceiveMobileDocType:webView()]; } void WebChromeClientIOS::setNeedsScrollNotifications(WebCore::Frame& frame, bool flag) { [[webView() _UIKitDelegateForwarder] webView:webView() needsScrollNotifications:[NSNumber numberWithBool:flag] forFrame:kit(&frame)]; } void WebChromeClientIOS::didFinishContentChangeObserving(WebCore::Frame& frame, WKContentChange observedContentChange) { if (!frame.document()) return; [[webView() _UIKitDelegateForwarder] webView:webView() didObserveDeferredContentChange:observedContentChange forFrame:kit(&frame)]; } static inline NSString *nameForViewportFitValue(ViewportFit value) { switch (value) { case ViewportFit::Auto: return WebViewportFitAutoValue; case ViewportFit::Contain: return WebViewportFitContainValue; case ViewportFit::Cover: return WebViewportFitCoverValue; } return WebViewportFitAutoValue; } static inline NSDictionary *dictionaryForViewportArguments(const WebCore::ViewportArguments& arguments) { return @{ WebViewportInitialScaleKey: @(arguments.zoom), WebViewportMinimumScaleKey: @(arguments.minZoom), WebViewportMaximumScaleKey: @(arguments.maxZoom), WebViewportUserScalableKey: @(arguments.userZoom), WebViewportShrinkToFitKey: @(0), WebViewportFitKey: nameForViewportFitValue(arguments.viewportFit), WebViewportWidthKey: @(arguments.width), WebViewportHeightKey: @(arguments.height) }; } FloatSize WebChromeClientIOS::screenSize() const { return FloatSize(WebCore::screenSize()); } FloatSize WebChromeClientIOS::availableScreenSize() const { // WebKit1 code should query the WAKWindow for the available screen size. ASSERT_NOT_REACHED(); return FloatSize(); } FloatSize WebChromeClientIOS::overrideScreenSize() const { return screenSize(); } void WebChromeClientIOS::dispatchViewportPropertiesDidChange(const WebCore::ViewportArguments& arguments) const { [[webView() _UIKitDelegateForwarder] webView:webView() didReceiveViewportArguments:dictionaryForViewportArguments(arguments)]; } void WebChromeClientIOS::dispatchDisabledAdaptationsDidChange(const OptionSet&) const { } void WebChromeClientIOS::notifyRevealedSelectionByScrollingFrame(WebCore::Frame& frame) { [[webView() _UIKitDelegateForwarder] revealedSelectionByScrollingWebFrame:kit(&frame)]; } bool WebChromeClientIOS::isStopping() { return [webView() _isStopping]; } void WebChromeClientIOS::didLayout(LayoutType changeType) { [[webView() _UIKitDelegate] webThreadWebViewDidLayout:webView() byScrolling:(changeType == ChromeClient::Scroll)]; } void WebChromeClientIOS::didStartOverflowScroll() { [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidStartOverflowScroll:webView()]; } void WebChromeClientIOS::didEndOverflowScroll() { [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidEndOverflowScroll:webView()]; } void WebChromeClientIOS::suppressFormNotifications() { m_formNotificationSuppressions++; } void WebChromeClientIOS::restoreFormNotifications() { m_formNotificationSuppressions--; ASSERT(m_formNotificationSuppressions >= 0); if (m_formNotificationSuppressions < 0) m_formNotificationSuppressions = 0; } void WebChromeClientIOS::elementDidFocus(WebCore::Element& element, const WebCore::FocusOptions&) { if (m_formNotificationSuppressions <= 0) [[webView() _UIKitDelegateForwarder] webView:webView() elementDidFocusNode:kit(&element)]; } void WebChromeClientIOS::elementDidBlur(WebCore::Element& element) { if (m_formNotificationSuppressions <= 0) [[webView() _UIKitDelegateForwarder] webView:webView() elementDidBlurNode:kit(&element)]; } bool WebChromeClientIOS::selectItemWritingDirectionIsNatural() { return false; } bool WebChromeClientIOS::selectItemAlignmentFollowsMenuWritingDirection() { return true; } RefPtr WebChromeClientIOS::createPopupMenu(WebCore::PopupMenuClient& client) const { return adoptRef(new PopupMenuIOS(&client)); } RefPtr WebChromeClientIOS::createSearchPopupMenu(WebCore::PopupMenuClient& client) const { return adoptRef(new SearchPopupMenuIOS(&client)); } void WebChromeClientIOS::attachRootGraphicsLayer(Frame&, GraphicsLayer* graphicsLayer) { // FIXME: for non-root frames we rely on RenderView positioning the root layer, // which is a hack. // Send the delegate message on the web thread to avoid [[webView() _UIKitDelegate] _webthread_webView:webView() attachRootLayer:graphicsLayer ? graphicsLayer->platformLayer() : 0]; } void WebChromeClientIOS::didFlushCompositingLayers() { [[[webView() _UIKitDelegateForwarder] asyncForwarder] webViewDidCommitCompositingLayerChanges:webView()]; } bool WebChromeClientIOS::fetchCustomFixedPositionLayoutRect(IntRect& rect) { NSRect updatedRect; if ([webView() _fetchCustomFixedPositionLayoutRect:&updatedRect]) { rect = enclosingIntRect(updatedRect); return true; } return false; } void WebChromeClientIOS::updateViewportConstrainedLayers(HashMap>& layerMap, const HashMap& stickyContainers) { [[webView() _fixedPositionContent] setViewportConstrainedLayers:layerMap stickyContainerMap:stickyContainers]; } void WebChromeClientIOS::addOrUpdateScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer, const IntSize& scrollSize, bool allowHorizontalScrollbar, bool allowVerticalScrollbar) { DOMNode *domNode = kit(node); [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() didCreateOrUpdateScrollingLayer:scrollingLayer withContentsLayer:contentsLayer scrollSize:[NSValue valueWithSize:scrollSize] forNode:domNode allowHorizontalScrollbar:allowHorizontalScrollbar allowVerticalScrollbar:allowVerticalScrollbar]; } void WebChromeClientIOS::removeScrollingLayer(Node* node, PlatformLayer* scrollingLayer, PlatformLayer* contentsLayer) { DOMNode *domNode = kit(node); [[[webView() _UIKitDelegateForwarder] asyncForwarder] webView:webView() willRemoveScrollingLayer:scrollingLayer withContentsLayer:contentsLayer forNode:domNode]; } void WebChromeClientIOS::webAppOrientationsUpdated() { [[webView() _UIDelegateForwarder] webViewSupportedOrientationsUpdated:webView()]; } void WebChromeClientIOS::focusedElementChanged(Element* element) { if (!is(element)) return; HTMLInputElement& inputElement = downcast(*element); if (!inputElement.isText()) return; CallFormDelegate(webView(), @selector(didFocusTextField:inFrame:), kit(&inputElement), kit(inputElement.document().frame())); } void WebChromeClientIOS::showPlaybackTargetPicker(bool hasVideo, WebCore::RouteSharingPolicy, const String&) { CGPoint point = [[webView() _UIKitDelegateForwarder] interactionLocation]; CGRect elementRect = [[webView() mainFrame] elementRectAtPoint:point]; [[webView() _UIKitDelegateForwarder] showPlaybackTargetPicker:hasVideo fromRect:elementRect]; } RefPtr WebChromeClientIOS::createIconForFiles(const Vector& filenames) { return Icon::createIconForFiles(filenames); } #if ENABLE(ORIENTATION_EVENTS) int WebChromeClientIOS::deviceOrientation() const { return [webView() _deviceOrientation]; } #endif #endif // PLATFORM(IOS_FAMILY)