6db4b25dcdfeb051dec61e3a0d9f3d38f5bad8fc
[WebKit-https.git] / Tools / WebKitTestRunner / mac / TestControllerMac.mm
1 /*
2  * Copyright (C) 2010 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 "TestController.h"
28
29 #import "PlatformWebView.h"
30 #import "PoseAsClass.h"
31 #import "TestInvocation.h"
32 #import "TestRunnerWKWebView.h"
33 #import "WebKitTestRunnerPasteboard.h"
34 #import <WebKit/WKContextPrivate.h>
35 #import <WebKit/WKPageGroup.h>
36 #import <WebKit/WKProcessPoolPrivate.h>
37 #import <WebKit/WKStringCF.h>
38 #import <WebKit/WKURLCF.h>
39 #import <WebKit/WKUserContentControllerPrivate.h>
40 #import <WebKit/WKWebView.h>
41 #import <WebKit/WKWebViewConfiguration.h>
42 #import <WebKit/WKWebViewConfigurationPrivate.h>
43 #import <WebKit/WKWebViewPrivate.h>
44 #import <WebKit/_WKUserContentExtensionStore.h>
45 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
46 #import <mach-o/dyld.h>
47 #import <wtf/ObjCRuntimeExtras.h>
48 #import <wtf/mac/AppKitCompatibilityDeclarations.h>
49
50 @interface NSSound ()
51 + (void)_setAlertType:(NSUInteger)alertType;
52 @end
53
54 namespace WTR {
55
56 void TestController::notifyDone()
57 {
58 }
59
60 static PlatformWindow wtr_NSApplication_keyWindow(id self, SEL _cmd)
61 {
62     return WTR::PlatformWebView::keyWindow();
63 }
64
65 void TestController::platformInitialize()
66 {
67     poseAsClass("WebKitTestRunnerPasteboard", "NSPasteboard");
68     poseAsClass("WebKitTestRunnerEvent", "NSEvent");
69     
70     cocoaPlatformInitialize();
71
72     [NSSound _setAlertType:0];
73
74     Method keyWindowMethod = class_getInstanceMethod(objc_getClass("NSApplication"), @selector(keyWindow));
75
76     ASSERT(keyWindowMethod);
77     if (!keyWindowMethod) {
78         NSLog(@"Failed to swizzle the \"keyWindowMethod\" method on NSApplication");
79         return;
80     }
81     
82     method_setImplementation(keyWindowMethod, (IMP)wtr_NSApplication_keyWindow);
83 }
84
85 void TestController::platformDestroy()
86 {
87     [WebKitTestRunnerPasteboard releaseLocalPasteboards];
88 }
89
90 void TestController::initializeInjectedBundlePath()
91 {
92     NSString *nsBundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"WebKitTestRunnerInjectedBundle.bundle"];
93     m_injectedBundlePath.adopt(WKStringCreateWithCFString((__bridge CFStringRef)nsBundlePath));
94 }
95
96 void TestController::initializeTestPluginDirectory()
97 {
98     m_testPluginDirectory.adopt(WKStringCreateWithCFString((__bridge CFStringRef)[[NSBundle mainBundle] bundlePath]));
99 }
100
101 void TestController::platformResetPreferencesToConsistentValues()
102 {
103 }
104
105 void TestController::platformResetStateToConsistentValues(const TestOptions& options)
106 {
107     cocoaResetStateToConsistentValues(options);
108
109     while ([NSApp nextEventMatchingMask:NSEventMaskGesture | NSEventMaskScrollWheel untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]) {
110         // Clear out (and ignore) any pending gesture and scroll wheel events.
111     }
112 }
113
114 void TestController::updatePlatformSpecificTestOptionsForTest(TestOptions& options, const std::string&) const
115 {
116     options.useThreadedScrolling = true;
117     options.useRemoteLayerTree = shouldUseRemoteLayerTree();
118     options.shouldShowWebView = shouldShowWebView();
119 }
120
121 void TestController::configureContentExtensionForTest(const TestInvocation& test)
122 {
123 #if WK_API_ENABLED
124     if (!test.urlContains("contentextensions/"))
125         return;
126
127     RetainPtr<CFURLRef> testURL = adoptCF(WKURLCopyCFURL(kCFAllocatorDefault, test.url()));
128     NSURL *filterURL = [(__bridge NSURL *)testURL.get() URLByAppendingPathExtension:@"json"];
129
130     NSStringEncoding encoding;
131     NSString *contentExtensionString = [[NSString alloc] initWithContentsOfURL:filterURL usedEncoding:&encoding error:NULL];
132     if (!contentExtensionString)
133         return;
134     
135     __block bool doneCompiling = false;
136
137     NSURL *tempDir;
138     auto temporaryFolder = libraryPathForTesting();
139     if (!!temporaryFolder)
140         tempDir = [NSURL fileURLWithPath:[(NSString*)temporaryFolder stringByAppendingPathComponent:@"ContentExtensions"] isDirectory:YES];
141     else
142         tempDir = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"ContentExtensions"] isDirectory:YES];
143
144     [[_WKUserContentExtensionStore storeWithURL:tempDir] compileContentExtensionForIdentifier:@"TestContentExtensions" encodedContentExtension:contentExtensionString completionHandler:^(_WKUserContentFilter *filter, NSError *error)
145     {
146         if (!error)
147             [mainWebView()->platformView().configuration.userContentController _addUserContentFilter:filter];
148         else
149             NSLog(@"%@", [error helpAnchor]);
150         doneCompiling = true;
151     }];
152     platformRunUntil(doneCompiling, noTimeout);
153 #endif
154 }
155
156 void TestController::platformConfigureViewForTest(const TestInvocation& test)
157 {
158 }
159
160 static NSSet *allowedFontFamilySet()
161 {
162     static NSSet *fontFamilySet = [[NSSet setWithObjects:
163         @"Ahem",
164         @"Al Bayan",
165         @"American Typewriter",
166         @"Andale Mono",
167         @"Apple Braille",
168         @"Apple Color Emoji",
169         @"Apple Chancery",
170         @"Apple Garamond BT",
171         @"Apple LiGothic",
172         @"Apple LiSung",
173         @"Apple Symbols",
174         @"AppleGothic",
175         @"AppleMyungjo",
176         @"Arial Black",
177         @"Arial Hebrew",
178         @"Arial Narrow",
179         @"Arial Rounded MT Bold",
180         @"Arial Unicode MS",
181         @"Arial",
182         @"Avenir Next",
183         @"Ayuthaya",
184         @"Baghdad",
185         @"Baskerville",
186         @"BiauKai",
187         @"Big Caslon",
188         @"Brush Script MT",
189         @"Chalkboard",
190         @"Chalkduster",
191         @"Charcoal CY",
192         @"Cochin",
193         @"Comic Sans MS",
194         @"Copperplate",
195         @"Corsiva Hebrew",
196         @"Courier New",
197         @"Courier",
198         @"DecoType Naskh",
199         @"Devanagari MT",
200         @"Didot",
201         @"Euphemia UCAS",
202         @"Futura",
203         @"GB18030 Bitmap",
204         @"Geeza Pro",
205         @"Geneva CY",
206         @"Geneva",
207         @"Georgia",
208         @"Gill Sans",
209         @"Gujarati MT",
210         @"GungSeo",
211         @"Gurmukhi MT",
212         @"HeadLineA",
213         @"Hei",
214         @"Heiti SC",
215         @"Heiti TC",
216         @"Helvetica CY",
217         @"Helvetica Neue",
218         @"Helvetica",
219         @"Helvetica2",
220         @"Herculanum",
221         @"Hiragino Kaku Gothic Pro",
222         @"Hiragino Kaku Gothic ProN",
223         @"Hiragino Kaku Gothic Std",
224         @"Hiragino Kaku Gothic StdN",
225         @"Hiragino Maru Gothic Pro",
226         @"Hiragino Maru Gothic ProN",
227         @"Hiragino Mincho Pro",
228         @"Hiragino Mincho ProN",
229         @"Hiragino Sans",
230         @"Hiragino Sans GB",
231         @"Hoefler Text",
232         @"Impact",
233         @"InaiMathi",
234         @"Kai",
235         @"Kailasa",
236         @"Kokonor",
237         @"Krungthep",
238         @"KufiStandardGK",
239         @"Lao Sangam MN",
240         @"LastResort",
241         @"LiHei Pro",
242         @"LiSong Pro",
243         @"Lucida Grande",
244         @"Marker Felt",
245         @"Menlo",
246         @"Microsoft Sans Serif",
247         @"Monaco",
248         @"Mshtakan",
249         @"Nadeem",
250         @"New Peninim MT",
251         @"Optima",
252         @"Osaka",
253         @"Palatino",
254         @"Papyrus",
255         @"PCMyungjo",
256         @"PilGi",
257         @"PingFang HK",
258         @"PingFang SC",
259         @"PingFang TC",
260         @"Plantagenet Cherokee",
261         @"Raanana",
262         @"Sathu",
263         @"Silom",
264         @"Skia",
265         @"Snell Roundhand",
266         @"Songti SC",
267         @"Songti TC",
268         @"STFangsong",
269         @"STHeiti",
270         @"STIXGeneral",
271         @"STIXSizeOneSym",
272         @"STKaiti",
273         @"STSong",
274         @"Symbol",
275         @"Tahoma",
276         @"Thonburi",
277         @"Times New Roman",
278         @"Times",
279         @"Trebuchet MS",
280         @"Verdana",
281         @"Webdings",
282         @"WebKit WeightWatcher",
283         @"FontWithFeaturesOTF",
284         @"FontWithFeaturesTTF",
285         @"Wingdings 2",
286         @"Wingdings 3",
287         @"Wingdings",
288         @"Zapf Dingbats",
289         @"Zapfino",
290         nil] retain];
291
292     return fontFamilySet;
293 }
294
295 static NSSet *systemHiddenFontFamilySet()
296 {
297     static NSSet *fontFamilySet = [[NSSet setWithObjects:
298         @".LucidaGrandeUI",
299         nil] retain];
300
301     return fontFamilySet;
302 }
303
304 static WKRetainPtr<WKArrayRef> generateWhitelist()
305 {
306     WKRetainPtr<WKMutableArrayRef> result = adoptWK(WKMutableArrayCreate());
307     for (NSString *fontFamily in allowedFontFamilySet()) {
308         NSArray *fontsForFamily = [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily];
309         WKRetainPtr<WKStringRef> familyInFont = adoptWK(WKStringCreateWithUTF8CString([fontFamily UTF8String]));
310         WKArrayAppendItem(result.get(), familyInFont.get());
311         for (NSArray *fontInfo in fontsForFamily) {
312             // Font name is the first entry in the array.
313             WKRetainPtr<WKStringRef> fontName = adoptWK(WKStringCreateWithUTF8CString([[fontInfo objectAtIndex:0] UTF8String]));
314             WKArrayAppendItem(result.get(), fontName.get());
315         }
316     }
317
318     for (NSString *hiddenFontFamily in systemHiddenFontFamilySet())
319         WKArrayAppendItem(result.get(), adoptWK(WKStringCreateWithUTF8CString([hiddenFontFamily UTF8String])).get());
320
321     return result;
322 }
323
324 void TestController::platformInitializeContext()
325 {
326     // Testing uses a private session, which is memory only. However creating one instantiates a shared NSURLCache,
327     // and if we haven't created one yet, the default one will be created on disk.
328     // Making the shared cache memory-only avoids touching the file system.
329     RetainPtr<NSURLCache> sharedCache =
330         adoptNS([[NSURLCache alloc] initWithMemoryCapacity:1024 * 1024
331                                       diskCapacity:0
332                                           diskPath:nil]);
333     [NSURLCache setSharedURLCache:sharedCache.get()];
334
335     WKContextSetFontWhitelist(m_context.get(), generateWhitelist().get());
336 }
337
338 void TestController::setHidden(bool hidden)
339 {
340     NSWindow *window = [mainWebView()->platformView() window];
341     if (!window)
342         return;
343
344     if (hidden)
345         [window orderOut:nil];
346     else
347         [window makeKeyAndOrderFront:nil];
348 }
349
350 void TestController::runModal(PlatformWebView* view)
351 {
352     NSWindow *window = [view->platformView() window];
353     if (!window)
354         return;
355     [NSApp runModalForWindow:window];
356 }
357
358 const char* TestController::platformLibraryPathForTesting()
359 {
360     return [[@"~/Library/Application Support/DumpRenderTree" stringByExpandingTildeInPath] UTF8String];
361 }
362
363 } // namespace WTR