blob: b42148ead0f873b815563fd0e4e3090dc6a940e4 [file] [log] [blame]
/*
* Copyright (C) 2012, 2013 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 "PageClientImplIOS.h"
#if PLATFORM(IOS)
#import "APIData.h"
#import "DataReference.h"
#import "DownloadProxy.h"
#import "FindIndicator.h"
#import "NativeWebKeyboardEvent.h"
#import "InteractionInformationAtPosition.h"
#import "ViewSnapshotStore.h"
#import "WKContentView.h"
#import "WKContentViewInteraction.h"
#import "WKWebViewInternal.h"
#import "WebContextMenuProxy.h"
#import "WebEditCommandProxy.h"
#import "WebProcessProxy.h"
#import "_WKDownloadInternal.h"
#import <UIKit/UIImagePickerController_Private.h>
#import <UIKit/UIWebTouchEventsGestureRecognizer.h>
#import <WebCore/NotImplemented.h>
#import <WebCore/PlatformScreen.h>
#import <WebCore/SharedBuffer.h>
#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_webView->_page->process().connection())
@interface UIView (IPI)
- (UIScrollView *)_scroller;
- (CGPoint)accessibilityConvertPointFromSceneReferenceCoordinates:(CGPoint)point;
- (CGRect)accessibilityConvertRectToSceneReferenceCoordinates:(CGRect)rect;
@end
using namespace WebCore;
namespace WebKit {
PageClientImpl::PageClientImpl(WKContentView *contentView, WKWebView *webView)
: m_contentView(contentView)
, m_webView(webView)
{
}
PageClientImpl::~PageClientImpl()
{
}
std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
{
return [m_contentView _createDrawingAreaProxy];
}
void PageClientImpl::setViewNeedsDisplay(const IntRect& rect)
{
ASSERT_NOT_REACHED();
}
void PageClientImpl::displayView()
{
ASSERT_NOT_REACHED();
}
bool PageClientImpl::canScrollView()
{
notImplemented();
return false;
}
void PageClientImpl::scrollView(const IntRect&, const IntSize&)
{
ASSERT_NOT_REACHED();
}
void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
{
UNUSED_PARAM(isProgrammaticScroll);
[m_webView _scrollToContentOffset:scrollPosition];
}
IntSize PageClientImpl::viewSize()
{
if (UIScrollView *scroller = [m_contentView _scroller])
return IntSize(scroller.bounds.size);
return IntSize(m_contentView.bounds.size);
}
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
ViewState::Flags PageClientImpl::viewState()
{
ViewState::Flags viewState = ViewState::NoFlags;
bool isInWindow = [m_webView window];
bool isVisible = isInWindow && [UIApplication sharedApplication].applicationState != UIApplicationStateBackground;
if (isInWindow)
viewState |= ViewState::IsInWindow;
if (isVisible)
viewState |= ViewState::WindowIsActive | ViewState::IsFocused | ViewState::IsVisible | ViewState::IsVisibleOrOccluded;
else
viewState |= ViewState::IsVisuallyIdle;
return viewState;
}
void PageClientImpl::processDidExit()
{
[m_contentView _processDidExit];
[m_webView _processDidExit];
}
void PageClientImpl::didRelaunchProcess()
{
[m_contentView _didRelaunchProcess];
}
void PageClientImpl::pageClosed()
{
notImplemented();
}
void PageClientImpl::preferencesDidChange()
{
notImplemented();
}
void PageClientImpl::toolTipChanged(const String&, const String&)
{
notImplemented();
}
bool PageClientImpl::decidePolicyForGeolocationPermissionRequest(WebFrameProxy& frame, WebSecurityOrigin& origin, GeolocationPermissionRequestProxy& request)
{
[m_contentView _decidePolicyForGeolocationRequestFromOrigin:origin frame:frame request:request];
return true;
}
void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
{
[m_webView _setHasCustomContentView:useCustomContentProvider loadedMIMEType:mimeType];
[m_contentView _didCommitLoadForMainFrame];
}
void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
{
ASSERT_ARG(download, download);
ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
[static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
}
void PageClientImpl::didChangeViewportMetaTagWidth(float newWidth)
{
[m_webView _setViewportMetaTagWidth:newWidth];
}
void PageClientImpl::setUsesMinimalUI(bool usesMinimalUI)
{
[m_webView _setUsesMinimalUI:usesMinimalUI];
}
double PageClientImpl::minimumZoomScale() const
{
if (UIScrollView *scroller = [m_webView scrollView])
return scroller.minimumZoomScale;
return 1;
}
WebCore::FloatSize PageClientImpl::contentsSize() const
{
return FloatSize([m_contentView bounds].size);
}
void PageClientImpl::setCursor(const Cursor&)
{
notImplemented();
}
void PageClientImpl::setCursorHiddenUntilMouseMoves(bool)
{
notImplemented();
}
void PageClientImpl::didChangeViewportProperties(const ViewportAttributes&)
{
notImplemented();
}
void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo)
{
notImplemented();
}
void PageClientImpl::clearAllEditCommands()
{
notImplemented();
}
bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo)
{
notImplemented();
return false;
}
void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo)
{
notImplemented();
}
void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
{
NSData *remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
[m_contentView _setAccessibilityWebProcessToken:remoteToken];
}
bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, bool isCharEvent)
{
return [m_contentView _interpretKeyEvent:event.nativeEvent() isCharEvent:isCharEvent];
}
void PageClientImpl::positionInformationDidChange(const InteractionInformationAtPosition& info)
{
[m_contentView _positionInformationDidChange:info];
}
void PageClientImpl::saveImageToLibrary(PassRefPtr<SharedBuffer> imageBuffer)
{
RetainPtr<NSData> imageData = imageBuffer->createNSData();
UIImageDataWriteToSavedPhotosAlbum(imageData.get(), nil, NULL, NULL);
}
bool PageClientImpl::executeSavedCommandBySelector(const String&)
{
notImplemented();
return false;
}
void PageClientImpl::setDragImage(const IntPoint&, PassRefPtr<ShareableBitmap>, bool)
{
notImplemented();
}
void PageClientImpl::selectionDidChange()
{
[m_contentView _selectionChanged];
}
void PageClientImpl::updateSecureInputState()
{
notImplemented();
}
void PageClientImpl::resetSecureInputState()
{
notImplemented();
}
void PageClientImpl::notifyInputContextAboutDiscardedComposition()
{
notImplemented();
}
void PageClientImpl::makeFirstResponder()
{
notImplemented();
}
FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
{
notImplemented();
return FloatRect();
}
FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
{
return rect;
}
IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
{
return IntPoint([m_contentView convertPoint:point fromView:nil]);
}
IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
{
return enclosingIntRect([m_contentView convertRect:rect toView:nil]);
}
IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
{
CGPoint rootViewPoint = point;
if ([m_contentView respondsToSelector:@selector(accessibilityConvertPointFromSceneReferenceCoordinates:)])
rootViewPoint = [m_contentView accessibilityConvertPointFromSceneReferenceCoordinates:rootViewPoint];
return IntPoint(rootViewPoint);
}
IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
{
CGRect rootViewRect = rect;
if ([m_contentView respondsToSelector:@selector(accessibilityConvertRectToSceneReferenceCoordinates:)])
rootViewRect = [m_contentView accessibilityConvertRectToSceneReferenceCoordinates:rootViewRect];
return enclosingIntRect(rootViewRect);
}
void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
{
notImplemented();
}
#if ENABLE(TOUCH_EVENTS)
void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& nativeWebtouchEvent, bool eventHandled)
{
[m_contentView _webTouchEvent:nativeWebtouchEvent preventsNativeGestures:eventHandled];
}
#endif
PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy*)
{
notImplemented();
return 0;
}
PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy*)
{
notImplemented();
return 0;
}
void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut, bool animate)
{
[m_contentView _setFindIndicator:findIndicator fadeOut:fadeOut animate:animate];
}
void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
{
}
void PageClientImpl::exitAcceleratedCompositingMode()
{
notImplemented();
}
void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&)
{
}
void PageClientImpl::setAcceleratedCompositingRootLayer(LayerOrView *rootLayer)
{
[m_contentView _setAcceleratedCompositingRootView:rootLayer];
}
LayerOrView *PageClientImpl::acceleratedCompositingRootLayer() const
{
notImplemented();
return nullptr;
}
ViewSnapshot PageClientImpl::takeViewSnapshot()
{
return [m_webView _takeViewSnapshot];
}
void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
{
notImplemented();
}
void PageClientImpl::clearCustomSwipeViews()
{
notImplemented();
}
void PageClientImpl::commitPotentialTapFailed()
{
[m_contentView _commitPotentialTapFailed];
}
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)
{
[m_contentView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
}
void PageClientImpl::didCommitLayerTree(const RemoteLayerTreeTransaction& layerTreeTransaction)
{
[m_contentView _didCommitLayerTree:layerTreeTransaction];
}
void PageClientImpl::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition)
{
[m_webView _dynamicViewportUpdateChangedTargetToScale:newScale position:newScrollPosition];
}
void PageClientImpl::startAssistingNode(const AssistedNodeInformation& nodeInformation, bool userIsInteracting, bool blurPreviousNode, API::Object* userData)
{
MESSAGE_CHECK(!userData || userData->type() == API::Object::Type::Data);
NSObject <NSSecureCoding> *userObject = nil;
if (API::Data* data = static_cast<API::Data*>(userData)) {
auto nsData = adoptNS([[NSData alloc] initWithBytesNoCopy:const_cast<void*>(static_cast<const void*>(data->bytes())) length:data->size() freeWhenDone:NO]);
auto unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:nsData.get()]);
[unarchiver setRequiresSecureCoding:YES];
@try {
userObject = [unarchiver decodeObjectOfClass:[NSObject class] forKey:@"userObject"];
} @catch (NSException *exception) {
LOG_ERROR("Failed to decode user data: %@", exception);
}
}
[m_contentView _startAssistingNode:nodeInformation userIsInteracting:userIsInteracting blurPreviousNode:blurPreviousNode userObject:userObject];
}
void PageClientImpl::stopAssistingNode()
{
[m_contentView _stopAssistingNode];
}
void PageClientImpl::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
{
[m_contentView _didUpdateBlockSelectionWithTouch:(SelectionTouch)touch withFlags:(SelectionFlags)flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
}
void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
{
[m_contentView _showPlaybackTargetPicker:hasVideo fromRect:elementRect];
}
bool PageClientImpl::handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, WebOpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener)
{
[m_contentView _showRunOpenPanel:parameters resultListener:listener];
return true;
}
#if ENABLE(INSPECTOR)
void PageClientImpl::showInspectorIndication()
{
[m_webView _showInspectorIndication];
}
void PageClientImpl::hideInspectorIndication()
{
[m_webView _hideInspectorIndication];
}
#endif
#if ENABLE(FULLSCREEN_API)
WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
{
return *this;
}
// WebFullScreenManagerProxyClient
void PageClientImpl::closeFullScreenManager()
{
}
bool PageClientImpl::isFullScreen()
{
return false;
}
void PageClientImpl::enterFullScreen()
{
}
void PageClientImpl::exitFullScreen()
{
}
void PageClientImpl::beganEnterFullScreen(const IntRect&, const IntRect&)
{
}
void PageClientImpl::beganExitFullScreen(const IntRect&, const IntRect&)
{
}
#endif // ENABLE(FULLSCREEN_API)
void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
{
RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytes:dataReference.data() length:dataReference.size()]);
[m_webView _didFinishLoadingDataForCustomContentProviderWithSuggestedFilename:suggestedFilename data:data.get()];
}
void PageClientImpl::zoomToRect(FloatRect rect, double minimumScale, double maximumScale)
{
[m_contentView _zoomToRect:rect withOrigin:rect.center() fitEntireRect:YES minimumScale:minimumScale maximumScale:maximumScale minimumScrollDistance:0];
}
void PageClientImpl::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
{
RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(kCFAllocatorDefault, pdfData.data(), pdfData.size()));
RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(data.get()));
m_webView._printedDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get())).get();
}
} // namespace WebKit
#endif // PLATFORM(IOS)