6f97b9fd98341e58005eb13e9612cd0507d459d8
[WebKit.git] / WebKitTools / WebKitTestRunner / TestController.cpp
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 #include "TestController.h"
27
28 #include "PlatformWebView.h"
29 #include "StringFunctions.h"
30 #include "TestInvocation.h"
31 #include <WebKit2/WKContextPrivate.h>
32 #include <WebKit2/WKPreferencesPrivate.h>
33 #include <wtf/PassOwnPtr.h>
34
35 namespace WTR {
36
37 static TestController* controller;
38
39 TestController& TestController::shared()
40 {
41     ASSERT(controller);
42     return *controller;
43 }
44
45 TestController::TestController(int argc, const char* argv[])
46     : m_dumpPixels(false)
47     , m_verbose(false)
48     , m_printSeparators(false)
49     , m_usingServerMode(false)
50     , m_state(Initial)
51     , m_doneResetting(false)
52 {
53     initialize(argc, argv);
54     controller = this;
55     run();
56     controller = 0;
57 }
58
59 TestController::~TestController()
60 {
61 }
62
63 static void closeOtherPage(WKPageRef page, const void* clientInfo)
64 {
65     WKPageClose(page);
66     const PlatformWebView* view = static_cast<const PlatformWebView*>(clientInfo);
67     delete view;
68 }
69
70 static WKPageRef createOtherPage(WKPageRef oldPage, const void*)
71 {
72     PlatformWebView* view = new PlatformWebView(WKPageGetPageNamespace(oldPage));
73     WKPageRef newPage = view->page();
74
75     view->resizeTo(800, 600);
76
77     WKPageUIClient otherPageUIClient = {
78         0,
79         view,
80         createOtherPage,
81         0,
82         closeOtherPage,
83         0,
84         0,
85         0,
86         0
87     };
88     WKPageSetPageUIClient(newPage, &otherPageUIClient);
89
90     WKRetain(newPage);
91     return newPage;
92 }
93
94 void TestController::initialize(int argc, const char* argv[])
95 {
96     platformInitialize();
97
98     bool printSupportedFeatures = false;
99
100     for (int i = 1; i < argc; ++i) {
101         std::string argument(argv[i]);
102
103         if (argument == "--pixel-tests") {
104             m_dumpPixels = true;
105             continue;
106         }
107         if (argument == "--verbose") {
108             m_verbose = true;
109             continue;
110         }
111         if (argument == "--print-supported-features") {
112             printSupportedFeatures = true;
113             break;
114         }
115
116         // Skip any other arguments that begin with '--'.
117         if (argument.length() >= 2 && argument[0] == '-' && argument[1] == '-')
118             continue;
119
120         m_paths.push_back(argument);
121     }
122
123     if (printSupportedFeatures) {
124         // FIXME: On Windows, DumpRenderTree uses this to expose whether it supports 3d
125         // transforms and accelerated compositing. When we support those features, we
126         // should match DRT's behavior.
127         exit(0);
128     }
129
130     m_usingServerMode = (m_paths.size() == 1 && m_paths[0] == "-");
131     if (m_usingServerMode)
132         m_printSeparators = true;
133     else
134         m_printSeparators = m_paths.size() > 1;
135
136     initializeInjectedBundlePath();
137     initializeTestPluginDirectory();
138
139     m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));
140     platformInitializeContext();
141
142     WKContextInjectedBundleClient injectedBundleClient = {
143         0,
144         this,
145         didReceiveMessageFromInjectedBundle
146     };
147     WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);
148
149     _WKContextSetAdditionalPluginsDirectory(m_context.get(), testPluginDirectory());
150
151     m_pageNamespace.adopt(WKPageNamespaceCreate(m_context.get()));
152     m_mainWebView = adoptPtr(new PlatformWebView(m_pageNamespace.get()));
153
154     WKPageUIClient pageUIClient = {
155         0,
156         this,
157         createOtherPage,
158         0,
159         0,
160         0,
161         0,
162         0,
163         0
164     };
165     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);
166
167     WKPageLoaderClient pageLoaderClient = {
168         0,
169         this,
170         0,
171         0,
172         0,
173         0,
174         0,
175         didFinishLoadForFrame,
176         0,
177         0,
178         0,
179         0,
180         0,
181         0,
182         0,
183         0,
184         0,
185         0,
186         0
187     };
188     WKPageSetPageLoaderClient(m_mainWebView->page(), &pageLoaderClient);
189 }
190
191 void TestController::resetStateToConsistentValues()
192 {
193     m_state = Resetting;
194
195     // FIXME: This function should also ensure that there is only one page open.
196
197     // Reset preferences
198     WKPreferencesRef preferences = WKContextGetPreferences(m_context.get());
199     WKPreferencesSetOfflineWebApplicationCacheEnabled(preferences, true);
200     WKPreferencesSetFontSmoothingLevel(preferences, kWKFontSmoothingLevelNoSubpixelAntiAliasing);
201     WKPreferencesSetXSSAuditorEnabled(preferences, false);
202
203     m_mainWebView->focus();
204
205     // Reset main page back to about:blank
206     m_doneResetting = false;
207
208     WKRetainPtr<WKURLRef> url(AdoptWK, createWKURL("about:blank"));
209     WKPageLoadURL(m_mainWebView->page(), url.get());
210     TestController::runUntil(m_doneResetting);
211 }
212
213 void TestController::runTest(const char* test)
214 {
215     resetStateToConsistentValues();
216
217     m_state = RunningTest;
218     m_currentInvocation.set(new TestInvocation(test));
219     m_currentInvocation->invoke();
220     m_currentInvocation.clear();
221 }
222
223 void TestController::runTestingServerLoop()
224 {
225     char filenameBuffer[2048];
226     while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
227         char *newLineCharacter = strchr(filenameBuffer, '\n');
228         if (newLineCharacter)
229             *newLineCharacter = '\0';
230
231         if (strlen(filenameBuffer) == 0)
232             continue;
233
234         runTest(filenameBuffer);
235     }
236 }
237
238 void TestController::run()
239 {
240     if (m_usingServerMode)
241         runTestingServerLoop();
242     else {
243         for (size_t i = 0; i < m_paths.size(); ++i)
244             runTest(m_paths[i].c_str());
245     }
246 }
247
248 // WKContextInjectedBundleClient
249
250 void TestController::didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo)
251 {
252     static_cast<TestController*>(const_cast<void*>(clientInfo))->didReceiveMessageFromInjectedBundle(messageName, messageBody);
253 }
254
255 void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName, WKTypeRef messageBody)
256 {
257     m_currentInvocation->didReceiveMessageFromInjectedBundle(messageName, messageBody);
258 }
259
260 // WKPageLoaderClient
261
262 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, const void* clientInfo)
263 {
264     static_cast<TestController*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(page, frame);
265 }
266
267 void TestController::didFinishLoadForFrame(WKPageRef page, WKFrameRef frame)
268 {
269     if (m_state != Resetting)
270         return;
271
272     if (!WKFrameIsMainFrame(frame))
273         return;
274
275     WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKFrameCopyURL(frame));
276     RetainPtr<CFURLRef> cfURL= toCF(wkURL);
277     CFStringRef cfURLString = CFURLGetString(cfURL.get());
278     if (!CFEqual(cfURLString, CFSTR("about:blank")))
279         return;
280
281     m_doneResetting = true;
282 }
283
284 } // namespace WTR