Rename WKProcessClass to WKProcessPool
[WebKit-https.git] / Source / WebKit2 / UIProcess / ios / WKContentView.mm
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #import "config.h"
27 #import "WKContentViewInternal.h"
28
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>
49
50 #if USE(IOSURFACE)
51 #import <IOSurface/IOSurface.h>
52 #endif
53
54 #if __has_include(<QuartzCore/QuartzCorePrivate.h>)
55 #import <QuartzCore/QuartzCorePrivate.h>
56 #endif
57
58 @interface CALayer (Details)
59 @property BOOL hitTestsAsOpaque;
60 @end
61
62 using namespace WebCore;
63 using namespace WebKit;
64
65 @implementation WKContentView {
66     std::unique_ptr<PageClientImpl> _pageClient;
67     RetainPtr<WKBrowsingContextController> _browsingContextController;
68
69     RetainPtr<UIView> _rootContentView;
70     RetainPtr<WKInteractionView> _interactionView;
71 }
72
73 - (instancetype)initWithFrame:(CGRect)frame context:(WebKit::WebContext&)context configuration:(WebKit::WebPageConfiguration)webPageConfiguration
74 {
75     if (!(self = [super initWithFrame:frame]))
76         return nil;
77
78     InitializeWebKit2();
79
80     _pageClient = std::make_unique<PageClientImpl>(self);
81
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);
87
88     WebContext::statistics().wkViewCount++;
89
90     _rootContentView = adoptNS([[UIView alloc] init]);
91     [_rootContentView layer].masksToBounds = NO;
92     [_rootContentView setUserInteractionEnabled:NO];
93
94     [self addSubview:_rootContentView.get()];
95
96     _interactionView = adoptNS([[WKInteractionView alloc] init]);
97     [_interactionView setPage:_page];
98     [self addSubview:_interactionView.get()];
99
100     self.layer.hitTestsAsOpaque = YES;
101
102     return self;
103 }
104
105 - (void)dealloc
106 {
107     _page->close();
108
109     WebContext::statistics().wkViewCount--;
110
111     [super dealloc];
112 }
113
114 - (void)willMoveToWindow:(UIWindow *)newWindow
115 {
116     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
117     UIWindow *window = self.window;
118
119     if (window)
120         [defaultCenter removeObserver:self name:UIWindowDidMoveToScreenNotification object:window];
121
122     if (newWindow)
123         [defaultCenter addObserver:self selector:@selector(_windowDidMoveToScreenNotification:) name:UIWindowDidMoveToScreenNotification object:newWindow];
124 }
125
126 - (void)didMoveToWindow
127 {
128     if (self.window)
129         [self _updateForScreen:self.window.screen];
130     _page->viewStateDidChange(ViewState::IsInWindow);
131 }
132
133 - (WKBrowsingContextController *)browsingContextController
134 {
135     if (!_browsingContextController)
136         _browsingContextController = [[WKBrowsingContextController alloc] _initWithPageRef:toAPI(_page.get())];
137
138     return _browsingContextController.get();
139 }
140
141 - (WKPageRef)_pageRef
142 {
143     return toAPI(_page.get());
144 }
145
146 - (BOOL)isAssistingNode
147 {
148     return [_interactionView isEditable];
149 }
150
151 - (void)didUpdateVisibleRect:(CGRect)visibleRect unobscuredRect:(CGRect)unobscuredRect scale:(CGFloat)scale
152 {
153     _page->setUnobscuredContentRect(unobscuredRect);
154     _page->scrollingCoordinatorProxy()->scrollPositionChangedViaDelegatedScrolling(_page->scrollingCoordinatorProxy()->rootScrollingNodeID(), roundedIntPoint(unobscuredRect.origin));
155
156     if (auto drawingArea = _page->drawingArea()) {
157         FloatRect exposedRect = visibleRect;
158         exposedRect.scale(scale);
159         drawingArea->setExposedRect(exposedRect);
160     }
161
162     [self _updateFixedPositionRect];
163 }
164
165 - (void)setMinimumSize:(CGSize)size
166 {
167     _page->drawingArea()->setSize(IntSize(size), IntSize(), IntSize());
168 }
169
170 - (FloatRect)fixedPositionRectFromExposedRect:(FloatRect)exposedRect scale:(float)scale
171 {
172     // FIXME: This should modify the rect based on the scale.
173     UNUSED_PARAM(scale);
174     return exposedRect;
175 }
176
177 - (void)_updateFixedPositionRect
178 {
179     auto drawingArea = _page->drawingArea();
180     if (!drawingArea)
181         return;
182     FloatRect fixedPosRect = [self fixedPositionRectFromExposedRect:_page->unobscuredContentRect() scale:_page->pageScaleFactor()];
183     drawingArea->setCustomFixedPositionRect(fixedPosRect);
184 }
185
186 - (void)setMinimumLayoutSize:(CGSize)size
187 {
188     _page->setViewportConfigurationMinimumLayoutSize(IntSize(CGCeiling(size.width), CGCeiling(size.height)));
189 }
190
191 - (void)didFinishScrolling
192 {
193     [self _updateFixedPositionRect];
194     [_interactionView _didEndScrollingOrZooming];
195 }
196
197 - (void)willStartZoomOrScroll
198 {
199     [_interactionView _willStartScrollingOrZooming];
200 }
201
202 - (void)willStartUserTriggeredScroll
203 {
204     [_interactionView _willStartUserTriggeredScrollingOrZooming];
205 }
206
207 - (void)willStartUserTriggeredZoom
208 {
209     [_interactionView _willStartUserTriggeredScrollingOrZooming];
210     _page->willStartUserTriggeredZooming();
211 }
212
213 - (void)didZoomToScale:(CGFloat)scale
214 {
215     _page->didFinishZooming(scale);
216     [_interactionView _didEndScrollingOrZooming];
217 }
218
219 #pragma mark Internal
220
221 - (void)_windowDidMoveToScreenNotification:(NSNotification *)notification
222 {
223     ASSERT(notification.object == self.window);
224
225     UIScreen *screen = notification.userInfo[UIWindowNewScreenUserInfoKey];
226     [self _updateForScreen:screen];
227 }
228
229 - (void)_updateForScreen:(UIScreen *)screen
230 {
231     ASSERT(screen);
232     _page->setIntrinsicDeviceScaleFactor(screen.scale);
233 }
234
235 #pragma mark PageClientImpl methods
236
237 - (std::unique_ptr<DrawingAreaProxy>)_createDrawingAreaProxy
238 {
239     return std::make_unique<RemoteLayerTreeDrawingAreaProxy>(_page.get());
240 }
241
242 - (void)_processDidExit
243 {
244     // FIXME: Implement.
245 }
246
247 - (void)_didRelaunchProcess
248 {
249     // FIXME: Implement.
250 }
251
252 - (void)_didCommitLoadForMainFrame
253 {
254     if ([_delegate respondsToSelector:@selector(contentViewDidCommitLoadForMainFrame:)])
255         [_delegate contentViewDidCommitLoadForMainFrame:self];
256     [_interactionView _stopAssistingNode];
257 }
258
259 - (void)_didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&)layerTreeTransaction
260 {
261     CGSize contentsSize = layerTreeTransaction.contentsSize();
262
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)];
266
267     if ([_delegate respondsToSelector:@selector(contentView:didCommitLayerTree:)])
268         [_delegate contentView:self didCommitLayerTree:layerTreeTransaction];
269 }
270
271 - (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
272 {
273     [_interactionView _webTouchEvent:touchEvent preventsNativeGestures:preventsNativeGesture];
274 }
275
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
277 {
278     [_interactionView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
279 }
280
281 - (void)_setAcceleratedCompositingRootLayer:(CALayer *)rootLayer
282 {
283     [[_rootContentView layer] setSublayers:@[rootLayer]];
284 }
285
286 // FIXME: change the name. Leave it for now to make it easier to refer to the UIKit implementation.
287 - (void)_startAssistingNode
288 {
289     [_interactionView _startAssistingNode];
290 }
291
292 - (void)_stopAssistingNode
293 {
294     [_interactionView _stopAssistingNode];
295 }
296
297 - (void)_selectionChanged
298 {
299     [_interactionView _selectionChanged];
300 }
301
302 - (void)_didUpdateBlockSelectionWithTouch:(WKSelectionTouch)touch withFlags:(WKSelectionFlags)flags growThreshold:(CGFloat)growThreshold shrinkThreshold:(CGFloat)shrinkThreshold
303 {
304     [_interactionView _didUpdateBlockSelectionWithTouch:touch withFlags:flags growThreshold:growThreshold shrinkThreshold:shrinkThreshold];
305 }
306
307 - (BOOL)_interpretKeyEvent:(WebIOSEvent *)theEvent isCharEvent:(BOOL)isCharEvent
308 {
309     return [_interactionView _interpretKeyEvent:theEvent isCharEvent:isCharEvent];
310 }
311
312 - (void)_positionInformationDidChange:(const InteractionInformationAtPosition&)info
313 {
314     [_interactionView _positionInformationDidChange:info];
315 }
316
317 - (void)_decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin&)origin frame:(WebFrameProxy&)frame request:(GeolocationPermissionRequestProxy&)permissionRequest
318 {
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]];
322 }
323
324 - (RetainPtr<CGImageRef>)_takeViewSnapshot
325 {
326     return [_delegate takeViewSnapshotForContentView:self];
327 }
328
329 @end