10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com>
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Redistribution and use in source and binary forms, with or without
50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * modification, are permitted provided that the following conditions
60bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * are met:
70bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 1.  Redistributions of source code must retain the above copyright
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     notice, this list of conditions and the following disclaimer.
100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 2.  Redistributions in binary form must reproduce the above copyright
110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     notice, this list of conditions and the following disclaimer in the
120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     documentation and/or other materials provided with the distribution.
130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     its contributors may be used to endorse or promote products derived
150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     from this software without specific prior written permission.
160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch */
280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h"
300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "DumpRenderTree.h"
310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "LayoutTestController.h"
330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WorkQueue.h"
340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WorkQueueItem.h"
350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <JavaScriptCore/JavaScript.h>
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <wx/wx.h>
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WebView.h"
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WebFrame.h"
410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "WebBrowserShell.h"
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <wtf/Assertions.h>
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <cassert>
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <stdlib.h>
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <string.h>
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <time.h>
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvolatile bool done = true;
510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvolatile bool notified = false;
520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool printSeparators = true;
530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int dumpPixels;
540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic int dumpTree = 1;
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochtime_t startTime; // to detect timeouts / failed tests
560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochusing namespace std;
580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochFILE* logOutput;
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenRefPtr<LayoutTestController> gLayoutTestController;
620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic wxWebView* webView;
630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic wxTimer* idleTimer;
640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochconst unsigned timeOut = 10;
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochconst unsigned maxViewHeight = 600;
670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochconst unsigned maxViewWidth = 800;
680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass LayoutWebViewEventHandler : public wxEvtHandler {
700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic:
720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    LayoutWebViewEventHandler(wxWebView* webView)
730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        : m_webView(webView)
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void bindEvents()
780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_LOAD, wxWebViewLoadEventHandler(LayoutWebViewEventHandler::OnLoadEvent), NULL, this);
800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_JS_ALERT, wxWebViewAlertEventHandler(LayoutWebViewEventHandler::OnAlertEvent), NULL, this);
810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_JS_CONFIRM, wxWebViewConfirmEventHandler(LayoutWebViewEventHandler::OnConfirmEvent), NULL, this);
820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_JS_PROMPT, wxWebViewPromptEventHandler(LayoutWebViewEventHandler::OnPromptEvent), NULL, this);
830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_CONSOLE_MESSAGE, wxWebViewConsoleMessageEventHandler(LayoutWebViewEventHandler::OnConsoleMessageEvent), NULL, this);
840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_RECEIVED_TITLE, wxWebViewReceivedTitleEventHandler(LayoutWebViewEventHandler::OnReceivedTitleEvent), NULL, this);
850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_webView->Connect(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED, wxWebViewWindowObjectClearedEventHandler(LayoutWebViewEventHandler::OnWindowObjectClearedEvent), NULL, this);
860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnLoadEvent(wxWebViewLoadEvent& event)
890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (event.GetState() == wxWEBVIEW_LOAD_FAILED || event.GetState() == wxWEBVIEW_LOAD_STOPPED)
920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            done = true;
930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (event.GetState() == wxWEBVIEW_LOAD_ONLOAD_HANDLED) {
950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            done = true;
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (!gLayoutTestController->waitToDump() || notified) {
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                dump();
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnAlertEvent(wxWebViewAlertEvent& event)
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        fprintf(stdout, "ALERT: %S\n", event.GetMessage().c_str());
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnConfirmEvent(wxWebViewConfirmEvent& event)
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        fprintf(stdout, "CONFIRM: %S\n", event.GetMessage().c_str());
1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        event.SetReturnCode(1);
1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnPromptEvent(wxWebViewPromptEvent& event)
1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        fprintf(stdout, "PROMPT: %S, default text: %S\n", event.GetMessage().c_str(), event.GetResponse().c_str());
1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        event.SetReturnCode(1);
1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnConsoleMessageEvent(wxWebViewConsoleMessageEvent& event)
1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        fprintf(stdout, "CONSOLE MESSAGE: line %d: %S\n", event.GetLineNumber(), event.GetMessage().c_str());
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnReceivedTitleEvent(wxWebViewReceivedTitleEvent& event)
1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (gLayoutTestController->dumpTitleChanges() && !done) {
1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const char* title = event.GetTitle().mb_str(wxConvUTF8);
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            printf("TITLE CHANGED: %S\n", title ? title : "");
1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    void OnWindowObjectClearedEvent(wxWebViewWindowObjectClearedEvent& event)
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        JSValueRef exception = 0;
1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        gLayoutTestController->makeWindowObject(event.GetJSContext(), event.GetWindowObject(), &exception);
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate:
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxWebView* m_webView;
1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid notifyDoneFired()
1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    notified = true;
1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (done)
1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        dump();
1490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochLayoutWebViewEventHandler* eventHandler = NULL;
1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic wxString dumpFramesAsText(wxWebFrame* frame)
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // TODO: implement this. leaving this here so we don't forget this case.
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (gLayoutTestController->dumpChildFramesAsText()) {
1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return frame->GetInnerText();
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid dump()
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!done)
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (gLayoutTestController->waitToDump() && !notified)
1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (dumpTree) {
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        const char* result = 0;
1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool dumpAsText = gLayoutTestController->dumpAsText();
1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        wxString str;
1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (gLayoutTestController->dumpAsText())
1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            str = dumpFramesAsText(webView->GetMainFrame());
1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        else
1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            str = webView->GetMainFrame()->GetExternalRepresentation();
1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        result = str.ToUTF8();
1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!result) {
1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const char* errorMessage;
1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (gLayoutTestController->dumpAsText())
1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                errorMessage = "WebFrame::GetInnerText";
1850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            else
1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                errorMessage = "WebFrame::GetExternalRepresentation";
1870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            printf("ERROR: NULL result from %s", errorMessage);
1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else {
1890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            printf("%s\n", result);
1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (gLayoutTestController->dumpBackForwardList()) {
1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // FIXME: not implemented
1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (printSeparators) {
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            puts("#EOF");
1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            fputs("#EOF\n", stderr);
1990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            fflush(stdout);
2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            fflush(stderr);
2010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
2020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
204967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (dumpPixels
205967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        && gLayoutTestController->generatePixelResults()
206967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        && !gLayoutTestController->dumpDOMAsWebArchive()
207967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        && !gLayoutTestController->dumpSourceAsWebArchive()) {
208967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        // FIXME: Add support for dumping pixels
2090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        fflush(stdout);
2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    puts("#EOF");
2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    fflush(stdout);
2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    fflush(stderr);
2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
21606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gLayoutTestController.clear();
2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void runTest(const wxString testPathOrURL)
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    done = false;
2220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    time(&startTime);
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    string pathOrURLString(testPathOrURL.char_str());
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    string pathOrURL(pathOrURLString);
2250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    string expectedPixelHash;
2260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    size_t separatorPos = pathOrURL.find("'");
2280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (separatorPos != string::npos) {
2290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        pathOrURL = string(pathOrURLString, 0, separatorPos);
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        expectedPixelHash = string(pathOrURLString, separatorPos + 1);
2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // CURL isn't happy if we don't have a protocol.
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    size_t http = pathOrURL.find("http://");
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (http == string::npos)
2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        pathOrURL.insert(0, "file://");
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
23806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen    gLayoutTestController = LayoutTestController::create(pathOrURL, expectedPixelHash);
2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!gLayoutTestController) {
2400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        wxTheApp->ExitMainLoop();
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    WorkQueue::shared()->clear();
2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    WorkQueue::shared()->setFrozen(false);
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    webView->LoadURL(wxString(pathOrURL.c_str(), wxConvUTF8));
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // wait until load completes and the results are dumped
2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (!done)
2500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        wxSafeYield();
2510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass MyApp : public wxApp
2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochpublic:
2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    virtual bool OnInit();
2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochprivate:
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxLog* logger;
2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch};
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochIMPLEMENT_APP(MyApp)
2650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool MyApp::OnInit()
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    logOutput = fopen("output.txt", "ab");
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (logOutput) {
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        logger = new wxLogStderr(logOutput);
2710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        wxLog::SetActiveTarget(logger);
2720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxLogMessage(wxT("Starting DumpRenderTool, %d args.\n"), argc);
2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    for (int i = 1; i < argc; ++i) {
2770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        wxString option = wxString(argv[i]);
2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!option.CmpNoCase(_T("--notree"))) {
2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            dumpTree = false;
2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            continue;
2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
2820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!option.CmpNoCase(_T("--pixel-tests"))) {
2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            dumpPixels = true;
2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            continue;
2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!option.CmpNoCase(_T("--tree"))) {
2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            dumpTree = true;
2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            continue;
2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxInitAllImageHandlers();
2940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // create the main application window
2960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxWebBrowserShell* webFrame = new wxWebBrowserShell(_T("wxWebKit DumpRenderTree App"));
2970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SetTopWindow(webFrame);
2980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    webView = webFrame->webview;
2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    webView->SetSize(wxSize(maxViewWidth, maxViewHeight));
3000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!eventHandler) {
3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        eventHandler = new LayoutWebViewEventHandler(webView);
3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        eventHandler->bindEvents();
3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    int optind = 1;
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    time(&startTime);
3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxString option_str = wxString(argv[optind]);
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (argc == optind+1 && option_str.Find(_T("-")) == 0) {
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        char filenameBuffer[2048];
3110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            wxString filename = wxString::FromUTF8(filenameBuffer);
3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            char* newLineCharacter = strchr(filenameBuffer, '\n');
3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (newLineCharacter)
3150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                *newLineCharacter = '\0';
3160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (strlen(filenameBuffer) == 0)
3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return 0;
3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            wxLogMessage(wxT("Running test %S.\n"), filenameBuffer);
3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            runTest(filename);
3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    } else {
3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (int i = optind; i != argc; ++i) {
3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            runTest(wxTheApp->argv[1]);
3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
3280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    webFrame->Close();
3310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    delete eventHandler;
3320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wxLog::SetActiveTarget(NULL);
3340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    delete logger;
3350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    fclose(logOutput);
3360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // returning false shuts the app down
3380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return false;
3390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
340