Allow WebKit clients to specify a minimum effective width for layout.
[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::setMinimumEffectiveWidth(double effectiveWidth)
49 {
50 #if WK_API_ENABLED
51     TestController::singleton().mainWebView()->platformView()._minimumEffectiveDeviceWidth = effectiveWidth;
52 #else
53     UNUSED_PARAM(effectiveWidth);
54 #endif
55 }
56
57 void UIScriptController::resignFirstResponder()
58 {
59 #if WK_API_ENABLED
60     [TestController::singleton().mainWebView()->platformView() resignFirstResponder];
61 #endif
62 }
63
64 void UIScriptController::doAsyncTask(JSValueRef callback)
65 {
66     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
67
68     dispatch_async(dispatch_get_main_queue(), ^{
69         if (!m_context)
70             return;
71         m_context->asyncTaskComplete(callbackID);
72     });
73 }
74
75 void UIScriptController::setShareSheetCompletesImmediatelyWithResolution(bool resolved)
76 {
77 #if WK_API_ENABLED
78     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
79     [webView _setShareSheetCompletesImmediatelyWithResolutionForTesting:resolved];
80 #else
81     UNUSED_PARAM(resolved);
82 #endif
83 }
84
85 void UIScriptController::removeViewFromWindow(JSValueRef callback)
86 {
87 #if WK_API_ENABLED
88     // FIXME: On iOS, we never invoke the completion callback that's passed in. Fixing this causes the layout
89     // test pageoverlay/overlay-remove-reinsert-view.html to start failing consistently on iOS. It seems like
90     // this warrants some more investigation.
91 #if PLATFORM(MAC)
92     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
93 #else
94     UNUSED_PARAM(callback);
95 #endif
96
97     auto* mainWebView = TestController::singleton().mainWebView();
98     mainWebView->removeFromWindow();
99
100 #if PLATFORM(MAC)
101     [mainWebView->platformView() _doAfterNextPresentationUpdate:^{
102         if (!m_context)
103             return;
104         m_context->asyncTaskComplete(callbackID);
105     }];
106 #endif // PLATFORM(MAC)
107 #else
108     UNUSED_PARAM(callback);
109 #endif
110 }
111
112 void UIScriptController::addViewToWindow(JSValueRef callback)
113 {
114 #if WK_API_ENABLED
115 #if PLATFORM(MAC)
116     unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
117 #else
118     UNUSED_PARAM(callback);
119 #endif
120
121     auto* mainWebView = TestController::singleton().mainWebView();
122     mainWebView->addToWindow();
123
124 #if PLATFORM(MAC)
125     [mainWebView->platformView() _doAfterNextPresentationUpdate:^{
126         if (!m_context)
127             return;
128         m_context->asyncTaskComplete(callbackID);
129     }];
130 #endif // PLATFORM(MAC)
131 #else
132     UNUSED_PARAM(callback);
133 #endif
134 }
135
136 void UIScriptController::overridePreference(JSStringRef preferenceRef, JSStringRef valueRef)
137 {
138 #if WK_API_ENABLED
139     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
140     WKPreferences *preferences = webView.configuration.preferences;
141
142     String preference = toWTFString(toWK(preferenceRef));
143     String value = toWTFString(toWK(valueRef));
144     if (preference == "WebKitMinimumFontSize")
145         preferences.minimumFontSize = value.toDouble();
146 #else
147     UNUSED_PARAM(preferenceRef);
148     UNUSED_PARAM(valueRef);
149 #endif
150 }
151
152 void UIScriptController::findString(JSStringRef string, unsigned long options, unsigned long maxCount)
153 {
154 #if WK_API_ENABLED
155     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
156     [webView _findString:toWTFString(toWK(string)) options:options maxCount:maxCount];
157 #else
158     UNUSED_PARAM(string);
159     UNUSED_PARAM(options);
160     UNUSED_PARAM(maxCount);
161 #endif
162 }
163
164 JSObjectRef UIScriptController::contentsOfUserInterfaceItem(JSStringRef interfaceItem) const
165 {
166 #if WK_API_ENABLED
167     TestRunnerWKWebView *webView = TestController::singleton().mainWebView()->platformView();
168     NSDictionary *contentDictionary = [webView _contentsOfUserInterfaceItem:toWTFString(toWK(interfaceItem))];
169     return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:contentDictionary inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
170 #else
171     UNUSED_PARAM(interfaceItem);
172     return nullptr;
173 #endif
174 }
175
176 void UIScriptController::setDefaultCalendarType(JSStringRef calendarIdentifier)
177 {
178 #if WK_API_ENABLED
179     TestController::singleton().setDefaultCalendarType((__bridge NSString *)adoptCF(JSStringCopyCFString(kCFAllocatorDefault, calendarIdentifier)).get());
180 #endif
181 }
182
183 JSObjectRef UIScriptController::calendarType() const
184 {
185 #if WK_API_ENABLED
186     WKWebView *webView = TestController::singleton().mainWebView()->platformView();
187     UIView *contentView = [webView valueForKeyPath:@"_currentContentView"];
188     NSString *calendarTypeString = [contentView valueForKeyPath:@"formInputControl.dateTimePickerCalendarType"];
189     auto jsContext = m_context->jsContext();
190     return JSValueToObject(jsContext, [JSValue valueWithObject:calendarTypeString inContext:[JSContext contextWithJSGlobalContextRef:jsContext]].JSValueRef, nullptr);
191 #else
192     return nullptr;
193 #endif
194 }
195     
196 } // namespace WTR