b479b9336f406f86408eca222b52cc8eefd2cd3a
[WebKit-https.git] / Tools / WebKitTestRunner / ios / UIScriptControllerIOS.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 "UIScriptController.h"
28
29 #if PLATFORM(IOS)
30
31 #import "HIDEventGenerator.h"
32 #import "PlatformWebView.h"
33 #import "StringFunctions.h"
34 #import "TestController.h"
35 #import "TestRunnerWKWebView.h"
36 #import "UIScriptContext.h"
37 #import <UIKit/UIKit.h>
38 #import <WebKit/WKWebViewPrivate.h>
39 #import <WebKit/WebKit.h>
40
41 namespace WTR {
42
43 void UIScriptController::doAsyncTask(JSValueRef callback)
44 {
45     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
46
47     dispatch_async(dispatch_get_main_queue(), ^{
48         if (!m_context)
49             return;
50         m_context->asyncTaskComplete(callbackID);
51     });
52 }
53
54 void UIScriptController::zoomToScale(double scale, JSValueRef callback)
55 {
56     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
57
58     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
59
60     [webView zoomToScale:scale animated:YES completionHandler:^{
61         if (!m_context)
62             return;
63         m_context->asyncTaskComplete(callbackID);
64     }];
65 }
66
67 double UIScriptController::zoomScale() const
68 {
69     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
70     return webView.scrollView.zoomScale;
71 }
72
73 static CGPoint globalToContentCoordinates(TestRunnerWKWebView *webView, long x, long y)
74 {
75     CGPoint point = CGPointMake(x, y);
76     point = [webView _convertPointFromContentsToView:point];
77     point = [webView convertPoint:point toView:nil];
78     point = [webView.window convertPoint:point toWindow:nil];
79     return point;
80 }
81
82 void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback)
83 {
84     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
85
86     auto location = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y);
87     [[HIDEventGenerator sharedHIDEventGenerator] touchDown:location touchCount:touchCount completionBlock:^{
88         if (!m_context)
89             return;
90         m_context->asyncTaskComplete(callbackID);
91     }];
92 }
93
94 void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback)
95 {
96     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
97     
98     auto location = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y);
99     [[HIDEventGenerator sharedHIDEventGenerator] liftUp:location touchCount:touchCount completionBlock:^{
100         if (!m_context)
101             return;
102         m_context->asyncTaskComplete(callbackID);
103     }];
104 }
105
106 void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef callback)
107 {
108     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
109
110     [[HIDEventGenerator sharedHIDEventGenerator] tap:globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y) completionBlock:^{
111         if (!m_context)
112             return;
113         m_context->asyncTaskComplete(callbackID);
114     }];
115 }
116
117 void UIScriptController::doubleTapAtPoint(long x, long y, JSValueRef callback)
118 {
119     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
120
121     [[HIDEventGenerator sharedHIDEventGenerator] doubleTap:globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y) completionBlock:^{
122         if (!m_context)
123             return;
124         m_context->asyncTaskComplete(callbackID);
125     }];
126 }
127
128 void UIScriptController::dragFromPointToPoint(long startX, long startY, long endX, long endY, double durationSeconds, JSValueRef callback)
129 {
130     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
131
132     CGPoint startPoint = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), startX, startY);
133     CGPoint endPoint = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), endX, endY);
134     
135     [[HIDEventGenerator sharedHIDEventGenerator] dragWithStartPoint:startPoint endPoint:endPoint duration:durationSeconds completionBlock:^{
136         if (!m_context)
137             return;
138         m_context->asyncTaskComplete(callbackID);
139     }];
140 }
141
142 void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
143 {
144     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
145
146     // Assumes that the keyboard is already shown.
147     [[HIDEventGenerator sharedHIDEventGenerator] keyPress:toWTFString(toWK(character)) completionBlock:^{
148         if (!m_context)
149             return;
150         m_context->asyncTaskComplete(callbackID);
151     }];
152 }
153
154 void UIScriptController::keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
155 {
156     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
157
158     // Assumes that the keyboard is already shown.
159     [[HIDEventGenerator sharedHIDEventGenerator] keyDown:toWTFString(toWK(character)) completionBlock:^{
160         if (!m_context)
161             return;
162         m_context->asyncTaskComplete(callbackID);
163     }];
164 }
165
166 void UIScriptController::keyUpUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
167 {
168     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
169
170     // Assumes that the keyboard is already shown.
171     [[HIDEventGenerator sharedHIDEventGenerator] keyUp:toWTFString(toWK(character)) completionBlock:^{
172         if (!m_context)
173             return;
174         m_context->asyncTaskComplete(callbackID);
175     }];
176 }
177
178 void UIScriptController::dismissFormAccessoryView()
179 {
180     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
181     [webView dismissFormAccessoryView];
182 }
183
184 void UIScriptController::selectFormAccessoryPickerRow(long rowIndex)
185 {
186     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
187     [webView selectFormAccessoryPickerRow:rowIndex];
188 }
189
190 void UIScriptController::keyboardAccessoryBarNext()
191 {
192     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
193     [webView keyboardAccessoryBarNext];
194 }
195
196 void UIScriptController::keyboardAccessoryBarPrevious()
197 {
198     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
199     [webView keyboardAccessoryBarPrevious];
200 }
201
202 double UIScriptController::minimumZoomScale() const
203 {
204     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
205     return webView.scrollView.minimumZoomScale;
206 }
207
208 double UIScriptController::maximumZoomScale() const
209 {
210     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
211     return webView.scrollView.maximumZoomScale;
212 }
213
214 JSObjectRef UIScriptController::contentVisibleRect() const
215 {
216     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
217
218     CGRect contentVisibleRect = webView._contentVisibleRect;
219     
220     WKRect wkRect = WKRectMake(contentVisibleRect.origin.x, contentVisibleRect.origin.y, contentVisibleRect.size.width, contentVisibleRect.size.height);
221     return m_context->objectFromRect(wkRect);
222 }
223
224 void UIScriptController::platformSetWillBeginZoomingCallback()
225 {
226     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
227     webView.willBeginZoomingCallback = ^{
228         if (!m_context)
229             return;
230         m_context->fireCallback(CallbackTypeWillBeginZooming);
231     };
232 }
233
234 void UIScriptController::platformSetDidEndZoomingCallback()
235 {
236     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
237     webView.didEndZoomingCallback = ^{
238         if (!m_context)
239             return;
240         m_context->fireCallback(CallbackTypeDidEndZooming);
241     };
242 }
243
244 void UIScriptController::platformSetDidShowKeyboardCallback()
245 {
246     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
247     webView.didShowKeyboardCallback = ^{
248         if (!m_context)
249             return;
250         m_context->fireCallback(CallbackTypeDidShowKeyboard);
251     };
252 }
253
254 void UIScriptController::platformSetDidHideKeyboardCallback()
255 {
256     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
257     webView.didHideKeyboardCallback = ^{
258         if (!m_context)
259             return;
260         m_context->fireCallback(CallbackTypeDidHideKeyboard);
261     };
262 }
263
264 void UIScriptController::platformSetDidEndScrollingCallback()
265 {
266     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
267     webView.didEndScrollingCallback = ^{
268         if (!m_context)
269             return;
270         m_context->fireCallback(CallbackTypeDidEndScrolling);
271     };
272 }
273
274 void UIScriptController::platformClearAllCallbacks()
275 {
276     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
277     webView.didEndZoomingCallback = nil;
278     webView.willBeginZoomingCallback = nil;
279     webView.didHideKeyboardCallback = nil;
280     webView.didShowKeyboardCallback = nil;
281     webView.didEndScrollingCallback = nil;
282 }
283
284 }
285
286 #endif // PLATFORM(IOS)