[Cocoa] Fold common UIScriptController functionality on macOS and iOS into UIScriptCo...
[WebKit-https.git] / Tools / WebKitTestRunner / UIScriptControllerCocoa.mm
1 /*
2  * Copyright (C) 2018 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 #import "PlatformWebView.h"
30 #import "StringFunctions.h"
31 #import "TestController.h"
32 #import "TestRunnerWKWebView.h"
33 #import "UIScriptContext.h"
34 #import <JavaScriptCore/JavaScriptCore.h>
35 #import <WebKit/WKWebViewPrivate.h>
36
37 namespace WTR {
38
39 void UIScriptController::setViewScale(double scale)
40 {
41 #if WK_API_ENABLED
42     TestController::singleton().mainWebView()->platformView()._viewScale = scale;
43 #else
44     UNUSED_PARAM(scale);
45 #endif
46 }
47
48 void UIScriptController::resignFirstResponder()
49 {
50 #if WK_API_ENABLED
51     [TestController::singleton().mainWebView()->platformView() resignFirstResponder];
52 #endif
53 }
54
55 void UIScriptController::doAsyncTask(JSValueRef callback)
56 {
57     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
58
59     dispatch_async(dispatch_get_main_queue(), ^{
60         if (!m_context)
61             return;
62         m_context->asyncTaskComplete(callbackID);
63     });
64 }
65
66 void UIScriptController::setShareSheetCompletesImmediatelyWithResolution(bool resolved)
67 {
68 #if WK_API_ENABLED
69     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
70     [webView _setShareSheetCompletesImmediatelyWithResolutionForTesting:resolved];
71 #else
72     UNUSED_PARAM(resolved);
73 #endif
74 }
75
76 void UIScriptController::removeViewFromWindow(JSValueRef callback)
77 {
78 #if WK_API_ENABLED
79     // FIXME: On iOS, we never invoke the completion callback that's passed in. Fixing this causes the layout
80     // test pageoverlay/overlay-remove-reinsert-view.html to start failing consistently on iOS. It seems like
81     // this warrants some more investigation.
82 #if PLATFORM(MAC)
83     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
84 #else
85     UNUSED_PARAM(callback);
86 #endif
87
88     auto* mainWebView = TestController::singleton().mainWebView();
89     mainWebView->removeFromWindow();
90
91 #if PLATFORM(MAC)
92     [mainWebView->platformView() _doAfterNextPresentationUpdate:^{
93         if (!m_context)
94             return;
95         m_context->asyncTaskComplete(callbackID);
96     }];
97 #endif // PLATFORM(MAC)
98 #else
99     UNUSED_PARAM(callback);
100 #endif
101 }
102
103 void UIScriptController::addViewToWindow(JSValueRef callback)
104 {
105 #if WK_API_ENABLED
106 #if PLATFORM(MAC)
107     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
108 #else
109     UNUSED_PARAM(callback);
110 #endif
111
112     auto* mainWebView = TestController::singleton().mainWebView();
113     mainWebView->addToWindow();
114
115 #if PLATFORM(MAC)
116     [mainWebView->platformView() _doAfterNextPresentationUpdate:^{
117         if (!m_context)
118             return;
119         m_context->asyncTaskComplete(callbackID);
120     }];
121 #endif // PLATFORM(MAC)
122 #else
123     UNUSED_PARAM(callback);
124 #endif
125 }
126
127 void UIScriptController::overridePreference(JSStringRef preferenceRef, JSStringRef valueRef)
128 {
129 #if WK_API_ENABLED
130     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
131     WKPreferences *preferences = webView.configuration.preferences;
132
133     String preference = toWTFString(toWK(preferenceRef));
134     String value = toWTFString(toWK(valueRef));
135     if (preference == "WebKitMinimumFontSize")
136         preferences.minimumFontSize = value.toDouble();
137 #else
138     UNUSED_PARAM(preferenceRef);
139     UNUSED_PARAM(valueRef);
140 #endif
141 }
142
143 void UIScriptController::findString(JSStringRef string, unsigned long options, unsigned long maxCount)
144 {
145 #if WK_API_ENABLED
146     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
147     [webView _findString:toWTFString(toWK(string)) options:options maxCount:maxCount];
148 #else
149     UNUSED_PARAM(string);
150     UNUSED_PARAM(options);
151     UNUSED_PARAM(maxCount);
152 #endif
153 }
154
155 JSObjectRef UIScriptController::contentsOfUserInterfaceItem(JSStringRef interfaceItem) const
156 {
157 #if WK_API_ENABLED
158     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
159     NSDictionary *contentDictionary = [webView _contentsOfUserInterfaceItem:toWTFString(toWK(interfaceItem))];
160     return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:contentDictionary inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
161 #else
162     UNUSED_PARAM(interfaceItem);
163     return nullptr;
164 #endif
165 }
166
167 } // namespace WTR