4670de2eed3b15d31e326049ebdda92f357522c0
[WebKit-https.git] / Tools / WebKitTestRunner / cocoa / TestRunnerWKWebView.mm
1 /*
2  * Copyright (C) 2015 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 "TestRunnerWKWebView.h"
28
29 #import "WebKitTestRunnerDraggingInfo.h"
30 #import <WebKit/WKUIDelegatePrivate.h>
31 #import <wtf/Assertions.h>
32 #import <wtf/RetainPtr.h>
33
34 #if PLATFORM(IOS)
35 #import "UIKitTestSPI.h"
36 #import <WebKit/WKWebViewPrivate.h>
37 @interface WKWebView ()
38
39 // FIXME: move these to WKWebView_Private.h
40 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view;
41 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale;
42 - (void)_didFinishScrolling;
43 - (void)_scheduleVisibleContentRectUpdate;
44
45 @end
46 #endif
47
48 #if WK_API_ENABLED
49
50 @interface TestRunnerWKWebView () <WKUIDelegatePrivate> {
51     RetainPtr<NSNumber *> m_stableStateOverride;
52     BOOL m_isInteractingWithFormControl;
53 }
54
55 @property (nonatomic, copy) void (^zoomToScaleCompletionHandler)(void);
56 @property (nonatomic, copy) void (^retrieveSpeakSelectionContentCompletionHandler)(void);
57 @property (nonatomic) BOOL isShowingKeyboard;
58
59 @end
60
61 @implementation TestRunnerWKWebView
62
63 #if PLATFORM(MAC)
64 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
65 - (void)dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag
66 IGNORE_WARNINGS_END
67 {
68     RetainPtr<WebKitTestRunnerDraggingInfo> draggingInfo = adoptNS([[WebKitTestRunnerDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj]);
69     [self draggingUpdated:draggingInfo.get()];
70 }
71 #endif
72
73 #if PLATFORM(IOS)
74 - (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration
75 {
76     if (self = [super initWithFrame:frame configuration:configuration]) {
77         NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
78         [center addObserver:self selector:@selector(_invokeShowKeyboardCallbackIfNecessary) name:UIKeyboardDidShowNotification object:nil];
79         [center addObserver:self selector:@selector(_invokeHideKeyboardCallbackIfNecessary) name:UIKeyboardDidHideNotification object:nil];
80
81         self.UIDelegate = self;
82     }
83     return self;
84 }
85
86 - (void)dealloc
87 {
88     [[NSNotificationCenter defaultCenter] removeObserver:self];
89
90     self.didStartFormControlInteractionCallback = nil;
91     self.didEndFormControlInteractionCallback = nil;
92     self.didShowForcePressPreviewCallback = nil;
93     self.didDismissForcePressPreviewCallback = nil;
94     self.willBeginZoomingCallback = nil;
95     self.didEndZoomingCallback = nil;
96     self.didShowKeyboardCallback = nil;
97     self.didHideKeyboardCallback = nil;
98     self.didEndScrollingCallback = nil;
99     self.rotationDidEndCallback = nil;
100
101     self.zoomToScaleCompletionHandler = nil;
102     self.retrieveSpeakSelectionContentCompletionHandler = nil;
103
104     [super dealloc];
105 }
106
107 - (void)didStartFormControlInteraction
108 {
109     m_isInteractingWithFormControl = YES;
110
111     if (self.didStartFormControlInteractionCallback)
112         self.didStartFormControlInteractionCallback();
113 }
114
115 - (void)didEndFormControlInteraction
116 {
117     m_isInteractingWithFormControl = NO;
118
119     if (self.didEndFormControlInteractionCallback)
120         self.didEndFormControlInteractionCallback();
121 }
122
123 - (BOOL)isInteractingWithFormControl
124 {
125     return m_isInteractingWithFormControl;
126 }
127
128 - (void)_didShowForcePressPreview
129 {
130     if (self.didShowForcePressPreviewCallback)
131         self.didShowForcePressPreviewCallback();
132 }
133
134 - (void)_didDismissForcePressPreview
135 {
136     if (self.didDismissForcePressPreviewCallback)
137         self.didDismissForcePressPreviewCallback();
138 }
139
140 - (void)zoomToScale:(double)scale animated:(BOOL)animated completionHandler:(void (^)(void))completionHandler
141 {
142     ASSERT(!self.zoomToScaleCompletionHandler);
143
144     if (self.scrollView.zoomScale == scale) {
145         dispatch_async(dispatch_get_main_queue(), ^{
146             completionHandler();
147         });
148         return;
149     }
150
151     self.zoomToScaleCompletionHandler = completionHandler;
152     [self.scrollView setZoomScale:scale animated:animated];
153 }
154
155 - (void)_invokeShowKeyboardCallbackIfNecessary
156 {
157     if (self.isShowingKeyboard)
158         return;
159
160     self.isShowingKeyboard = YES;
161     if (self.didShowKeyboardCallback)
162         self.didShowKeyboardCallback();
163 }
164
165 - (void)_invokeHideKeyboardCallbackIfNecessary
166 {
167     if (!self.isShowingKeyboard)
168         return;
169
170     self.isShowingKeyboard = NO;
171     if (self.didHideKeyboardCallback)
172         self.didHideKeyboardCallback();
173 }
174
175 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view
176 {
177     [super scrollViewWillBeginZooming:scrollView withView:view];
178
179     if (self.willBeginZoomingCallback)
180         self.willBeginZoomingCallback();
181 }
182
183 - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
184 {
185     [super scrollViewDidEndZooming:scrollView withView:view atScale:scale];
186     
187     if (self.didEndZoomingCallback)
188         self.didEndZoomingCallback();
189
190     if (self.zoomToScaleCompletionHandler) {
191         self.zoomToScaleCompletionHandler();
192         self.zoomToScaleCompletionHandler = nullptr;
193     }
194 }
195
196 - (void)_didFinishScrolling
197 {
198     [super _didFinishScrolling];
199
200     if (self.didEndScrollingCallback)
201         self.didEndScrollingCallback();
202 }
203
204 - (NSNumber *)_stableStateOverride
205 {
206     return m_stableStateOverride.get();
207 }
208
209 - (void)_setStableStateOverride:(NSNumber *)overrideBoolean
210 {
211     m_stableStateOverride = overrideBoolean;
212     [self _scheduleVisibleContentRectUpdate];
213 }
214
215 - (void)_didEndRotation
216 {
217     if (self.rotationDidEndCallback)
218         self.rotationDidEndCallback();
219 }
220
221 - (void)_accessibilityDidGetSpeakSelectionContent:(NSString *)content
222 {
223     self.accessibilitySpeakSelectionContent = content;
224     if (self.retrieveSpeakSelectionContentCompletionHandler)
225         self.retrieveSpeakSelectionContentCompletionHandler();
226 }
227
228 - (void)accessibilityRetrieveSpeakSelectionContentWithCompletionHandler:(void (^)(void))completionHandler
229 {
230     self.retrieveSpeakSelectionContentCompletionHandler = completionHandler;
231     [self _accessibilityRetrieveSpeakSelectionContent];
232 }
233
234 - (void)setOverrideSafeAreaInsets:(UIEdgeInsets)insets
235 {
236     _overrideSafeAreaInsets = insets;
237 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000
238     [self _updateSafeAreaInsets];
239 #endif
240 }
241
242 - (UIEdgeInsets)_safeAreaInsetsForFrame:(CGRect)frame inSuperview:(UIView *)view
243 {
244     return _overrideSafeAreaInsets;
245 }
246
247 #pragma mark - WKUIDelegatePrivate
248
249 // In extra zoom mode, fullscreen form control UI takes on the same role as keyboards and input view controllers
250 // in UIKit. As such, we allow keyboard presentation and dismissal callbacks to work in extra zoom mode as well.
251 - (void)_webView:(WKWebView *)webView didPresentFocusedElementViewController:(UIViewController *)controller
252 {
253     [self _invokeShowKeyboardCallbackIfNecessary];
254 }
255
256 - (void)_webView:(WKWebView *)webView didDismissFocusedElementViewController:(UIViewController *)controller
257 {
258     [self _invokeHideKeyboardCallbackIfNecessary];
259 }
260
261 #endif // PLATFORM(IOS)
262
263 @end
264
265 #endif // WK_API_ENABLED