js/regress/is-string-fold-tricky.html and js/regress/is-string-fold.html are crashing
[WebKit-https.git] / Tools / WebKitTestRunner / mac / PlatformWebViewMac.mm
1 /*
2  * Copyright (C) 2010, 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 "PlatformWebView.h"
28
29 #import "TestController.h"
30 #import "WebKitTestRunnerDraggingInfo.h"
31 #import <WebKit/WKImageCG.h>
32 #import <WebKit/WKPreferencesPrivate.h>
33 #import <WebKit/WKViewPrivate.h>
34 #import <wtf/RetainPtr.h>
35
36 using namespace WTR;
37
38 enum {
39     _NSBackingStoreUnbuffered = 3
40 };
41
42 @interface WebKitTestRunnerWindow : NSWindow {
43     PlatformWebView* _platformWebView;
44     NSPoint _fakeOrigin;
45 }
46 @property (nonatomic, assign) PlatformWebView* platformWebView;
47 @end
48
49 @interface TestRunnerWKView : WKView {
50     BOOL _useThreadedScrolling;
51 }
52
53 - (id)initWithFrame:(NSRect)frame contextRef:(WKContextRef)context pageGroupRef:(WKPageGroupRef)pageGroup relatedToPage:(WKPageRef)relatedPage useThreadedScrolling:(BOOL)useThreadedScrolling;
54
55 @property (nonatomic, assign) BOOL useThreadedScrolling;
56 @end
57
58 @implementation TestRunnerWKView
59
60 @synthesize useThreadedScrolling = _useThreadedScrolling;
61
62 - (id)initWithFrame:(NSRect)frame contextRef:(WKContextRef)context pageGroupRef:(WKPageGroupRef)pageGroup relatedToPage:(WKPageRef)relatedPage useThreadedScrolling:(BOOL)useThreadedScrolling
63 {
64     _useThreadedScrolling = useThreadedScrolling;
65     return [super initWithFrame:frame contextRef:context pageGroupRef:pageGroup relatedToPage:relatedPage];
66 }
67
68 - (void)dragImage:(NSImage *)anImage at:(NSPoint)viewLocation offset:(NSSize)initialOffset event:(NSEvent *)event pasteboard:(NSPasteboard *)pboard source:(id)sourceObj slideBack:(BOOL)slideFlag
69 {
70     RetainPtr<WebKitTestRunnerDraggingInfo> draggingInfo = adoptNS([[WebKitTestRunnerDraggingInfo alloc] initWithImage:anImage offset:initialOffset pasteboard:pboard source:sourceObj]);
71     [self draggingUpdated:draggingInfo.get()];
72 }
73
74 @end
75
76 @implementation WebKitTestRunnerWindow
77 @synthesize platformWebView = _platformWebView;
78
79 - (BOOL)isKeyWindow
80 {
81     return _platformWebView ? _platformWebView->windowIsKey() : YES;
82 }
83
84 - (void)setFrameOrigin:(NSPoint)point
85 {
86     _fakeOrigin = point;
87 }
88
89 - (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews animate:(BOOL)performAnimation
90 {
91     NSRect currentFrame = [super frame];
92
93     _fakeOrigin = windowFrame.origin;
94
95     [super setFrame:NSMakeRect(currentFrame.origin.x, currentFrame.origin.y, windowFrame.size.width, windowFrame.size.height) display:displayViews animate:performAnimation];
96 }
97
98 - (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews
99 {
100     NSRect currentFrame = [super frame];
101
102     _fakeOrigin = windowFrame.origin;
103
104     [super setFrame:NSMakeRect(currentFrame.origin.x, currentFrame.origin.y, windowFrame.size.width, windowFrame.size.height) display:displayViews];
105 }
106
107 - (NSRect)frameRespectingFakeOrigin
108 {
109     NSRect currentFrame = [self frame];
110     return NSMakeRect(_fakeOrigin.x, _fakeOrigin.y, currentFrame.size.width, currentFrame.size.height);
111 }
112 @end
113
114 @interface NSWindow (Details)
115
116 - (void)_setWindowResolution:(CGFloat)resolution displayIfChanged:(BOOL)displayIfChanged;
117
118 @end
119
120 namespace WTR {
121
122 PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, WKPageRef relatedPage, WKDictionaryRef options)
123     : m_windowIsKey(true)
124     , m_options(options)
125 {
126     WKRetainPtr<WKStringRef> useThreadedScrollingKey(AdoptWK, WKStringCreateWithUTF8CString("ThreadedScrolling"));
127     WKRetainPtr<WKStringRef> useRemoteLayerTreeKey(AdoptWK, WKStringCreateWithUTF8CString("RemoteLayerTree"));
128     WKTypeRef useThreadedScrollingValue = options ? WKDictionaryGetItemForKey(options, useThreadedScrollingKey.get()) : NULL;
129     bool useThreadedScrolling = useThreadedScrollingValue && WKBooleanGetValue(static_cast<WKBooleanRef>(useThreadedScrollingValue));
130
131     // The tiled drawing specific tests also depend on threaded scrolling.
132     WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroupRef);
133     WKPreferencesSetThreadedScrollingEnabled(preferences, useThreadedScrolling);
134
135     // FIXME: Not sure this is the best place for this; maybe we should have API to set this so we can do it from TestController?
136     WKTypeRef useRemoteLayerTreeValue = options ? WKDictionaryGetItemForKey(options, useRemoteLayerTreeKey.get()) : NULL;
137     if (useRemoteLayerTreeValue && WKBooleanGetValue(static_cast<WKBooleanRef>(useRemoteLayerTreeValue)))
138         [[NSUserDefaults standardUserDefaults] setValue:@YES forKey:@"WebKit2UseRemoteLayerTreeDrawingArea"];
139
140     NSRect rect = NSMakeRect(0, 0, TestController::viewWidth, TestController::viewHeight);
141     m_view = [[TestRunnerWKView alloc] initWithFrame:rect contextRef:contextRef pageGroupRef:pageGroupRef relatedToPage:relatedPage useThreadedScrolling:useThreadedScrolling];
142     [m_view setWindowOcclusionDetectionEnabled:NO];
143
144     NSScreen *firstScreen = [[NSScreen screens] objectAtIndex:0];
145     NSRect windowRect = NSOffsetRect(rect, -10000, [firstScreen frame].size.height - rect.size.height + 10000);
146     m_window = [[WebKitTestRunnerWindow alloc] initWithContentRect:windowRect styleMask:NSBorderlessWindowMask backing:(NSBackingStoreType)_NSBackingStoreUnbuffered defer:YES];
147     m_window.platformWebView = this;
148     [m_window setColorSpace:[firstScreen colorSpace]];
149     [m_window setCollectionBehavior:NSWindowCollectionBehaviorStationary];
150     [[m_window contentView] addSubview:m_view];
151     [m_window orderBack:nil];
152     [m_window setReleasedWhenClosed:NO];
153 }
154
155 void PlatformWebView::resizeTo(unsigned width, unsigned height)
156 {
157     WKRect frame = windowFrame();
158     frame.size.width = width;
159     frame.size.height = height;
160     setWindowFrame(frame);
161 }
162
163 PlatformWebView::~PlatformWebView()
164 {
165     m_window.platformWebView = nullptr;
166     [m_window close];
167     [m_window release];
168     [m_view release];
169 }
170
171 WKPageRef PlatformWebView::page()
172 {
173     return [m_view pageRef];
174 }
175
176 void PlatformWebView::focus()
177 {
178     [m_window makeFirstResponder:m_view];
179     setWindowIsKey(true);
180 }
181
182 WKRect PlatformWebView::windowFrame()
183 {
184     NSRect frame = [m_window frameRespectingFakeOrigin];
185
186     WKRect wkFrame;
187     wkFrame.origin.x = frame.origin.x;
188     wkFrame.origin.y = frame.origin.y;
189     wkFrame.size.width = frame.size.width;
190     wkFrame.size.height = frame.size.height;
191     return wkFrame;
192 }
193
194 void PlatformWebView::setWindowFrame(WKRect frame)
195 {
196     [m_window setFrame:NSMakeRect(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height) display:YES];
197     [m_view setFrame:NSMakeRect(0, 0, frame.size.width, frame.size.height)];
198 }
199
200 void PlatformWebView::didInitializeClients()
201 {
202     // Set a temporary 1x1 window frame to force a WindowAndViewFramesChanged notification. <rdar://problem/13380145>
203     forceWindowFramesChanged();
204 }
205
206 void PlatformWebView::addChromeInputField()
207 {
208     NSTextField* textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)];
209     textField.tag = 1;
210     [[m_window contentView] addSubview:textField];
211     [textField release];
212
213     [textField setNextKeyView:m_view];
214     [m_view setNextKeyView:textField];
215 }
216
217 void PlatformWebView::removeChromeInputField()
218 {
219     NSView* textField = [[m_window contentView] viewWithTag:1];
220     if (textField) {
221         [textField removeFromSuperview];
222         makeWebViewFirstResponder();
223     }
224 }
225
226 void PlatformWebView::makeWebViewFirstResponder()
227 {
228     [m_window makeFirstResponder:m_view];
229 }
230
231 WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
232 {
233     [m_view display];
234     CGWindowImageOption options = kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque;
235
236     if ([m_window backingScaleFactor] == 1)
237         options |= kCGWindowImageNominalResolution;
238
239     RetainPtr<CGImageRef> windowSnapshotImage = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, [m_window windowNumber], options));
240
241     // windowSnapshotImage will be in GenericRGB, as we've set the main display's color space to GenericRGB.
242     return adoptWK(WKImageCreateFromCGImage(windowSnapshotImage.get(), 0));
243 }
244
245 bool PlatformWebView::viewSupportsOptions(WKDictionaryRef options) const
246 {
247     WKRetainPtr<WKStringRef> useThreadedScrollingKey(AdoptWK, WKStringCreateWithUTF8CString("ThreadedScrolling"));
248     WKTypeRef useThreadedScrollingValue = WKDictionaryGetItemForKey(options, useThreadedScrollingKey.get());
249     bool useThreadedScrolling = useThreadedScrollingValue && WKBooleanGetValue(static_cast<WKBooleanRef>(useThreadedScrollingValue));
250
251     return useThreadedScrolling == [(TestRunnerWKView *)m_view useThreadedScrolling];
252 }
253
254 void PlatformWebView::changeWindowScaleIfNeeded(float newScale)
255 {
256     CGFloat currentScale = [m_window backingScaleFactor];
257     if (currentScale == newScale)
258         return;
259     [m_window _setWindowResolution:newScale displayIfChanged:YES];
260     // Instead of re-constructing the current window, let's fake resize it to ensure that the scale change gets picked up.
261     forceWindowFramesChanged();
262     // Changing the scaling factor on the window does not trigger NSWindowDidChangeBackingPropertiesNotification. We need to send the notification manually.
263     RetainPtr<NSMutableDictionary> notificationUserInfo = adoptNS([[NSMutableDictionary alloc] initWithCapacity:1]);
264     [notificationUserInfo setObject:[NSNumber numberWithDouble:currentScale] forKey:NSBackingPropertyOldScaleFactorKey];
265     [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidChangeBackingPropertiesNotification object:m_window userInfo:notificationUserInfo.get()];
266 }
267
268 void PlatformWebView::forceWindowFramesChanged()
269 {
270     WKRect wkFrame = windowFrame();
271     [m_window setFrame:NSMakeRect(0, 0, 1, 1) display:YES];
272     setWindowFrame(wkFrame);
273 }
274
275 } // namespace WTR