2 * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "DumpRenderTree.h"
32 #include "LayoutTestController.h"
33 #include "WorkQueue.h"
34 #include "WorkQueueItem.h"
36 #include <JavaScriptCore/JavaScript.h>
41 #include "WebBrowserShell.h"
43 #include <wtf/Assertions.h>
50 volatile bool done = true;
51 volatile bool notified = false;
52 static bool printSeparators = true;
53 static int dumpPixels;
54 static int dumpTree = 1;
55 time_t startTime; // to detect timeouts / failed tests
58 using namespace WebKit;
62 RefPtr<LayoutTestController> gLayoutTestController;
63 static WebView* webView;
64 static wxTimer* idleTimer;
66 const unsigned timeOut = 10;
67 const unsigned maxViewHeight = 600;
68 const unsigned maxViewWidth = 800;
70 class LayoutWebViewEventHandler : public wxEvtHandler {
73 LayoutWebViewEventHandler(WebView* webView)
80 m_webView->Connect(wxEVT_WEBVIEW_LOAD, WebViewLoadEventHandler(LayoutWebViewEventHandler::OnLoadEvent), 0, this);
81 m_webView->Connect(wxEVT_WEBVIEW_JS_ALERT, WebViewAlertEventHandler(LayoutWebViewEventHandler::OnAlertEvent), 0, this);
82 m_webView->Connect(wxEVT_WEBVIEW_JS_CONFIRM, WebViewConfirmEventHandler(LayoutWebViewEventHandler::OnConfirmEvent), 0, this);
83 m_webView->Connect(wxEVT_WEBVIEW_JS_PROMPT, WebViewPromptEventHandler(LayoutWebViewEventHandler::OnPromptEvent), 0, this);
84 m_webView->Connect(wxEVT_WEBVIEW_CONSOLE_MESSAGE, WebViewConsoleMessageEventHandler(LayoutWebViewEventHandler::OnConsoleMessageEvent), 0, this);
85 m_webView->Connect(wxEVT_WEBVIEW_RECEIVED_TITLE, WebViewReceivedTitleEventHandler(LayoutWebViewEventHandler::OnReceivedTitleEvent), 0, this);
86 m_webView->Connect(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED, WebViewWindowObjectClearedEventHandler(LayoutWebViewEventHandler::OnWindowObjectClearedEvent), 0, this);
89 void OnLoadEvent(WebViewLoadEvent& event)
92 if (event.GetState() == WEBVIEW_LOAD_FAILED || event.GetState() == WEBVIEW_LOAD_STOPPED)
95 if (event.GetState() == WEBVIEW_LOAD_ONLOAD_HANDLED) {
98 if (!gLayoutTestController->waitToDump() || notified) {
104 void OnAlertEvent(WebViewAlertEvent& event)
106 wxFprintf(stdout, "ALERT: %S\n", event.GetMessage());
109 void OnConfirmEvent(WebViewConfirmEvent& event)
111 wxFprintf(stdout, "CONFIRM: %S\n", event.GetMessage());
112 event.SetReturnCode(1);
115 void OnPromptEvent(WebViewPromptEvent& event)
117 wxFprintf(stdout, "PROMPT: %S, default text: %S\n", event.GetMessage(), event.GetResponse());
118 event.SetReturnCode(1);
121 void OnConsoleMessageEvent(WebViewConsoleMessageEvent& event)
123 fprintf(stdout, "CONSOLE MESSAGE: ");
124 if (event.GetLineNumber())
125 fprintf(stdout, "line %d: ", event.GetLineNumber());
126 wxFprintf(stdout, "%S\n", event.GetMessage());
129 void OnReceivedTitleEvent(WebViewReceivedTitleEvent& event)
131 if (gLayoutTestController->dumpTitleChanges() && !done)
132 wxFprintf(stdout, "TITLE CHANGED: %S\n", event.GetTitle());
135 void OnWindowObjectClearedEvent(WebViewWindowObjectClearedEvent& event)
137 JSValueRef exception = 0;
138 gLayoutTestController->makeWindowObject(event.GetJSContext(), event.GetWindowObject(), &exception);
146 void notifyDoneFired()
153 LayoutWebViewEventHandler* eventHandler = 0;
155 static wxString dumpFramesAsText(WebFrame* frame)
157 // TODO: implement this. leaving this here so we don't forget this case.
158 if (gLayoutTestController->dumpChildFramesAsText()) {
161 return frame->GetInnerText();
169 if (gLayoutTestController->waitToDump() && !notified)
173 const char* result = 0;
175 bool dumpAsText = gLayoutTestController->dumpAsText();
177 if (gLayoutTestController->dumpAsText())
178 str = dumpFramesAsText(webView->GetMainFrame());
180 str = webView->GetMainFrame()->GetExternalRepresentation();
182 result = str.ToUTF8();
184 const char* errorMessage;
185 if (gLayoutTestController->dumpAsText())
186 errorMessage = "WebFrame::GetInnerText";
188 errorMessage = "WebFrame::GetExternalRepresentation";
189 printf("ERROR: 0 result from %s", errorMessage);
191 printf("%s\n", result);
194 if (gLayoutTestController->dumpBackForwardList()) {
195 // FIXME: not implemented
198 if (printSeparators) {
200 fputs("#EOF\n", stderr);
207 && gLayoutTestController->generatePixelResults()
208 && !gLayoutTestController->dumpDOMAsWebArchive()
209 && !gLayoutTestController->dumpSourceAsWebArchive()) {
210 // FIXME: Add support for dumping pixels
218 gLayoutTestController.clear();
221 static void runTest(const wxString testPathOrURL)
225 string pathOrURLString(testPathOrURL.char_str());
226 string pathOrURL(pathOrURLString);
227 string expectedPixelHash;
229 size_t separatorPos = pathOrURL.find("'");
230 if (separatorPos != string::npos) {
231 pathOrURL = string(pathOrURLString, 0, separatorPos);
232 expectedPixelHash = string(pathOrURLString, separatorPos + 1);
235 // CURL isn't happy if we don't have a protocol.
236 size_t http = pathOrURL.find("http://");
237 if (http == string::npos)
238 pathOrURL.insert(0, "file://");
240 gLayoutTestController = LayoutTestController::create(pathOrURL, expectedPixelHash);
241 if (!gLayoutTestController) {
242 wxTheApp->ExitMainLoop();
245 WorkQueue::shared()->clear();
246 WorkQueue::shared()->setFrozen(false);
248 webView->LoadURL(wxString(pathOrURL.c_str(), wxConvUTF8));
250 // wait until load completes and the results are dumped
255 class MyApp : public wxApp
259 virtual bool OnInit();
270 logOutput = fopen("output.txt", "ab");
272 logger = new wxLogStderr(logOutput);
273 wxLog::SetActiveTarget(logger);
276 wxLogMessage(wxT("Starting DumpRenderTool, %d args.\n"), argc);
278 for (int i = 1; i < argc; ++i) {
279 wxString option = wxString(argv[i]);
280 if (!option.CmpNoCase(_T("--notree"))) {
285 if (!option.CmpNoCase(_T("--pixel-tests"))) {
290 if (!option.CmpNoCase(_T("--tree"))) {
295 wxInitAllImageHandlers();
297 // create the main application window
298 WebBrowserShell* webFrame = new WebBrowserShell(_T("wxWebKit DumpRenderTree App"), "about:blank");
299 SetTopWindow(webFrame);
300 webView = webFrame->webview;
301 webView->SetSize(wxSize(maxViewWidth, maxViewHeight));
304 eventHandler = new LayoutWebViewEventHandler(webView);
305 eventHandler->bindEvents();
310 wxString option_str = wxString(argv[optind]);
311 if (argc == optind+1 && option_str.Find(_T("-")) == 0) {
312 char filenameBuffer[2048];
313 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
314 wxString filename = wxString::FromUTF8(filenameBuffer);
315 char* newLineCharacter = strchr(filenameBuffer, '\n');
316 if (newLineCharacter)
317 *newLineCharacter = '\0';
319 if (strlen(filenameBuffer) == 0)
321 wxLogMessage(wxT("Running test %S.\n"), filenameBuffer);
326 printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
327 for (int i = optind; i != argc; ++i) {
328 runTest(wxTheApp->argv[1]);
335 wxLog::SetActiveTarget(0);
339 // returning false shuts the app down