WebKitTools/DumpRenderTree/wx/DumpRenderTreeWx.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com>
       
     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  *
       
     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.
       
    16  *
       
    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.
       
    27  */
       
    28 
       
    29 #include "config.h"
       
    30 #include "DumpRenderTree.h"
       
    31 
       
    32 #include "LayoutTestController.h"
       
    33 #include "WorkQueue.h"
       
    34 #include "WorkQueueItem.h"
       
    35 
       
    36 #include <JavaScriptCore/JavaScript.h>
       
    37 
       
    38 #include <wx/wx.h>
       
    39 #include "WebView.h"
       
    40 #include "WebFrame.h"
       
    41 #include "WebBrowserShell.h"
       
    42 
       
    43 #include <wtf/Assertions.h>
       
    44 
       
    45 #include <cassert>
       
    46 #include <stdlib.h>
       
    47 #include <string.h>
       
    48 #include <time.h>
       
    49 
       
    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
       
    56 
       
    57 using namespace std;
       
    58 
       
    59 FILE* logOutput;
       
    60 
       
    61 RefPtr<LayoutTestController> gLayoutTestController;
       
    62 static wxWebView* webView;
       
    63 static wxTimer* idleTimer;
       
    64 
       
    65 const unsigned timeOut = 10;
       
    66 const unsigned maxViewHeight = 600;
       
    67 const unsigned maxViewWidth = 800;
       
    68 
       
    69 class LayoutWebViewEventHandler : public wxEvtHandler {
       
    70 
       
    71 public:
       
    72     LayoutWebViewEventHandler(wxWebView* webView)
       
    73         : m_webView(webView)
       
    74     {
       
    75     }
       
    76     
       
    77     void bindEvents() 
       
    78     {
       
    79         m_webView->Connect(wxEVT_WEBVIEW_LOAD, wxWebViewLoadEventHandler(LayoutWebViewEventHandler::OnLoadEvent), NULL, this);
       
    80         m_webView->Connect(wxEVT_WEBVIEW_JS_ALERT, wxWebViewAlertEventHandler(LayoutWebViewEventHandler::OnAlertEvent), NULL, this);
       
    81         m_webView->Connect(wxEVT_WEBVIEW_JS_CONFIRM, wxWebViewConfirmEventHandler(LayoutWebViewEventHandler::OnConfirmEvent), NULL, this);
       
    82         m_webView->Connect(wxEVT_WEBVIEW_JS_PROMPT, wxWebViewPromptEventHandler(LayoutWebViewEventHandler::OnPromptEvent), NULL, this);
       
    83         m_webView->Connect(wxEVT_WEBVIEW_CONSOLE_MESSAGE, wxWebViewConsoleMessageEventHandler(LayoutWebViewEventHandler::OnConsoleMessageEvent), NULL, this);
       
    84         m_webView->Connect(wxEVT_WEBVIEW_RECEIVED_TITLE, wxWebViewReceivedTitleEventHandler(LayoutWebViewEventHandler::OnReceivedTitleEvent), NULL, this);
       
    85         m_webView->Connect(wxEVT_WEBVIEW_WINDOW_OBJECT_CLEARED, wxWebViewWindowObjectClearedEventHandler(LayoutWebViewEventHandler::OnWindowObjectClearedEvent), NULL, this);
       
    86     }
       
    87     
       
    88     void OnLoadEvent(wxWebViewLoadEvent& event) 
       
    89     {
       
    90 
       
    91         if (event.GetState() == wxWEBVIEW_LOAD_FAILED || event.GetState() == wxWEBVIEW_LOAD_STOPPED)
       
    92             done = true; 
       
    93         
       
    94         if (event.GetState() == wxWEBVIEW_LOAD_ONLOAD_HANDLED) {
       
    95             done = true;
       
    96             
       
    97             if (!gLayoutTestController->waitToDump() || notified) {
       
    98                 dump();
       
    99             }
       
   100         }
       
   101     }
       
   102     
       
   103     void OnAlertEvent(wxWebViewAlertEvent& event)
       
   104     {
       
   105         fprintf(stdout, "ALERT: %S\n", event.GetMessage().c_str());
       
   106     }
       
   107     
       
   108     void OnConfirmEvent(wxWebViewConfirmEvent& event)
       
   109     {
       
   110         fprintf(stdout, "CONFIRM: %S\n", event.GetMessage().c_str());
       
   111         event.SetReturnCode(1);
       
   112     }
       
   113     
       
   114     void OnPromptEvent(wxWebViewPromptEvent& event)
       
   115     {
       
   116         fprintf(stdout, "PROMPT: %S, default text: %S\n", event.GetMessage().c_str(), event.GetResponse().c_str());
       
   117         event.SetReturnCode(1);
       
   118     }
       
   119     
       
   120     void OnConsoleMessageEvent(wxWebViewConsoleMessageEvent& event)
       
   121     {
       
   122         fprintf(stdout, "CONSOLE MESSAGE: line %d: %S\n", event.GetLineNumber(), event.GetMessage().c_str());
       
   123     }
       
   124     
       
   125     void OnReceivedTitleEvent(wxWebViewReceivedTitleEvent& event)
       
   126     {
       
   127         if (gLayoutTestController->dumpTitleChanges() && !done) {
       
   128             const char* title = event.GetTitle().mb_str(wxConvUTF8);
       
   129             printf("TITLE CHANGED: %S\n", title ? title : "");
       
   130         }
       
   131     }
       
   132     
       
   133     void OnWindowObjectClearedEvent(wxWebViewWindowObjectClearedEvent& event)
       
   134     {
       
   135         JSValueRef exception = 0;
       
   136         gLayoutTestController->makeWindowObject(event.GetJSContext(), event.GetWindowObject(), &exception);
       
   137     }
       
   138     
       
   139 private:
       
   140     wxWebView* m_webView;
       
   141 
       
   142 };
       
   143 
       
   144 void notifyDoneFired() 
       
   145 {
       
   146     notified = true;
       
   147     if (done)
       
   148         dump();
       
   149 }
       
   150 
       
   151 LayoutWebViewEventHandler* eventHandler = NULL;
       
   152 
       
   153 static wxString dumpFramesAsText(wxWebFrame* frame)
       
   154 {
       
   155     // TODO: implement this. leaving this here so we don't forget this case.
       
   156     if (gLayoutTestController->dumpChildFramesAsText()) {
       
   157     }
       
   158     
       
   159     return frame->GetInnerText();
       
   160 }
       
   161 
       
   162 void dump()
       
   163 {    
       
   164     if (!done)
       
   165         return;
       
   166     
       
   167     if (gLayoutTestController->waitToDump() && !notified)
       
   168         return;
       
   169         
       
   170     if (dumpTree) {
       
   171         const char* result = 0;
       
   172 
       
   173         bool dumpAsText = gLayoutTestController->dumpAsText();
       
   174         wxString str;
       
   175         if (gLayoutTestController->dumpAsText())
       
   176             str = dumpFramesAsText(webView->GetMainFrame());
       
   177         else 
       
   178             str = webView->GetMainFrame()->GetExternalRepresentation();
       
   179 
       
   180         result = str.ToUTF8();
       
   181         if (!result) {
       
   182             const char* errorMessage;
       
   183             if (gLayoutTestController->dumpAsText())
       
   184                 errorMessage = "WebFrame::GetInnerText";
       
   185             else
       
   186                 errorMessage = "WebFrame::GetExternalRepresentation";
       
   187             printf("ERROR: NULL result from %s", errorMessage);
       
   188         } else {
       
   189             printf("%s\n", result);
       
   190         }
       
   191 
       
   192         if (gLayoutTestController->dumpBackForwardList()) {
       
   193             // FIXME: not implemented
       
   194         }
       
   195 
       
   196         if (printSeparators) {
       
   197             puts("#EOF");
       
   198             fputs("#EOF\n", stderr);
       
   199             fflush(stdout);
       
   200             fflush(stderr);
       
   201         }
       
   202     }
       
   203 
       
   204     if (dumpPixels
       
   205         && gLayoutTestController->generatePixelResults()
       
   206         && !gLayoutTestController->dumpDOMAsWebArchive()
       
   207         && !gLayoutTestController->dumpSourceAsWebArchive()) {
       
   208         // FIXME: Add support for dumping pixels
       
   209         fflush(stdout);
       
   210     }
       
   211 
       
   212     puts("#EOF");
       
   213     fflush(stdout);
       
   214     fflush(stderr);
       
   215 
       
   216     gLayoutTestController.clear();
       
   217 }
       
   218 
       
   219 static void runTest(const wxString testPathOrURL)
       
   220 {
       
   221     done = false;
       
   222     time(&startTime);
       
   223     string pathOrURLString(testPathOrURL.char_str());
       
   224     string pathOrURL(pathOrURLString);
       
   225     string expectedPixelHash;
       
   226 
       
   227     size_t separatorPos = pathOrURL.find("'");
       
   228     if (separatorPos != string::npos) {
       
   229         pathOrURL = string(pathOrURLString, 0, separatorPos);
       
   230         expectedPixelHash = string(pathOrURLString, separatorPos + 1);
       
   231     }
       
   232     
       
   233     // CURL isn't happy if we don't have a protocol.
       
   234     size_t http = pathOrURL.find("http://");
       
   235     if (http == string::npos)
       
   236         pathOrURL.insert(0, "file://");
       
   237     
       
   238     gLayoutTestController = LayoutTestController::create(pathOrURL, expectedPixelHash);
       
   239     if (!gLayoutTestController) {
       
   240         wxTheApp->ExitMainLoop();
       
   241     }
       
   242 
       
   243     WorkQueue::shared()->clear();
       
   244     WorkQueue::shared()->setFrozen(false);
       
   245 
       
   246     webView->LoadURL(wxString(pathOrURL.c_str(), wxConvUTF8));
       
   247     
       
   248     // wait until load completes and the results are dumped
       
   249     while (!done)
       
   250         wxSafeYield();
       
   251 }
       
   252 
       
   253 class MyApp : public wxApp
       
   254 {
       
   255 public:
       
   256 
       
   257     virtual bool OnInit();
       
   258     
       
   259 private:
       
   260     wxLog* logger;
       
   261 };
       
   262 
       
   263 
       
   264 IMPLEMENT_APP(MyApp)
       
   265 
       
   266 bool MyApp::OnInit()
       
   267 {
       
   268     logOutput = fopen("output.txt", "ab");
       
   269     if (logOutput) {
       
   270         logger = new wxLogStderr(logOutput);
       
   271         wxLog::SetActiveTarget(logger);
       
   272     }
       
   273 
       
   274     wxLogMessage(wxT("Starting DumpRenderTool, %d args.\n"), argc);
       
   275 
       
   276     for (int i = 1; i < argc; ++i) {
       
   277         wxString option = wxString(argv[i]);
       
   278         if (!option.CmpNoCase(_T("--notree"))) {
       
   279             dumpTree = false;
       
   280             continue;
       
   281         }
       
   282         
       
   283         if (!option.CmpNoCase(_T("--pixel-tests"))) {
       
   284             dumpPixels = true;
       
   285             continue;
       
   286         }
       
   287         
       
   288         if (!option.CmpNoCase(_T("--tree"))) {
       
   289             dumpTree = true;
       
   290             continue;
       
   291         }
       
   292     }
       
   293     wxInitAllImageHandlers();
       
   294         
       
   295     // create the main application window
       
   296     wxWebBrowserShell* webFrame = new wxWebBrowserShell(_T("wxWebKit DumpRenderTree App"));
       
   297     SetTopWindow(webFrame);
       
   298     webView = webFrame->webview;
       
   299     webView->SetSize(wxSize(maxViewWidth, maxViewHeight));
       
   300     
       
   301     if (!eventHandler) {
       
   302         eventHandler = new LayoutWebViewEventHandler(webView);
       
   303         eventHandler->bindEvents();
       
   304     }
       
   305 
       
   306     int optind = 1;
       
   307     time(&startTime);
       
   308     wxString option_str = wxString(argv[optind]);
       
   309     if (argc == optind+1 && option_str.Find(_T("-")) == 0) {
       
   310         char filenameBuffer[2048];
       
   311         while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
       
   312             wxString filename = wxString::FromUTF8(filenameBuffer);
       
   313             char* newLineCharacter = strchr(filenameBuffer, '\n');
       
   314             if (newLineCharacter)
       
   315                 *newLineCharacter = '\0';
       
   316 
       
   317             if (strlen(filenameBuffer) == 0)
       
   318                 return 0;
       
   319             wxLogMessage(wxT("Running test %S.\n"), filenameBuffer);
       
   320             runTest(filename);
       
   321         }
       
   322     
       
   323     } else {
       
   324         printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
       
   325         for (int i = optind; i != argc; ++i) {
       
   326             runTest(wxTheApp->argv[1]);
       
   327         }
       
   328     }
       
   329     
       
   330     webFrame->Close();
       
   331     delete eventHandler;
       
   332 
       
   333     wxLog::SetActiveTarget(NULL);
       
   334     delete logger;
       
   335     fclose(logOutput);
       
   336     
       
   337     // returning false shuts the app down
       
   338     return false;
       
   339 }