2007-12-04 Xan Lopez <xan@gnome.org>
[WebKit-https.git] / WebKitTools / DumpRenderTree / gtk / DumpRenderTree.cpp
1 /*
2  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
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 falseT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN false EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT falseT 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 "webkitwebframe.h"
30 #include "webkitwebview.h"
31
32 #include <gtk/gtk.h>
33
34 #include <string.h>
35
36 #include <JavaScriptCore/JSBase.h>
37 #include <JavaScriptCore/JSContextRef.h>
38 #include <JavaScriptCore/JSStringRef.h>
39 #include <JavaScriptCore/JSObjectRef.h>
40 #include <JavaScriptCore/JSValueRef.h>
41
42 #include "LayoutTestController.h"
43 #include "WorkQueue.h"
44 #include "WorkQueueItem.h"
45
46 #include <getopt.h>
47 #include <stdlib.h>
48
49 extern "C" {
50 // This API is not yet public.
51 extern GSList* webkit_web_frame_get_children(WebKitWebFrame* frame);
52 extern gchar* webkit_web_frame_get_inner_text(WebKitWebFrame* frame);
53 }
54
55 volatile bool done;
56 static bool printSeparators;
57 static int testRepaintDefault;
58 static int repaintSweepHorizontallyDefault;
59 static int dumpPixels;
60 static int dumpTree;
61 static gchar* currentTest;
62
63 LayoutTestController* layoutTestController = 0;
64 static WebKitWebView* view;
65 WebKitWebFrame* mainFrame = 0;
66
67 const unsigned maxViewHeight = 600;
68 const unsigned maxViewWidth = 800;
69
70 static gchar* autocorrectURL(const gchar* url)
71 {
72     if (strncmp("http://", url, 7) != 0 && strncmp("https://", url, 8) != 0) {
73         GString* string = g_string_new("file://");
74         g_string_append(string, url);
75         return g_string_free(string, FALSE);
76     }
77
78     return g_strdup(url);
79 }
80
81 static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
82 {
83     return strstr(pathOrURL, "loading/");
84 }
85
86 void dumpFrameScrollPosition(WebKitWebFrame* frame)
87 {
88
89 }
90
91 void displayWebView()
92 {
93
94 }
95
96 static void appendString(gchar*& target, gchar* string)
97 {
98     gchar* oldString = target;
99     target = g_strconcat(target, string, NULL);
100     g_free(oldString);
101 }
102
103 static gchar* dumpFramesAsText(WebKitWebFrame* frame)
104 {
105     gchar* result = 0;
106
107     // Add header for all but the main frame.
108     bool isMainFrame = (webkit_web_view_get_main_frame(view) == frame);
109
110     if (isMainFrame) {
111         const gchar* frameName = webkit_web_frame_get_name(frame);
112         gchar* innerText = webkit_web_frame_get_inner_text(frame);
113
114         result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s", frameName, innerText);
115
116         g_free(innerText);
117     }
118
119     if (layoutTestController->dumpChildFramesAsText()) {
120         GSList* children = webkit_web_frame_get_children(frame);
121         for (;children; children = g_slist_next(children))
122            appendString(result, dumpFramesAsText((WebKitWebFrame*)children->data));
123     }
124
125     return result;
126 }
127
128 static gchar* dumpRenderTreeAsText(WebKitWebFrame* frame)
129 {
130     // FIXME: this will require new WebKitGtk SPI
131     return strdup("foo");
132 }
133
134 void dump()
135 {
136     if (dumpTree) {
137         char* result = 0;
138
139         bool dumpAsText = layoutTestController->dumpAsText();
140         // FIXME: Also dump text resuls as text.
141         layoutTestController->setDumpAsText(dumpAsText);
142         if (layoutTestController->dumpAsText())
143             result = dumpFramesAsText(mainFrame);
144         else {
145             bool isSVGW3CTest = (g_strrstr(currentTest, "svg/W3C-SVG-1.1"));
146             if (isSVGW3CTest)
147                 gtk_widget_set_size_request(GTK_WIDGET(view), 480, 360);
148             else
149                 gtk_widget_set_size_request(GTK_WIDGET(view), maxViewWidth, maxViewHeight);
150             result = dumpRenderTreeAsText(mainFrame);
151         }
152
153         if (!result) {
154             const char* errorMessage;
155             if (layoutTestController->dumpAsText())
156                 errorMessage = "[documentElement innerText]";
157             else if (layoutTestController->dumpDOMAsWebArchive())
158                 errorMessage = "[[mainFrame DOMDocument] webArchive]";
159             else if (layoutTestController->dumpSourceAsWebArchive())
160                 errorMessage = "[[mainFrame dataSource] webArchive]";
161             else
162                 errorMessage = "[mainFrame renderTreeAsExternalRepresentation]";
163             printf("ERROR: nil result from %s", errorMessage);
164         } else {
165             printf("%s", result);
166         g_free(result);
167             if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive())
168                 dumpFrameScrollPosition(mainFrame);
169         }
170
171         if (layoutTestController->dumpBackForwardList()) {
172             // FIXME: not implemented
173         }
174
175         if (printSeparators)
176             puts("#EOF");
177     }
178
179     if (dumpPixels) {
180         if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) {
181             // FIXME: Add support for dumping pixels
182         }
183     }
184
185     fflush(stdout);
186
187     // FIXME: call displayWebView here when we support --paint
188
189     done = true;
190 }
191
192 static void runTest(const char* pathOrURL)
193 {
194     gchar* url = autocorrectURL(pathOrURL);
195
196     layoutTestController = new LayoutTestController(testRepaintDefault, repaintSweepHorizontallyDefault);
197
198     done = false;
199
200     if (shouldLogFrameLoadDelegates(pathOrURL))
201         layoutTestController->setDumpFrameLoadCallbacks(true);
202
203     if (currentTest)
204         g_free(currentTest);
205     currentTest = url;
206
207     WorkQueue::shared()->clear();
208     WorkQueue::shared()->setFrozen(false);
209
210     webkit_web_view_open(view, url);
211
212     while (!done)
213         g_main_context_iteration(NULL, true);
214
215     WorkQueue::shared()->clear();
216
217     delete layoutTestController;
218     layoutTestController = 0;
219 }
220
221 int main(int argc, char* argv[])
222 {
223
224     struct option options[] = {
225         {"horizontal-sweep", no_argument, &repaintSweepHorizontallyDefault, true},
226         {"notree", no_argument, &dumpTree, false},
227         {"pixel-tests", no_argument, &dumpPixels, true},
228         {"repaint", no_argument, &testRepaintDefault, true},
229         {"tree", no_argument, &dumpTree, true},
230         {NULL, 0, NULL, 0}
231     };
232
233     int option;
234     while ((option = getopt_long(argc, (char* const*)argv, "", options, NULL)) != -1)
235         switch (option) {
236             case '?':   // unknown or ambiguous option
237             case ':':   // missing argument
238                 exit(1);
239                 break;
240         }
241
242     view = WEBKIT_WEB_VIEW(webkit_web_view_new());
243     mainFrame = webkit_web_view_get_main_frame(view);
244
245     if (argc == optind+1 && strcmp(argv[optind], "-") == 0) {
246         char filenameBuffer[2048];
247         printSeparators = true;
248         while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
249             char* newLineCharacter = strchr(filenameBuffer, '\n');
250             if (newLineCharacter)
251                 *newLineCharacter = '\0';
252
253             if (strlen(filenameBuffer) == 0)
254                 continue;
255
256             runTest(filenameBuffer);
257         }
258     } else {
259         printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
260         for (int i = optind; i != argc; ++i)
261             runTest(argv[i]);
262     }
263
264     return 0;
265 }