• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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