1 /*
2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3 * Copyright (C) 2008 Alp Toker <alp@nuanti.com>
4 * Copyright (C) 2009 Jan Alonzo <jmalonzo@gmail.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "DumpRenderTree.h"
33
34 #include "AccessibilityController.h"
35 #include "GCController.h"
36 #include "LayoutTestController.h"
37 #include "WorkQueue.h"
38 #include "WorkQueueItem.h"
39
40 #include <gtk/gtk.h>
41 #include <webkit/webkit.h>
42 #include <JavaScriptCore/JavaScript.h>
43
44 #include <wtf/Assertions.h>
45
46 #include <cassert>
47 #include <getopt.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 using namespace std;
52
53 extern "C" {
54 // This API is not yet public.
55 extern G_CONST_RETURN gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem*);
56 extern gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem*);
57 extern GList* webkit_web_history_item_get_children(WebKitWebHistoryItem*);
58 extern GSList* webkit_web_frame_get_children(WebKitWebFrame* frame);
59 extern gchar* webkit_web_frame_get_inner_text(WebKitWebFrame* frame);
60 extern gchar* webkit_web_frame_dump_render_tree(WebKitWebFrame* frame);
61 extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory);
62 extern gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame);
63 extern void webkit_web_frame_clear_main_frame_name(WebKitWebFrame* frame);
64 extern void webkit_web_view_set_group_name(WebKitWebView* view, const gchar* groupName);
65 }
66
67 volatile bool done;
68 static bool printSeparators;
69 static int dumpPixels;
70 static int dumpTree = 1;
71
72 AccessibilityController* axController = 0;
73 LayoutTestController* gLayoutTestController = 0;
74 static GCController* gcController = 0;
75 static WebKitWebView* webView;
76 static GtkWidget* container;
77 WebKitWebFrame* mainFrame = 0;
78 WebKitWebFrame* topLoadingFrame = 0;
79 guint waitToDumpWatchdog = 0;
80 bool waitForPolicy = false;
81
82 // This is a list of opened webviews
83 GSList* webViewList = 0;
84
85 // current b/f item at the end of the previous test
86 static WebKitWebHistoryItem* prevTestBFItem = NULL;
87
88 const unsigned maxViewHeight = 600;
89 const unsigned maxViewWidth = 800;
90 const unsigned historyItemIndent = 8;
91
autocorrectURL(const gchar * url)92 static gchar* autocorrectURL(const gchar* url)
93 {
94 if (strncmp("http://", url, 7) != 0 && strncmp("https://", url, 8) != 0) {
95 GString* string = g_string_new("file://");
96 g_string_append(string, url);
97 return g_string_free(string, FALSE);
98 }
99
100 return g_strdup(url);
101 }
102
shouldLogFrameLoadDelegates(const char * pathOrURL)103 static bool shouldLogFrameLoadDelegates(const char* pathOrURL)
104 {
105 return strstr(pathOrURL, "loading/");
106 }
107
dumpFrameScrollPosition(WebKitWebFrame * frame)108 void dumpFrameScrollPosition(WebKitWebFrame* frame)
109 {
110
111 }
112
displayWebView()113 void displayWebView()
114 {
115
116 }
117
appendString(gchar * & target,gchar * string)118 static void appendString(gchar*& target, gchar* string)
119 {
120 gchar* oldString = target;
121 target = g_strconcat(target, string, NULL);
122 g_free(oldString);
123 }
124
dumpFramesAsText(WebKitWebFrame * frame)125 static gchar* dumpFramesAsText(WebKitWebFrame* frame)
126 {
127 gchar* result = 0;
128
129 // Add header for all but the main frame.
130 bool isMainFrame = (webkit_web_view_get_main_frame(webView) == frame);
131
132 gchar* innerText = webkit_web_frame_get_inner_text(frame);
133 if (isMainFrame)
134 result = g_strdup_printf("%s\n", innerText);
135 else {
136 const gchar* frameName = webkit_web_frame_get_name(frame);
137 result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s\n", frameName, innerText);
138 }
139 g_free(innerText);
140
141 if (gLayoutTestController->dumpChildFramesAsText()) {
142 GSList* children = webkit_web_frame_get_children(frame);
143 for (GSList* child = children; child; child = g_slist_next(child))
144 appendString(result, dumpFramesAsText(static_cast<WebKitWebFrame* >(child->data)));
145 g_slist_free(children);
146 }
147
148 return result;
149 }
150
compareHistoryItems(gpointer * item1,gpointer * item2)151 static gint compareHistoryItems(gpointer* item1, gpointer* item2)
152 {
153 return g_ascii_strcasecmp(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item1)),
154 webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item2)));
155 }
156
dumpHistoryItem(WebKitWebHistoryItem * item,int indent,bool current)157 static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current)
158 {
159 ASSERT(item != NULL);
160 int start = 0;
161 g_object_ref(item);
162 if (current) {
163 printf("curr->");
164 start = 6;
165 }
166 for (int i = start; i < indent; i++)
167 putchar(' ');
168
169 // normalize file URLs.
170 const gchar* uri = webkit_web_history_item_get_uri(item);
171 gchar* uriScheme = g_uri_parse_scheme(uri);
172 if (g_strcmp0(uriScheme, "file") == 0) {
173 gchar* pos = g_strstr_len(uri, -1, "/LayoutTests/");
174 if (!pos)
175 return;
176
177 GString* result = g_string_sized_new(strlen(uri));
178 result = g_string_append(result, "(file test):");
179 result = g_string_append(result, pos + strlen("/LayoutTests/"));
180 printf("%s", result->str);
181 g_string_free(result, TRUE);
182 } else
183 printf("%s", uri);
184
185 g_free(uriScheme);
186
187 const gchar* target = webkit_web_history_item_get_target(item);
188 if (target && strlen(target) > 0)
189 printf(" (in frame \"%s\")", target);
190 if (webkit_web_history_item_is_target_item(item))
191 printf(" **nav target**");
192 putchar('\n');
193 GList* kids = webkit_web_history_item_get_children(item);
194 if (kids) {
195 // must sort to eliminate arbitrary result ordering which defeats reproducible testing
196 kids = g_list_sort(kids, (GCompareFunc) compareHistoryItems);
197 for (unsigned i = 0; i < g_list_length(kids); i++)
198 dumpHistoryItem(WEBKIT_WEB_HISTORY_ITEM(g_list_nth_data(kids, i)), indent+4, FALSE);
199 }
200 g_object_unref(item);
201 }
202
dumpBackForwardListForWebView(WebKitWebView * view)203 static void dumpBackForwardListForWebView(WebKitWebView* view)
204 {
205 printf("\n============== Back Forward List ==============\n");
206 WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(view);
207
208 // Print out all items in the list after prevTestBFItem, which was from the previous test
209 // Gather items from the end of the list, the print them out from oldest to newest
210 GList* itemsToPrint = NULL;
211 gint forwardListCount = webkit_web_back_forward_list_get_forward_length(bfList);
212 for (int i = forwardListCount; i > 0; i--) {
213 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
214 // something is wrong if the item from the last test is in the forward part of the b/f list
215 ASSERT(item != prevTestBFItem);
216 g_object_ref(item);
217 itemsToPrint = g_list_append(itemsToPrint, item);
218 }
219
220 WebKitWebHistoryItem* currentItem = webkit_web_back_forward_list_get_current_item(bfList);
221
222 g_object_ref(currentItem);
223 itemsToPrint = g_list_append(itemsToPrint, currentItem);
224
225 gint currentItemIndex = g_list_length(itemsToPrint) - 1;
226 gint backListCount = webkit_web_back_forward_list_get_back_length(bfList);
227 for (int i = -1; i >= -(backListCount); i--) {
228 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
229 if (item == prevTestBFItem)
230 break;
231 g_object_ref(item);
232 itemsToPrint = g_list_append(itemsToPrint, item);
233 }
234
235 for (int i = g_list_length(itemsToPrint) - 1; i >= 0; i--) {
236 WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(g_list_nth_data(itemsToPrint, i));
237 dumpHistoryItem(item, historyItemIndent, i == currentItemIndex);
238 g_object_unref(item);
239 }
240 g_list_free(itemsToPrint);
241 printf("===============================================\n");
242 }
243
dumpBackForwardListForAllWebViews()244 static void dumpBackForwardListForAllWebViews()
245 {
246 // Dump the back forward list of the main WebView first
247 dumpBackForwardListForWebView(webView);
248
249 // The view list is prepended. Reverse the list so we get the order right.
250 GSList* viewList = g_slist_reverse(webViewList);
251 for (unsigned i = 0; i < g_slist_length(viewList); ++i)
252 dumpBackForwardListForWebView(WEBKIT_WEB_VIEW(g_slist_nth_data(viewList, i)));
253 }
254
invalidateAnyPreviousWaitToDumpWatchdog()255 static void invalidateAnyPreviousWaitToDumpWatchdog()
256 {
257 if (waitToDumpWatchdog) {
258 g_source_remove(waitToDumpWatchdog);
259 waitToDumpWatchdog = 0;
260 }
261
262 waitForPolicy = false;
263 }
264
resetWebViewToConsistentStateBeforeTesting()265 static void resetWebViewToConsistentStateBeforeTesting()
266 {
267 WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
268 g_object_set(G_OBJECT(settings),
269 "enable-private-browsing", FALSE,
270 "enable-developer-extras", FALSE,
271 "enable-spell-checking", TRUE,
272 "enable-html5-database", TRUE,
273 "enable-html5-local-storage", TRUE,
274 "enable-xss-auditor", FALSE,
275 "javascript-can-open-windows-automatically", TRUE,
276 "enable-offline-web-application-cache", TRUE,
277 NULL);
278
279 webkit_web_frame_clear_main_frame_name(mainFrame);
280
281 WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
282 g_object_set(G_OBJECT(inspector), "javascript-profiling-enabled", FALSE, NULL);
283 }
284
dump()285 void dump()
286 {
287 invalidateAnyPreviousWaitToDumpWatchdog();
288
289 bool dumpAsText = gLayoutTestController->dumpAsText();
290 if (dumpTree) {
291 char* result = 0;
292 gchar* responseMimeType = webkit_web_frame_get_response_mime_type(mainFrame);
293
294 dumpAsText = g_str_equal(responseMimeType, "text/plain");
295 g_free(responseMimeType);
296
297 // Test can request controller to be dumped as text even
298 // while test's response mime type is not text/plain.
299 // Overriding this behavior with dumpAsText being false is a bad idea.
300 if (dumpAsText)
301 gLayoutTestController->setDumpAsText(dumpAsText);
302
303 if (gLayoutTestController->dumpAsText())
304 result = dumpFramesAsText(mainFrame);
305 else
306 result = webkit_web_frame_dump_render_tree(mainFrame);
307
308 if (!result) {
309 const char* errorMessage;
310 if (gLayoutTestController->dumpAsText())
311 errorMessage = "[documentElement innerText]";
312 else if (gLayoutTestController->dumpDOMAsWebArchive())
313 errorMessage = "[[mainFrame DOMDocument] webArchive]";
314 else if (gLayoutTestController->dumpSourceAsWebArchive())
315 errorMessage = "[[mainFrame dataSource] webArchive]";
316 else
317 errorMessage = "[mainFrame renderTreeAsExternalRepresentation]";
318 printf("ERROR: nil result from %s", errorMessage);
319 } else {
320 printf("%s", result);
321 g_free(result);
322 if (!gLayoutTestController->dumpAsText() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive())
323 dumpFrameScrollPosition(mainFrame);
324
325 if (gLayoutTestController->dumpBackForwardList())
326 dumpBackForwardListForAllWebViews();
327 }
328
329 if (printSeparators) {
330 puts("#EOF"); // terminate the content block
331 fputs("#EOF\n", stderr);
332 fflush(stdout);
333 fflush(stderr);
334 }
335 }
336
337 if (dumpPixels) {
338 if (!gLayoutTestController->dumpAsText() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive()) {
339 // FIXME: Add support for dumping pixels
340 }
341 }
342
343 // FIXME: call displayWebView here when we support --paint
344
345 puts("#EOF"); // terminate the (possibly empty) pixels block
346
347 fflush(stdout);
348 fflush(stderr);
349
350 done = true;
351 }
352
setDefaultsToConsistentStateValuesForTesting()353 static void setDefaultsToConsistentStateValuesForTesting()
354 {
355 gdk_screen_set_resolution(gdk_screen_get_default(), 72.0);
356
357 WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
358 g_object_set(G_OBJECT(settings),
359 "default-font-family", "Times",
360 "monospace-font-family", "Courier",
361 "serif-font-family", "Times",
362 "sans-serif-font-family", "Helvetica",
363 "default-font-size", 16,
364 "default-monospace-font-size", 13,
365 "minimum-font-size", 1,
366 NULL);
367
368 /* Disable the default auth dialog for testing */
369 SoupSession* session = webkit_get_default_session();
370 soup_session_remove_feature_by_type(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG);
371
372 #if PLATFORM(X11)
373 webkit_web_settings_add_extra_plugin_directory(webView, TEST_PLUGIN_DIR);
374 #endif
375 }
376
runTest(const string & testPathOrURL)377 static void runTest(const string& testPathOrURL)
378 {
379 ASSERT(!testPathOrURL.empty());
380
381 // Look for "'" as a separator between the path or URL, and the pixel dump hash that follows.
382 string pathOrURL(testPathOrURL);
383 string expectedPixelHash;
384
385 size_t separatorPos = pathOrURL.find("'");
386 if (separatorPos != string::npos) {
387 pathOrURL = string(testPathOrURL, 0, separatorPos);
388 expectedPixelHash = string(testPathOrURL, separatorPos + 1);
389 }
390
391 gchar* url = autocorrectURL(pathOrURL.c_str());
392 const string testURL(url);
393
394 resetWebViewToConsistentStateBeforeTesting();
395
396 gLayoutTestController = new LayoutTestController(testURL, expectedPixelHash);
397 topLoadingFrame = 0;
398 done = false;
399
400 gLayoutTestController->setIconDatabaseEnabled(false);
401
402 if (shouldLogFrameLoadDelegates(pathOrURL.c_str()))
403 gLayoutTestController->setDumpFrameLoadCallbacks(true);
404
405 WorkQueue::shared()->clear();
406 WorkQueue::shared()->setFrozen(false);
407
408 bool isSVGW3CTest = (gLayoutTestController->testPathOrURL().find("svg/W3C-SVG-1.1") != string::npos);
409 GtkAllocation size;
410 size.width = isSVGW3CTest ? 480 : maxViewWidth;
411 size.height = isSVGW3CTest ? 360 : maxViewHeight;
412 gtk_widget_size_allocate(container, &size);
413
414 if (prevTestBFItem)
415 g_object_unref(prevTestBFItem);
416 WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(webView);
417 prevTestBFItem = webkit_web_back_forward_list_get_current_item(bfList);
418 if (prevTestBFItem)
419 g_object_ref(prevTestBFItem);
420
421
422 webkit_web_view_open(webView, url);
423
424 g_free(url);
425 url = NULL;
426
427 while (!done)
428 g_main_context_iteration(NULL, TRUE);
429
430
431 // Also check if we still have opened webViews and free them.
432 if (gLayoutTestController->closeRemainingWindowsWhenComplete() || webViewList) {
433 while (webViewList) {
434 g_object_unref(WEBKIT_WEB_VIEW(webViewList->data));
435 webViewList = g_slist_next(webViewList);
436 }
437 g_slist_free(webViewList);
438 webViewList = 0;
439 }
440
441 // A blank load seems to be necessary to reset state after certain tests.
442 webkit_web_view_open(webView, "about:blank");
443
444 gLayoutTestController->deref();
445 gLayoutTestController = 0;
446 }
447
webViewLoadStarted(WebKitWebView * view,WebKitWebFrame * frame,void *)448 void webViewLoadStarted(WebKitWebView* view, WebKitWebFrame* frame, void*)
449 {
450 // Make sure we only set this once per test. If it gets cleared, and then set again, we might
451 // end up doing two dumps for one test.
452 if (!topLoadingFrame && !done)
453 topLoadingFrame = frame;
454 }
455
processWork(void * data)456 static gboolean processWork(void* data)
457 {
458 // if we finish all the commands, we're ready to dump state
459 if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
460 dump();
461
462 return FALSE;
463 }
464
webViewLoadFinished(WebKitWebView * view,WebKitWebFrame * frame,void *)465 static void webViewLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*)
466 {
467 if (frame != topLoadingFrame)
468 return;
469
470 topLoadingFrame = 0;
471 WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
472 if (gLayoutTestController->waitToDump())
473 return;
474
475 if (WorkQueue::shared()->count())
476 g_timeout_add(0, processWork, 0);
477 else
478 dump();
479 }
480
webViewWindowObjectCleared(WebKitWebView * view,WebKitWebFrame * frame,JSGlobalContextRef context,JSObjectRef windowObject,gpointer data)481 static void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* frame, JSGlobalContextRef context, JSObjectRef windowObject, gpointer data)
482 {
483 JSValueRef exception = 0;
484 ASSERT(gLayoutTestController);
485
486 gLayoutTestController->makeWindowObject(context, windowObject, &exception);
487 ASSERT(!exception);
488
489 gcController->makeWindowObject(context, windowObject, &exception);
490 ASSERT(!exception);
491
492 axController->makeWindowObject(context, windowObject, &exception);
493 ASSERT(!exception);
494
495 }
496
webViewConsoleMessage(WebKitWebView * view,const gchar * message,unsigned int line,const gchar * sourceId,gpointer data)497 static gboolean webViewConsoleMessage(WebKitWebView* view, const gchar* message, unsigned int line, const gchar* sourceId, gpointer data)
498 {
499 fprintf(stdout, "CONSOLE MESSAGE: line %d: %s\n", line, message);
500 return TRUE;
501 }
502
503
webViewScriptAlert(WebKitWebView * view,WebKitWebFrame * frame,const gchar * message,gpointer data)504 static gboolean webViewScriptAlert(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gpointer data)
505 {
506 fprintf(stdout, "ALERT: %s\n", message);
507 return TRUE;
508 }
509
webViewScriptPrompt(WebKitWebView * webView,WebKitWebFrame * frame,const gchar * message,const gchar * defaultValue,gchar ** value,gpointer data)510 static gboolean webViewScriptPrompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value, gpointer data)
511 {
512 fprintf(stdout, "PROMPT: %s, default text: %s\n", message, defaultValue);
513 *value = g_strdup(defaultValue);
514 return TRUE;
515 }
516
webViewScriptConfirm(WebKitWebView * view,WebKitWebFrame * frame,const gchar * message,gboolean * didConfirm,gpointer data)517 static gboolean webViewScriptConfirm(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm, gpointer data)
518 {
519 fprintf(stdout, "CONFIRM: %s\n", message);
520 *didConfirm = TRUE;
521 return TRUE;
522 }
523
webViewTitleChanged(WebKitWebView * view,WebKitWebFrame * frame,const gchar * title,gpointer data)524 static void webViewTitleChanged(WebKitWebView* view, WebKitWebFrame* frame, const gchar* title, gpointer data)
525 {
526 if (gLayoutTestController->dumpTitleChanges() && !done)
527 printf("TITLE CHANGED: %s\n", title ? title : "");
528 }
529
webViewNavigationPolicyDecisionRequested(WebKitWebView * view,WebKitWebFrame * frame,WebKitNetworkRequest * request,WebKitWebNavigationAction * navAction,WebKitWebPolicyDecision * policyDecision)530 static bool webViewNavigationPolicyDecisionRequested(WebKitWebView* view, WebKitWebFrame* frame,
531 WebKitNetworkRequest* request,
532 WebKitWebNavigationAction* navAction,
533 WebKitWebPolicyDecision* policyDecision)
534 {
535 // Use the default handler if we're not waiting for policy,
536 // i.e., LayoutTestController::waitForPolicyDelegate
537 if (!waitForPolicy)
538 return FALSE;
539
540 gchar* typeDescription;
541 WebKitWebNavigationReason reason;
542 g_object_get(G_OBJECT(navAction), "reason", &reason, NULL);
543
544 switch(reason) {
545 case WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED:
546 typeDescription = g_strdup("link clicked");
547 break;
548 case WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED:
549 typeDescription = g_strdup("form submitted");
550 break;
551 case WEBKIT_WEB_NAVIGATION_REASON_BACK_FORWARD:
552 typeDescription = g_strdup("back/forward");
553 break;
554 case WEBKIT_WEB_NAVIGATION_REASON_RELOAD:
555 typeDescription = g_strdup("reload");
556 break;
557 case WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED:
558 typeDescription = g_strdup("form resubmitted");
559 break;
560 case WEBKIT_WEB_NAVIGATION_REASON_OTHER:
561 typeDescription = g_strdup("other");
562 break;
563 default:
564 typeDescription = g_strdup("illegal value");
565 }
566
567 printf("Policy delegate: attempt to load %s with navigation type '%s'\n", webkit_network_request_get_uri(request), typeDescription);
568 g_free(typeDescription);
569
570 webkit_web_policy_decision_ignore(policyDecision);
571 gLayoutTestController->notifyDone();
572
573 return TRUE;
574 }
575
webViewStatusBarTextChanged(WebKitWebView * view,const gchar * message,gpointer data)576 static void webViewStatusBarTextChanged(WebKitWebView* view, const gchar* message, gpointer data)
577 {
578 // Are we doing anything wrong? One test that does not call
579 // dumpStatusCallbacks gets true here
580 if (gLayoutTestController->dumpStatusCallbacks()) {
581 if (message && strcmp(message, ""))
582 printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", message);
583 }
584 }
585
webViewClose(WebKitWebView * view)586 static gboolean webViewClose(WebKitWebView* view)
587 {
588 ASSERT(view);
589
590 webViewList = g_slist_remove(webViewList, view);
591 g_object_unref(view);
592
593 return TRUE;
594 }
595
596
597 static WebKitWebView* webViewCreate(WebKitWebView*, WebKitWebFrame*);
598
createWebView()599 static WebKitWebView* createWebView()
600 {
601 WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
602
603 // From bug 11756: Use a frame group name for all WebViews created by
604 // DumpRenderTree to allow testing of cross-page frame lookup.
605 webkit_web_view_set_group_name(view, "org.webkit.gtk.DumpRenderTree");
606
607 g_object_connect(G_OBJECT(view),
608 "signal::load-started", webViewLoadStarted, 0,
609 "signal::load-finished", webViewLoadFinished, 0,
610 "signal::window-object-cleared", webViewWindowObjectCleared, 0,
611 "signal::console-message", webViewConsoleMessage, 0,
612 "signal::script-alert", webViewScriptAlert, 0,
613 "signal::script-prompt", webViewScriptPrompt, 0,
614 "signal::script-confirm", webViewScriptConfirm, 0,
615 "signal::title-changed", webViewTitleChanged, 0,
616 "signal::navigation-policy-decision-requested", webViewNavigationPolicyDecisionRequested, 0,
617 "signal::status-bar-text-changed", webViewStatusBarTextChanged, 0,
618 "signal::create-web-view", webViewCreate, 0,
619 "signal::close-web-view", webViewClose, 0,
620 NULL);
621
622 return view;
623 }
624
webViewCreate(WebKitWebView * view,WebKitWebFrame * frame)625 static WebKitWebView* webViewCreate(WebKitWebView* view, WebKitWebFrame* frame)
626 {
627 if (!gLayoutTestController->canOpenWindows())
628 return 0;
629
630 // Make sure that waitUntilDone has been called.
631 ASSERT(gLayoutTestController->waitToDump());
632
633 WebKitWebView* newWebView = createWebView();
634 g_object_ref_sink(G_OBJECT(newWebView));
635 webViewList = g_slist_prepend(webViewList, newWebView);
636 return newWebView;
637 }
638
main(int argc,char * argv[])639 int main(int argc, char* argv[])
640 {
641 g_thread_init(NULL);
642 gtk_init(&argc, &argv);
643
644 struct option options[] = {
645 {"notree", no_argument, &dumpTree, false},
646 {"pixel-tests", no_argument, &dumpPixels, true},
647 {"tree", no_argument, &dumpTree, true},
648 {NULL, 0, NULL, 0}
649 };
650
651 int option;
652 while ((option = getopt_long(argc, (char* const*)argv, "", options, NULL)) != -1)
653 switch (option) {
654 case '?': // unknown or ambiguous option
655 case ':': // missing argument
656 exit(1);
657 break;
658 }
659
660 GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
661 container = GTK_WIDGET(gtk_scrolled_window_new(NULL, NULL));
662 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(container), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
663 gtk_container_add(GTK_CONTAINER(window), container);
664 gtk_widget_realize(window);
665
666 webView = createWebView();
667 gtk_container_add(GTK_CONTAINER(container), GTK_WIDGET(webView));
668 gtk_widget_realize(GTK_WIDGET(webView));
669 gtk_widget_show_all(container);
670 mainFrame = webkit_web_view_get_main_frame(webView);
671
672 setDefaultsToConsistentStateValuesForTesting();
673
674 gcController = new GCController();
675 axController = new AccessibilityController();
676
677 if (argc == optind+1 && strcmp(argv[optind], "-") == 0) {
678 char filenameBuffer[2048];
679 printSeparators = true;
680 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
681 char* newLineCharacter = strchr(filenameBuffer, '\n');
682 if (newLineCharacter)
683 *newLineCharacter = '\0';
684
685 if (strlen(filenameBuffer) == 0)
686 continue;
687
688 runTest(filenameBuffer);
689 }
690 } else {
691 printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
692 for (int i = optind; i != argc; ++i)
693 runTest(argv[i]);
694 }
695
696 delete gcController;
697 gcController = 0;
698
699 delete axController;
700 axController = 0;
701
702 g_object_unref(webView);
703
704 return 0;
705 }
706