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