2 * Copyright (C) 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 "WKContentViewInternal.h"
29 #import "InteractionInformationAtPosition.h"
30 #import "PageClientImplIOS.h"
31 #import "RemoteLayerTreeDrawingAreaProxy.h"
32 #import "RemoteScrollingCoordinatorProxy.h"
33 #import "WebKit2Initialize.h"
34 #import "WKBrowsingContextControllerInternal.h"
35 #import "WKBrowsingContextGroupPrivate.h"
36 #import "WKGeolocationProviderIOS.h"
37 #import "WKInteractionView.h"
38 #import "WKPreferencesInternal.h"
39 #import "WKProcessGroupPrivate.h"
40 #import "WKProcessPoolInternal.h"
41 #import "WKWebViewConfiguration.h"
42 #import "WebContext.h"
43 #import "WebFrameProxy.h"
44 #import "WebPageGroup.h"
45 #import "WebSystemInterface.h"
46 #import <UIKit/UIWindow_Private.h>
47 #import <WebCore/ViewportArguments.h>
48 #import <wtf/RetainPtr.h>
51 #import <IOSurface/IOSurface.h>
54 #if __has_include(<QuartzCore/QuartzCorePrivate.h>)
55 #import <QuartzCore/QuartzCorePrivate.h>
58 @interface CALayer (Details)
59 @property BOOL hitTestsAsOpaque;
62 using namespace WebCore;
63 using namespace WebKit;
65 @implementation WKContentView {
66 std::unique_ptr<PageClientImpl> _pageClient;
67 RetainPtr<WKBrowsingContextController> _browsingContextController;
69 RetainPtr<UIView> _rootContentView;
70 RetainPtr<WKInteractionView> _interactionView;
73 - (instancetype)initWithFrame:(CGRect)frame context:(WebKit::WebContext&)context configuration:(WebKit::WebPageConfiguration)webPageConfiguration
75 if (!(self = [super initWithFrame:frame]))
80 _pageClient = std::make_unique<PageClientImpl>(self);
82 _page = context.createWebPage(*_pageClient, std::move(webPageConfiguration));
83 _page->initializeWebPage();
84 _page->setIntrinsicDeviceScaleFactor([UIScreen mainScreen].scale);
85 _page->setUseFixedLayout(true);
86 _page->setDelegatesScrolling(true);
88 WebContext::statistics().wkViewCount++;
90 _rootContentView = adoptNS([[UIView alloc] init]);
91 [_rootContentView layer].masksToBounds = NO;
92 [_rootContentView setUserInteractionEnabled:NO];
94 [self addSubview:_rootContentView.get()];
96 _interactionView = adoptNS([[WKInteractionView alloc] init]);
97 [_interactionView setPage:_page];
98 [self addSubview:_interactionView.get()];
100 self.layer.hitTestsAsOpaque = YES;
109 WebContext::statistics().wkViewCount--;
114 - (void)willMoveToWindow:(UIWindow *)newWindow
116 NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
117 UIWindow *window = self.window;
120 [defaultCenter removeObserver:self name:UIWindowDidMoveToScreenNotification object:window];
123 [defaultCenter addObserver:self selector:@selector(_windowDidMoveToScreenNotification:) name:UIWindowDidMoveToScreenNotification object:newWindow];
126 - (void)didMoveToWindow
129 [self _updateForScreen:self.window.screen];
130 _page->viewStateDidChange(ViewState::IsInWindow);
133 - (WKBrowsingContextController *)browsingContextController
135 if (!_browsingContextController)
136 _browsingContextController = [[WKBrowsingContextController alloc] _initWithPageRef:toAPI(_page.get())];
138 return _browsingContextController.get();
141 - (WKPageRef)_pageRef
143 return toAPI(_page.get());
146 - (BOOL)isAssistingNode
148 return [_interactionView isEditable];
151 - (void)didUpdateVisibleRect:(CGRect)visibleRect unobscuredRect:(CGRect)unobscuredRect scale:(CGFloat)scale
153 _page->setUnobscuredContentRect(unobscuredRect);
154 _page->scrollingCoordinatorProxy()->scrollPositionChangedViaDelegatedScrolling(_page->scrollingCoordinatorProxy()->rootScrollingNodeID(), roundedIntPoint(unobscuredRect.origin));
156 if (auto drawingArea = _page->drawingArea()) {
157 FloatRect exposedRect = visibleRect;
158 exposedRect.scale(scale);
159 drawingArea->setExposedRect(exposedRect);
162 [self _updateFixedPositionRect];
165 - (void)setMinimumSize:(CGSize)size
167 _page->drawingArea()->setSize(IntSize(size), IntSize(), IntSize());
170 - (FloatRect)fixedPositionRectFromExposedRect:(FloatRect)exposedRect scale:(float)scale
172 // FIXME: This should modify the rect based on the scale.
177 - (void)_updateFixedPositionRect
179 auto drawingArea = _page->drawingArea();
182 FloatRect fixedPosRect = [self fixedPositionRectFromExposedRect:_page->unobscuredContentRect() scale:_page->pageScaleFactor()];
183 drawingArea->setCustomFixedPositionRect(fixedPosRect);
186 - (void)setMinimumLayoutSize:(CGSize)size
188 _page->setViewportConfigurationMinimumLayoutSize(IntSize(CGCeiling(size.width), CGCeiling(size.height)));
191 - (void)didFinishScrolling
193 [self _updateFixedPositionRect];
194 [_interactionView _didEndScrollingOrZooming];
197 - (void)willStartZoomOrScroll
199 [_interactionView _willStartScrollingOrZooming];
202 - (void)willStartUserTriggeredScroll
204 [_interactionView _willStartUserTriggeredScrollingOrZooming];
207 - (void)willStartUserTriggeredZoom
209 [_interactionView _willStartUserTriggeredScrollingOrZooming];
210 _page->willStartUserTriggeredZooming();
213 - (void)didZoomToScale:(CGFloat)scale
215 _page->didFinishZooming(scale);
216 [_interactionView _didEndScrollingOrZooming];
219 #pragma mark Internal
221 - (void)_windowDidMoveToScreenNotification:(NSNotification *)notification
223 ASSERT(notification.object == self.window);
225 UIScreen *screen = notification.userInfo[UIWindowNewScreenUserInfoKey];
226 [self _updateForScreen:screen];
229 - (void)_updateForScreen:(UIScreen *)screen
232 _page->setIntrinsicDeviceScaleFactor(screen.scale);
235 #pragma mark PageClientImpl methods
237 - (std::unique_ptr<DrawingAreaProxy>)_createDrawingAreaProxy
239 return std::make_unique<RemoteLayerTreeDrawingAreaProxy>(_page.get());
242 - (void)_processDidExit
247 - (void)_didRelaunchProcess
252 - (void)_didCommitLoadForMainFrame
254 if ([_delegate respondsToSelector:@selector(contentViewDidCommitLoadForMainFrame:)])
255 [_delegate contentViewDidCommitLoadForMainFrame:self];
256 [_interactionView _stopAssistingNode];
259 - (void)_didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&)layerTreeTransaction
261 CGSize contentsSize = layerTreeTransaction.contentsSize();
263 [self setBounds:{CGPointZero, contentsSize}];
264 [_interactionView setFrame:CGRectMake(0, 0, contentsSize.width, contentsSize.height)];
265 [_rootContentView setFrame:CGRectMake(0, 0, contentsSize.width, contentsSize.height)];
267 if ([_delegate respondsToSelector:@selector(contentView:didCommitLayerTree:)])
268 [_delegate contentView:self didCommitLayerTree:layerTreeTransaction];
271 - (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
273 [_interactionView _webTouchEvent:touchEvent preventsNativeGestures:preventsNativeGesture];
276 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const Color&)color quads:(const Vector<FloatQuad>&)highlightedQuads topLeftRadius:(const IntSize&)topLeftRadius topRightRadius:(const IntSize&)topRightRadius bottomLeftRadius:(const IntSize&)bottomLeftRadius bottomRightRadius:(const IntSize&)bottomRightRadius
278 [_interactionView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
281 - (void)_setAcceleratedCompositingRootLayer:(CALayer *)rootLayer
283 [[_rootContentView layer] setSublayers:@[rootLayer]];
286 // FIXME: change the name. Leave it for now to make it easier to refer to the UIKit implementation.
287 - (void)_startAssistingNode
289 [_interactionView _startAssistingNode];
292 - (void)_stopAssistingNode
294 [_interactionView _stopAssistingNode];
297 - (void)_selectionChanged
299 [_interactionView _selectionChanged];
302 - (void)_didUpdateBlockSelectionWithTouch:(WKSelectionTouch)touch withFlags:(WKSelectionFlags)flags growThreshold:(CGFloat)growThreshold shrinkThreshold:(CGFloat)shrinkThreshold
304 [_interactionView _didUpdateBlockSelectionWithTouch:touch withFlags:flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
307 - (BOOL)_interpretKeyEvent:(WebIOSEvent *)theEvent isCharEvent:(BOOL)isCharEvent
309 return [_interactionView _interpretKeyEvent:theEvent isCharEvent:isCharEvent];
312 - (void)_positionInformationDidChange:(const InteractionInformationAtPosition&)info
314 [_interactionView _positionInformationDidChange:info];
317 - (void)_decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin&)origin frame:(WebFrameProxy&)frame request:(GeolocationPermissionRequestProxy&)permissionRequest
319 // FIXME: The line below is commented out since wrapper(WebContext&) now returns a WKProcessPool.
320 // As part of the new API we should figure out where geolocation fits in, see <rdar://problem/15885544>.
321 // [[wrapper(_page->process().context()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:toAPI(&origin) frame:toAPI(&frame) request:toAPI(&permissionRequest) window:[self window]];
324 - (RetainPtr<CGImageRef>)_takeViewSnapshot
326 return [_delegate takeViewSnapshotForContentView:self];