2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #import "PageClientImplIOS.h"
32 #import "DataReference.h"
33 #import "DownloadProxy.h"
34 #import "FindIndicator.h"
35 #import "InteractionInformationAtPosition.h"
36 #import "NativeWebKeyboardEvent.h"
37 #import "NavigationState.h"
38 #import "ViewSnapshotStore.h"
39 #import "WKContentView.h"
40 #import "WKContentViewInteraction.h"
41 #import "WKWebViewConfigurationInternal.h"
42 #import "WKWebViewContentProviderRegistry.h"
43 #import "WKWebViewInternal.h"
44 #import "WebContextMenuProxy.h"
45 #import "WebEditCommandProxy.h"
46 #import "WebProcessProxy.h"
47 #import "_WKDownloadInternal.h"
48 #import <UIKit/UIImagePickerController_Private.h>
49 #import <UIKit/UIWebTouchEventsGestureRecognizer.h>
50 #import <WebCore/NotImplemented.h>
51 #import <WebCore/PlatformScreen.h>
52 #import <WebCore/SharedBuffer.h>
54 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_webView->_page->process().connection())
56 @interface UIView (IPI)
57 - (UIScrollView *)_scroller;
58 - (CGPoint)accessibilityConvertPointFromSceneReferenceCoordinates:(CGPoint)point;
59 - (CGRect)accessibilityConvertRectToSceneReferenceCoordinates:(CGRect)rect;
62 using namespace WebCore;
63 using namespace WebKit;
65 @interface WKEditCommandObjC : NSObject
67 RefPtr<WebEditCommandProxy> m_command;
69 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command;
70 - (WebEditCommandProxy*)command;
73 @interface WKEditorUndoTargetObjC : NSObject
74 - (void)undoEditing:(id)sender;
75 - (void)redoEditing:(id)sender;
78 @implementation WKEditCommandObjC
80 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command
90 - (WebEditCommandProxy *)command
92 return m_command.get();
97 @implementation WKEditorUndoTargetObjC
99 - (void)undoEditing:(id)sender
101 ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
102 [sender command]->unapply();
105 - (void)redoEditing:(id)sender
107 ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
108 [sender command]->reapply();
115 PageClientImpl::PageClientImpl(WKContentView *contentView, WKWebView *webView)
116 : m_contentView(contentView)
118 , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
122 PageClientImpl::~PageClientImpl()
126 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
128 return [m_contentView _createDrawingAreaProxy];
131 void PageClientImpl::setViewNeedsDisplay(const IntRect& rect)
133 ASSERT_NOT_REACHED();
136 void PageClientImpl::displayView()
138 ASSERT_NOT_REACHED();
141 bool PageClientImpl::canScrollView()
147 void PageClientImpl::scrollView(const IntRect&, const IntSize&)
149 ASSERT_NOT_REACHED();
152 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
154 UNUSED_PARAM(isProgrammaticScroll);
155 [m_webView _scrollToContentOffset:scrollPosition];
158 IntSize PageClientImpl::viewSize()
160 if (UIScrollView *scroller = [m_contentView _scroller])
161 return IntSize(scroller.bounds.size);
163 return IntSize(m_contentView.bounds.size);
166 bool PageClientImpl::isViewWindowActive()
168 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
169 return isViewVisible();
172 bool PageClientImpl::isViewFocused()
174 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
175 return isViewWindowActive();
178 bool PageClientImpl::isViewVisible()
180 return isViewInWindow() && !m_contentView.isBackground;
183 bool PageClientImpl::isViewInWindow()
185 // FIXME: in WebKitTestRunner, m_webView is nil, so check the content view instead.
187 return [m_webView window];
189 return [m_contentView window];
192 bool PageClientImpl::isViewVisibleOrOccluded()
194 return isViewVisible();
197 bool PageClientImpl::isVisuallyIdle()
199 return !isViewVisible();
202 void PageClientImpl::processDidExit()
204 [m_contentView _processDidExit];
205 [m_webView _processDidExit];
208 void PageClientImpl::didRelaunchProcess()
210 [m_contentView _didRelaunchProcess];
211 [m_webView _didRelaunchProcess];
214 void PageClientImpl::pageClosed()
219 void PageClientImpl::preferencesDidChange()
224 void PageClientImpl::toolTipChanged(const String&, const String&)
229 bool PageClientImpl::decidePolicyForGeolocationPermissionRequest(WebFrameProxy& frame, WebSecurityOrigin& origin, GeolocationPermissionRequestProxy& request)
231 [m_contentView _decidePolicyForGeolocationRequestFromOrigin:origin frame:frame request:request];
235 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
237 [m_webView _setHasCustomContentView:useCustomContentProvider loadedMIMEType:mimeType];
238 [m_contentView _didCommitLoadForMainFrame];
241 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
243 ASSERT_ARG(download, download);
244 ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
245 [static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
248 void PageClientImpl::didChangeViewportMetaTagWidth(float newWidth)
250 [m_webView _setViewportMetaTagWidth:newWidth];
253 void PageClientImpl::setUsesMinimalUI(bool usesMinimalUI)
255 [m_webView _setUsesMinimalUI:usesMinimalUI];
258 double PageClientImpl::minimumZoomScale() const
260 if (UIScrollView *scroller = [m_webView scrollView])
261 return scroller.minimumZoomScale;
266 WebCore::FloatSize PageClientImpl::contentsSize() const
268 return FloatSize([m_contentView bounds].size);
271 void PageClientImpl::setCursor(const Cursor&)
276 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool)
281 void PageClientImpl::didChangeViewportProperties(const ViewportAttributes&)
286 void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
288 RefPtr<WebEditCommandProxy> command = prpCommand;
290 RetainPtr<WKEditCommandObjC> commandObjC = adoptNS([[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]);
291 String actionName = WebEditCommandProxy::nameForEditAction(command->editAction());
293 NSUndoManager *undoManager = [m_contentView undoManager];
294 [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
295 if (!actionName.isEmpty())
296 [undoManager setActionName:(NSString *)actionName];
299 #if USE(INSERTION_UNDO_GROUPING)
300 void PageClientImpl::registerInsertionUndoGrouping()
306 void PageClientImpl::clearAllEditCommands()
308 [[m_contentView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
311 bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
313 return (undoOrRedo == WebPageProxy::Undo) ? [[m_contentView undoManager] canUndo] : [[m_contentView undoManager] canRedo];
316 void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
318 return (undoOrRedo == WebPageProxy::Undo) ? [[m_contentView undoManager] undo] : [[m_contentView undoManager] redo];
321 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
323 NSData *remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
324 [m_contentView _setAccessibilityWebProcessToken:remoteToken];
327 bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, bool isCharEvent)
329 return [m_contentView _interpretKeyEvent:event.nativeEvent() isCharEvent:isCharEvent];
332 void PageClientImpl::positionInformationDidChange(const InteractionInformationAtPosition& info)
334 [m_contentView _positionInformationDidChange:info];
337 void PageClientImpl::saveImageToLibrary(PassRefPtr<SharedBuffer> imageBuffer)
339 RetainPtr<NSData> imageData = imageBuffer->createNSData();
340 UIImageDataWriteToSavedPhotosAlbum(imageData.get(), nil, NULL, NULL);
343 bool PageClientImpl::executeSavedCommandBySelector(const String&)
349 void PageClientImpl::setDragImage(const IntPoint&, PassRefPtr<ShareableBitmap>, bool)
354 void PageClientImpl::selectionDidChange()
356 [m_contentView _selectionChanged];
359 void PageClientImpl::updateSecureInputState()
364 void PageClientImpl::resetSecureInputState()
369 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
374 void PageClientImpl::makeFirstResponder()
379 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
385 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
391 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
393 return IntPoint([m_contentView convertPoint:point fromView:nil]);
396 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
398 return enclosingIntRect([m_contentView convertRect:rect toView:nil]);
401 IntPoint PageClientImpl::accessibilityScreenToRootView(const IntPoint& point)
403 CGPoint rootViewPoint = point;
404 if ([m_contentView respondsToSelector:@selector(accessibilityConvertPointFromSceneReferenceCoordinates:)])
405 rootViewPoint = [m_contentView accessibilityConvertPointFromSceneReferenceCoordinates:rootViewPoint];
406 return IntPoint(rootViewPoint);
409 IntRect PageClientImpl::rootViewToAccessibilityScreen(const IntRect& rect)
411 CGRect rootViewRect = rect;
412 if ([m_contentView respondsToSelector:@selector(accessibilityConvertRectToSceneReferenceCoordinates:)])
413 rootViewRect = [m_contentView accessibilityConvertRectToSceneReferenceCoordinates:rootViewRect];
414 return enclosingIntRect(rootViewRect);
417 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool)
419 [m_contentView _didHandleKeyEvent:event.nativeEvent()];
422 #if ENABLE(TOUCH_EVENTS)
423 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& nativeWebtouchEvent, bool eventHandled)
425 [m_contentView _webTouchEvent:nativeWebtouchEvent preventsNativeGestures:eventHandled];
429 PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy*)
435 PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy*)
441 void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut, bool animate)
445 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
449 void PageClientImpl::exitAcceleratedCompositingMode()
454 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext&)
458 void PageClientImpl::setAcceleratedCompositingRootLayer(LayerOrView *rootLayer)
460 [m_contentView _setAcceleratedCompositingRootView:rootLayer];
463 LayerOrView *PageClientImpl::acceleratedCompositingRootLayer() const
469 PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
471 return [m_webView _takeViewSnapshot];
474 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
479 void PageClientImpl::clearCustomSwipeViews()
484 void PageClientImpl::commitPotentialTapFailed()
486 [m_contentView _commitPotentialTapFailed];
489 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)
491 [m_contentView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
494 void PageClientImpl::didCommitLayerTree(const RemoteLayerTreeTransaction& layerTreeTransaction)
496 [m_contentView _didCommitLayerTree:layerTreeTransaction];
499 void PageClientImpl::dynamicViewportUpdateChangedTarget(double newScale, const WebCore::FloatPoint& newScrollPosition, uint64_t nextValidLayerTreeTransactionID)
501 [m_webView _dynamicViewportUpdateChangedTargetToScale:newScale position:newScrollPosition nextValidLayerTreeTransactionID:nextValidLayerTreeTransactionID];
504 void PageClientImpl::restorePageState(const WebCore::FloatRect& exposedRect, double scale)
506 [m_webView _restorePageStateToExposedRect:exposedRect scale:scale];
509 void PageClientImpl::restorePageCenterAndScale(const WebCore::FloatPoint& center, double scale)
511 [m_webView _restorePageStateToUnobscuredCenter:center scale:scale];
514 void PageClientImpl::startAssistingNode(const AssistedNodeInformation& nodeInformation, bool userIsInteracting, bool blurPreviousNode, API::Object* userData)
516 MESSAGE_CHECK(!userData || userData->type() == API::Object::Type::Data);
518 NSObject <NSSecureCoding> *userObject = nil;
519 if (API::Data* data = static_cast<API::Data*>(userData)) {
520 auto nsData = adoptNS([[NSData alloc] initWithBytesNoCopy:const_cast<void*>(static_cast<const void*>(data->bytes())) length:data->size() freeWhenDone:NO]);
521 auto unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:nsData.get()]);
522 [unarchiver setRequiresSecureCoding:YES];
524 userObject = [unarchiver decodeObjectOfClass:[NSObject class] forKey:@"userObject"];
525 } @catch (NSException *exception) {
526 LOG_ERROR("Failed to decode user data: %@", exception);
530 [m_contentView _startAssistingNode:nodeInformation userIsInteracting:userIsInteracting blurPreviousNode:blurPreviousNode userObject:userObject];
533 bool PageClientImpl::isAssistingNode()
535 return [m_contentView isAssistingNode];
538 void PageClientImpl::stopAssistingNode()
540 [m_contentView _stopAssistingNode];
543 void PageClientImpl::didUpdateBlockSelectionWithTouch(uint32_t touch, uint32_t flags, float growThreshold, float shrinkThreshold)
545 [m_contentView _didUpdateBlockSelectionWithTouch:(SelectionTouch)touch withFlags:(SelectionFlags)flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
548 void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect)
550 [m_contentView _showPlaybackTargetPicker:hasVideo fromRect:elementRect];
553 bool PageClientImpl::handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, WebOpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener)
555 [m_contentView _showRunOpenPanel:parameters resultListener:listener];
559 #if ENABLE(INSPECTOR)
560 void PageClientImpl::showInspectorHighlight(const WebCore::Highlight& highlight)
562 [m_contentView _showInspectorHighlight:highlight];
565 void PageClientImpl::hideInspectorHighlight()
567 [m_contentView _hideInspectorHighlight];
570 void PageClientImpl::showInspectorIndication()
572 [m_contentView setShowingInspectorIndication:YES];
575 void PageClientImpl::hideInspectorIndication()
577 [m_contentView setShowingInspectorIndication:NO];
580 void PageClientImpl::enableInspectorNodeSearch()
582 [m_contentView _enableInspectorNodeSearch];
585 void PageClientImpl::disableInspectorNodeSearch()
587 [m_contentView _disableInspectorNodeSearch];
591 #if ENABLE(FULLSCREEN_API)
593 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
598 // WebFullScreenManagerProxyClient
600 void PageClientImpl::closeFullScreenManager()
604 bool PageClientImpl::isFullScreen()
609 void PageClientImpl::enterFullScreen()
613 void PageClientImpl::exitFullScreen()
617 void PageClientImpl::beganEnterFullScreen(const IntRect&, const IntRect&)
621 void PageClientImpl::beganExitFullScreen(const IntRect&, const IntRect&)
625 #endif // ENABLE(FULLSCREEN_API)
627 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
629 RetainPtr<NSData> data = adoptNS([[NSData alloc] initWithBytes:dataReference.data() length:dataReference.size()]);
630 [m_webView _didFinishLoadingDataForCustomContentProviderWithSuggestedFilename:suggestedFilename data:data.get()];
633 void PageClientImpl::zoomToRect(FloatRect rect, double minimumScale, double maximumScale)
635 [m_contentView _zoomToRect:rect withOrigin:rect.center() fitEntireRect:YES minimumScale:minimumScale maximumScale:maximumScale minimumScrollDistance:0];
638 void PageClientImpl::overflowScrollViewWillStartPanGesture()
640 [m_contentView scrollViewWillStartPanOrPinchGesture];
643 void PageClientImpl::overflowScrollViewDidScroll()
645 [m_contentView _didScroll];
648 void PageClientImpl::overflowScrollWillStartScroll()
650 [m_contentView _overflowScrollingWillBegin];
653 void PageClientImpl::overflowScrollDidEndScroll()
655 [m_contentView _overflowScrollingDidEnd];
658 void PageClientImpl::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
660 RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(kCFAllocatorDefault, pdfData.data(), pdfData.size()));
661 RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(data.get()));
662 m_webView._printedDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get())).get();
665 Vector<String> PageClientImpl::mimeTypesWithCustomContentProviders()
667 return m_webView.configuration._contentProviderRegistry._mimeTypesWithCustomContentProviders;
670 void PageClientImpl::navigationGestureDidBegin()
672 NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidBegin();
675 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
677 NavigationState::fromWebPage(*m_webView->_page).navigationGestureWillEnd(willNavigate, item);
680 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
682 NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidEnd(willNavigate, item);
685 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
687 NavigationState::fromWebPage(*m_webView->_page).willRecordNavigationSnapshot(item);
690 } // namespace WebKit
692 #endif // PLATFORM(IOS)