f0748a652173603880889c010e751e5fe91a5358
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / 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 "PageClientImplIOS.h"
30 #import "RemoteLayerTreeDrawingAreaProxy.h"
31 #import "UIWKRemoteView.h"
32 #import "WKBrowsingContextControllerInternal.h"
33 #import "WKBrowsingContextGroupPrivate.h"
34 #import "WKGeolocationProviderIOS.h"
35 #import "WKInteractionView.h"
36 #import "WKProcessGroupInternal.h"
37 #import "WebContext.h"
38 #import "WebFrameProxy.h"
39 #import "WebPageGroup.h"
40 #import "WebSystemInterface.h"
41 #import <QuartzCore/CALayerHost.h>
42 #import <UIKit/UIWindow_Private.h>
43 #import <WebCore/ViewportArguments.h>
44 #import <WebCore/WebCoreThreadSystemInterface.h>
45 #import <wtf/RetainPtr.h>
46
47 using namespace WebCore;
48 using namespace WebKit;
49
50 @implementation WKContentView {
51     std::unique_ptr<PageClientImpl> _pageClient;
52     RefPtr<WebPageProxy> _page;
53
54     RetainPtr<UIView> _rootContentView;
55     RetainPtr<WKInteractionView> _interactionView;
56 }
57
58 - (id)initWithCoder:(NSCoder *)coder
59 {
60     // FIXME: Implement.
61     [self release];
62     return nil;
63 }
64
65 - (id)initWithFrame:(CGRect)frame processGroup:(WKProcessGroup *)processGroup browsingContextGroup:(WKBrowsingContextGroup *)browsingContextGroup
66 {
67     if (!(self = [super initWithFrame:frame]))
68         return nil;
69
70     [self _commonInitializationWithContextRef:processGroup._contextRef pageGroupRef:browsingContextGroup._pageGroupRef relatedToPage:nullptr];
71     return self;
72 }
73
74 - (void)dealloc
75 {
76     _page->close();
77
78     WebContext::statistics().wkViewCount--;
79
80     [super dealloc];
81 }
82
83 - (void)willMoveToWindow:(UIWindow *)newWindow
84 {
85     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
86     UIWindow *window = self.window;
87
88     if (window)
89         [defaultCenter removeObserver:self name:UIWindowDidMoveToScreenNotification object:window];
90
91     if (newWindow)
92         [defaultCenter addObserver:self selector:@selector(_windowDidMoveToScreenNotification:) name:UIWindowDidMoveToScreenNotification object:newWindow];
93 }
94
95 - (void)didMoveToWindow
96 {
97     if (self.window)
98         [self _updateForScreen:self.window.screen];
99     _page->viewStateDidChange(ViewState::IsInWindow);
100 }
101
102 - (WKBrowsingContextController *)browsingContextController
103 {
104     return wrapper(*_page);
105 }
106
107 - (WKContentType)contentType
108 {
109     if (_page->mainFrame()->mimeType() == "text/plain")
110         return WKContentType::PlainText;
111     else if (_page->mainFrame()->isDisplayingStandaloneImageDocument())
112         return WKContentType::Image;
113     return WKContentType::Standard;
114 }
115
116 - (void)setMinimumSize:(CGSize)size
117 {
118     _page->drawingArea()->setSize(IntSize(size), IntSize(), IntSize());
119 }
120
121 - (void)setViewportSize:(CGSize)size
122 {
123     _page->setFixedLayoutSize(IntSize(size));
124 }
125
126 - (void)didScrollTo:(CGPoint)contentOffset
127 {
128     _page->didFinishScrolling(contentOffset);
129 }
130
131 - (void)didZoomToScale:(CGFloat)scale
132 {
133     _page->didFinishZooming(scale);
134 }
135
136 #pragma mark Internal
137
138 - (void)_commonInitializationWithContextRef:(WKContextRef)contextRef pageGroupRef:(WKPageGroupRef)pageGroupRef relatedToPage:(WKPageRef)relatedPage
139 {
140     // FIXME: This should not be necessary, find why hit testing does not work otherwise.
141     // <rdar://problem/12287363>
142     self.backgroundColor = [UIColor blackColor];
143
144     InitWebCoreThreadSystemInterface();
145     InitWebCoreSystemInterface();
146     RunLoop::initializeMainRunLoop();
147
148     _pageClient = std::make_unique<PageClientImpl>(self);
149     _page = toImpl(contextRef)->createWebPage(*_pageClient, toImpl(pageGroupRef), toImpl(relatedPage));
150     _page->initializeWebPage();
151     _page->setIntrinsicDeviceScaleFactor([UIScreen mainScreen].scale);
152     _page->setUseFixedLayout(true);
153
154     WebContext::statistics().wkViewCount++;
155
156     _rootContentView = adoptNS([[UIView alloc] init]);
157     [[_rootContentView layer] setMasksToBounds:NO];
158     [_rootContentView setUserInteractionEnabled:NO];
159
160     [self addSubview:_rootContentView.get()];
161
162     _interactionView = adoptNS([[WKInteractionView alloc] init]);
163     [_interactionView setPage:_page];
164     [self addSubview:_interactionView.get()];
165 }
166
167 - (void)_windowDidMoveToScreenNotification:(NSNotification *)notification
168 {
169     ASSERT(notification.object == self.window);
170
171     UIScreen *screen = notification.userInfo[UIWindowNewScreenUserInfoKey];
172     [self _updateForScreen:screen];
173 }
174
175 - (void)_updateForScreen:(UIScreen *)screen
176 {
177     ASSERT(screen);
178     _page->setIntrinsicDeviceScaleFactor(screen.scale);
179 }
180
181 #pragma mark PageClientImpl methods
182
183 - (std::unique_ptr<DrawingAreaProxy>)_createDrawingAreaProxy
184 {
185     return std::make_unique<RemoteLayerTreeDrawingAreaProxy>(_page.get());
186 }
187
188 - (void)_processDidCrash
189 {
190     // FIXME: Implement.
191 }
192
193 - (void)_didRelaunchProcess
194 {
195     // FIXME: Implement.
196 }
197
198 - (void)_didCommitLoadForMainFrame
199 {
200     if ([_delegate respondsToSelector:@selector(contentViewDidCommitLoadForMainFrame:)])
201         [_delegate contentViewDidCommitLoadForMainFrame:self];
202 }
203
204 - (void)_didChangeContentSize:(CGSize)contentsSize
205 {
206     [self setBounds:{CGPointZero, contentsSize}];
207     [_interactionView setFrame:CGRectMake(0, 0, contentsSize.width, contentsSize.height)];
208     [_rootContentView setFrame:CGRectMake(0, 0, contentsSize.width, contentsSize.height)];
209
210     if ([_delegate respondsToSelector:@selector(contentView:contentsSizeDidChange:)])
211         [_delegate contentView:self contentsSizeDidChange:contentsSize];
212 }
213
214 - (void)_didReceiveMobileDocTypeForMainFrame
215 {
216     if ([_delegate respondsToSelector:@selector(contentViewDidReceiveMobileDocType:)])
217         [_delegate contentViewDidReceiveMobileDocType:self];
218 }
219
220 - (void)_didChangeViewportArguments:(const WebCore::ViewportArguments&)arguments
221 {
222     if ([_delegate respondsToSelector:@selector(contentView:didChangeViewportArgumentsSize:initialScale:minimumScale:maximumScale:allowsUserScaling:)])
223         [_delegate contentView:self didChangeViewportArgumentsSize:CGSizeMake(arguments.width, arguments.height) initialScale:arguments.zoom minimumScale:arguments.minZoom maximumScale:arguments.maxZoom allowsUserScaling:arguments.userZoom];
224 }
225
226 - (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
227 {
228     [_interactionView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
229 }
230
231 - (void)_setAcceleratedCompositingRootLayer:(CALayer *)rootLayer
232 {
233     [[_rootContentView layer] setSublayers:@[rootLayer]];
234 }
235
236 // FIXME: change the name. Leave it for now to make it easier to refer to the UIKit implementation.
237 - (void)_startAssistingNode
238 {
239     [_interactionView _startAssistingNode];
240 }
241
242 - (void)_stopAssistingNode
243 {
244     [_interactionView _stopAssistingNode];
245 }
246
247 - (void)_selectionChanged
248 {
249     [_interactionView _selectionChanged];
250 }
251
252 - (BOOL)_interpretKeyEvent:(WebIOSEvent *)theEvent isCharEvent:(BOOL)isCharEvent
253 {
254     return [_interactionView _interpretKeyEvent:theEvent isCharEvent:isCharEvent];
255 }
256
257 - (void)_decidePolicyForGeolocationRequestFromOrigin:(WebSecurityOrigin&)origin frame:(WebFrameProxy&)frame request:(GeolocationPermissionRequestProxy&)permissionRequest
258 {
259     [[wrapper(_page->process().context()) _geolocationProvider] decidePolicyForGeolocationRequestFromOrigin:toAPI(&origin) frame:toAPI(&frame) request:toAPI(&permissionRequest) window:[self window]];
260 }
261
262 @end
263
264 @implementation WKContentView (Private)
265
266 - (WKPageRef)_pageRef
267 {
268     return toAPI(_page.get());
269 }
270
271 - (id)initWithFrame:(CGRect)frame contextRef:(WKContextRef)contextRef pageGroupRef:(WKPageGroupRef)pageGroupRef
272 {
273     return [self initWithFrame:frame contextRef:contextRef pageGroupRef:pageGroupRef relatedToPage:nullptr];
274 }
275
276 - (id)initWithFrame:(CGRect)frame contextRef:(WKContextRef)contextRef pageGroupRef:(WKPageGroupRef)pageGroupRef relatedToPage:(WKPageRef)relatedPage
277 {
278     if (!(self = [super initWithFrame:frame]))
279         return nil;
280
281     [self _commonInitializationWithContextRef:contextRef pageGroupRef:pageGroupRef relatedToPage:relatedPage];
282     return self;
283 }
284
285 @end