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 * Copyright (C) 2010, 2011 Igalia S.L.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "DumpRenderTree.h"
35 #include "AccessibilityController.h"
36 #include "EditingCallbacks.h"
37 #include "EventSender.h"
38 #include "GCController.h"
39 #include "LayoutTestController.h"
40 #include "PixelDumpSupport.h"
41 #include "SelfScrollingWebKitWebView.h"
42 #include "TextInputController.h"
43 #include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
44 #include "WebCoreTestSupport.h"
45 #include "WorkQueue.h"
46 #include "WorkQueueItem.h"
47 #include <JavaScriptCore/JavaScript.h>
53 #include <webkit/webkit.h>
54 #include <wtf/Assertions.h>
55 #include <wtf/gobject/GOwnPtr.h>
56 #include <wtf/gobject/GlibUtilities.h>
59 #include <fontconfig/fontconfig.h>
66 // This API is not yet public.
67 extern gchar* webkit_web_history_item_get_target(WebKitWebHistoryItem*);
68 extern gboolean webkit_web_history_item_is_target_item(WebKitWebHistoryItem*);
69 extern GList* webkit_web_history_item_get_children(WebKitWebHistoryItem*);
70 extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory);
71 extern gchar* webkit_web_frame_get_response_mime_type(WebKitWebFrame* frame);
75 static bool printSeparators;
76 static int dumpPixels;
77 static int dumpTree = 1;
78 static int useTimeoutWatchdog = 1;
80 AccessibilityController* axController = 0;
81 RefPtr<LayoutTestController> gLayoutTestController;
82 static GCController* gcController = 0;
83 static WebKitWebView* webView;
84 static GtkWidget* window;
85 static GtkWidget* container;
86 static GtkWidget* webInspectorWindow;
87 WebKitWebFrame* mainFrame = 0;
88 WebKitWebFrame* topLoadingFrame = 0;
89 guint waitToDumpWatchdog = 0;
90 bool waitForPolicy = false;
92 // This is a list of opened webviews
93 GSList* webViewList = 0;
95 // current b/f item at the end of the previous test
96 static WebKitWebHistoryItem* prevTestBFItem = NULL;
98 const unsigned historyItemIndent = 8;
100 static void runTest(const string& testPathOrURL);
102 static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url);
104 static bool shouldLogFrameLoadDelegates(const string& pathOrURL)
106 return pathOrURL.find("loading/") != string::npos;
109 static bool shouldOpenWebInspector(const string& pathOrURL)
111 return pathOrURL.find("inspector/") != string::npos;
114 static bool shouldDumpAsText(const string& pathOrURL)
116 return pathOrURL.find("dumpAsText/") != string::npos;
119 static bool shouldEnableDeveloperExtras(const string& pathOrURL)
124 void dumpFrameScrollPosition(WebKitWebFrame* frame)
129 void displayWebView()
131 gtk_widget_queue_draw(GTK_WIDGET(webView));
134 static void appendString(gchar*& target, gchar* string)
136 gchar* oldString = target;
137 target = g_strconcat(target, string, NULL);
141 static void initializeGtkFontSettings(const char* testURL)
143 GtkSettings* settings = gtk_settings_get_default();
146 g_object_set(settings,
147 "gtk-xft-dpi", 98304, // This is 96 * 1024 or 96 DPI according to the GTK+ docs.
148 "gtk-xft-antialias", 1,
149 "gtk-xft-hinting", 0,
150 "gtk-font-name", "Liberation Sans 12",
152 gdk_screen_set_resolution(gdk_screen_get_default(), 96.0);
154 // One test needs subpixel anti-aliasing turned on, but generally we
155 // want all text in other tests to use to grayscale anti-aliasing.
156 if (testURL && strstr(testURL, "xsettings_antialias_settings.html"))
157 g_object_set(settings, "gtk-xft-rgba", "rgb", NULL);
159 g_object_set(settings, "gtk-xft-rgba", "none", NULL);
162 CString getTopLevelPath()
164 if (!g_getenv("WEBKIT_TOP_LEVEL"))
165 g_setenv("WEBKIT_TOP_LEVEL", TOP_LEVEL_DIR, FALSE);
167 return TOP_LEVEL_DIR;
170 static void initializeFonts(const char* testURL = 0)
173 initializeGtkFontSettings(testURL);
177 // If a test resulted a font being added or removed via the @font-face rule, then
178 // we want to reset the FontConfig configuration to prevent it from affecting other tests.
179 static int numFonts = 0;
180 FcFontSet* appFontSet = FcConfigGetFonts(0, FcSetApplication);
181 if (appFontSet && numFonts && appFontSet->nfont == numFonts)
184 // Load our configuration file, which sets up proper aliases for family
185 // names like sans, serif and monospace.
186 FcConfig* config = FcConfigCreate();
187 GOwnPtr<gchar> fontConfigFilename(g_build_filename(FONTS_CONF_DIR, "fonts.conf", NULL));
188 if (!FcConfigParseAndLoad(config, reinterpret_cast<FcChar8*>(fontConfigFilename.get()), true))
189 g_error("Couldn't load font configuration file from: %s", fontConfigFilename.get());
191 CString topLevelPath = getTopLevelPath();
192 GOwnPtr<char> fontsPath(g_build_filename(topLevelPath.data(), "WebKitBuild", "Dependencies",
193 "Root", "webkitgtk-test-fonts", NULL));
194 if (!g_file_test(fontsPath.get(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
195 g_error("Could not locate test fonts at %s. Is WEBKIT_TOP_LEVEL set?", fontsPath.get());
197 GOwnPtr<GError> error;
198 GOwnPtr<GDir> fontsDirectory(g_dir_open(fontsPath.get(), 0, &error.outPtr()));
199 while (const char* directoryEntry = g_dir_read_name(fontsDirectory.get())) {
200 if (!g_str_has_suffix(directoryEntry, ".ttf") && !g_str_has_suffix(directoryEntry, ".otf"))
202 GOwnPtr<gchar> fontPath(g_build_filename(fontsPath.get(), directoryEntry, NULL));
203 if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(fontPath.get())))
204 g_error("Could not load font at %s!", fontPath.get());
208 // Ahem is used by many layout tests.
209 GOwnPtr<gchar> ahemFontFilename(g_build_filename(FONTS_CONF_DIR, "AHEM____.TTF", NULL));
210 if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(ahemFontFilename.get())))
211 g_error("Could not load font at %s!", ahemFontFilename.get());
213 for (int i = 1; i <= 9; i++) {
214 GOwnPtr<gchar> fontFilename(g_strdup_printf("WebKitWeightWatcher%i00.ttf", i));
215 GOwnPtr<gchar> fontPath(g_build_filename(FONTS_CONF_DIR, "..", "..", "fonts", fontFilename.get(), NULL));
216 if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontPath.get())))
217 g_error("Could not load font at %s!", fontPath.get());
220 // A font with no valid Fontconfig encoding to test https://bugs.webkit.org/show_bug.cgi?id=47452
221 GOwnPtr<gchar> fontWithNoValidEncodingFilename(g_build_filename(FONTS_CONF_DIR, "FontWithNoValidEncoding.fon", NULL));
222 if (!FcConfigAppFontAddFile(config, reinterpret_cast<FcChar8*>(fontWithNoValidEncodingFilename.get())))
223 g_error("Could not load font at %s!", fontWithNoValidEncodingFilename.get());
225 if (!FcConfigSetCurrent(config))
226 g_error("Could not set the current font configuration!");
228 numFonts = FcConfigGetFonts(config, FcSetApplication)->nfont;
232 static gchar* dumpFramesAsText(WebKitWebFrame* frame)
236 // Add header for all but the main frame.
237 bool isMainFrame = (webkit_web_view_get_main_frame(webView) == frame);
239 CString innerText = DumpRenderTreeSupportGtk::getInnerText(frame);
241 result = g_strdup_printf("%s\n", innerText.data());
243 const gchar* frameName = webkit_web_frame_get_name(frame);
244 result = g_strdup_printf("\n--------\nFrame: '%s'\n--------\n%s\n", frameName, innerText.data());
247 if (gLayoutTestController->dumpChildFramesAsText()) {
248 GSList* children = DumpRenderTreeSupportGtk::getFrameChildren(frame);
249 for (GSList* child = children; child; child = g_slist_next(child))
250 appendString(result, dumpFramesAsText(static_cast<WebKitWebFrame* >(child->data)));
251 g_slist_free(children);
257 static gint compareHistoryItems(gpointer* item1, gpointer* item2)
259 GOwnPtr<gchar> firstItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item1)));
260 GOwnPtr<gchar> secondItemTarget(webkit_web_history_item_get_target(WEBKIT_WEB_HISTORY_ITEM(item2)));
261 return g_ascii_strcasecmp(firstItemTarget.get(), secondItemTarget.get());
264 static void dumpHistoryItem(WebKitWebHistoryItem* item, int indent, bool current)
266 ASSERT(item != NULL);
273 for (int i = start; i < indent; i++)
276 // normalize file URLs.
277 const gchar* uri = webkit_web_history_item_get_uri(item);
278 gchar* uriScheme = g_uri_parse_scheme(uri);
279 if (g_strcmp0(uriScheme, "file") == 0) {
280 gchar* pos = g_strstr_len(uri, -1, "/LayoutTests/");
284 GString* result = g_string_sized_new(strlen(uri));
285 result = g_string_append(result, "(file test):");
286 result = g_string_append(result, pos + strlen("/LayoutTests/"));
287 printf("%s", result->str);
288 g_string_free(result, TRUE);
294 const gchar* target = webkit_web_history_item_get_target(item);
295 if (target && strlen(target) > 0)
296 printf(" (in frame \"%s\")", target);
297 if (webkit_web_history_item_is_target_item(item))
298 printf(" **nav target**");
301 if (GList* kids = webkit_web_history_item_get_children(item)) {
302 // must sort to eliminate arbitrary result ordering which defeats reproducible testing
303 for (GList* kid = g_list_sort(kids, (GCompareFunc) compareHistoryItems); kid; kid = g_list_next(kid)) {
304 WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(kid->data);
305 dumpHistoryItem(item, indent + 4, FALSE);
306 g_object_unref(item);
310 g_object_unref(item);
313 static void dumpBackForwardListForWebView(WebKitWebView* view)
315 printf("\n============== Back Forward List ==============\n");
316 WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(view);
318 // Print out all items in the list after prevTestBFItem, which was from the previous test
319 // Gather items from the end of the list, the print them out from oldest to newest
320 GList* itemsToPrint = NULL;
321 gint forwardListCount = webkit_web_back_forward_list_get_forward_length(bfList);
322 for (int i = forwardListCount; i > 0; i--) {
323 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
324 // something is wrong if the item from the last test is in the forward part of the b/f list
325 ASSERT(item != prevTestBFItem);
327 itemsToPrint = g_list_prepend(itemsToPrint, item);
330 WebKitWebHistoryItem* currentItem = webkit_web_back_forward_list_get_current_item(bfList);
331 g_object_ref(currentItem);
332 itemsToPrint = g_list_prepend(itemsToPrint, currentItem);
334 gint backListCount = webkit_web_back_forward_list_get_back_length(bfList);
335 for (int i = -1; i >= -(backListCount); i--) {
336 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_nth_item(bfList, i);
337 if (item == prevTestBFItem)
340 itemsToPrint = g_list_prepend(itemsToPrint, item);
343 for (GList* itemToPrint = itemsToPrint; itemToPrint; itemToPrint = g_list_next(itemToPrint)) {
344 WebKitWebHistoryItem* item = WEBKIT_WEB_HISTORY_ITEM(itemToPrint->data);
345 dumpHistoryItem(item, historyItemIndent, item == currentItem);
346 g_object_unref(item);
349 g_list_free(itemsToPrint);
350 printf("===============================================\n");
353 static void dumpBackForwardListForAllWebViews()
355 // Dump the back forward list of the main WebView first
356 dumpBackForwardListForWebView(webView);
358 // The view list is prepended. Reverse the list so we get the order right.
359 for (GSList* currentView = g_slist_reverse(webViewList); currentView; currentView = g_slist_next(currentView))
360 dumpBackForwardListForWebView(WEBKIT_WEB_VIEW(currentView->data));
363 void setWaitToDumpWatchdog(guint timer)
365 waitToDumpWatchdog = timer;
368 bool shouldSetWaitToDumpWatchdog()
370 return !waitToDumpWatchdog && useTimeoutWatchdog;
373 static void invalidateAnyPreviousWaitToDumpWatchdog()
375 if (waitToDumpWatchdog) {
376 g_source_remove(waitToDumpWatchdog);
377 waitToDumpWatchdog = 0;
380 waitForPolicy = false;
383 static void resetDefaultsToConsistentValues()
385 WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
386 GOwnPtr<gchar> localStoragePath(g_build_filename(g_get_user_data_dir(), "DumpRenderTreeGtk", "databases", NULL));
387 g_object_set(G_OBJECT(settings),
388 "enable-private-browsing", FALSE,
389 "enable-developer-extras", FALSE,
390 "enable-spell-checking", TRUE,
391 "enable-html5-database", TRUE,
392 "enable-html5-local-storage", TRUE,
393 "html5-local-storage-database-path", localStoragePath.get(),
394 "enable-xss-auditor", FALSE,
395 "enable-spatial-navigation", FALSE,
396 "enable-frame-flattening", FALSE,
397 "javascript-can-access-clipboard", TRUE,
398 "javascript-can-open-windows-automatically", TRUE,
399 "enable-offline-web-application-cache", TRUE,
400 "enable-universal-access-from-file-uris", TRUE,
401 "enable-scripts", TRUE,
402 "enable-dom-paste", TRUE,
403 "default-font-family", "Times",
404 "monospace-font-family", "Courier",
405 "serif-font-family", "Times",
406 "sans-serif-font-family", "Helvetica",
407 "cursive-font-family", "cursive",
408 "fantasy-font-family", "fantasy",
409 "default-font-size", 12,
410 "default-monospace-font-size", 10,
411 "minimum-font-size", 0,
412 "enable-caret-browsing", FALSE,
413 "enable-page-cache", FALSE,
414 "auto-resize-window", TRUE,
415 "enable-java-applet", FALSE,
416 "enable-plugins", TRUE,
417 "enable-hyperlink-auditing", FALSE,
418 "editing-behavior", WEBKIT_EDITING_BEHAVIOR_UNIX,
419 "enable-fullscreen", TRUE,
421 webkit_web_view_set_settings(webView, settings);
422 webkit_set_cache_model(WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER);
424 DumpRenderTreeSupportGtk::clearMainFrameName(mainFrame);
425 DumpRenderTreeSupportGtk::scalePageBy(webView, 1, 0, 0);
427 WebKitWebInspector* inspector = webkit_web_view_get_inspector(webView);
428 g_object_set(G_OBJECT(inspector), "javascript-profiling-enabled", FALSE, NULL);
430 webkit_web_view_set_zoom_level(webView, 1.0);
431 DumpRenderTreeSupportGtk::setMinimumTimerInterval(webView, DumpRenderTreeSupportGtk::defaultMinimumTimerInterval());
433 DumpRenderTreeSupportGtk::resetOriginAccessWhiteLists();
435 WebKitWebBackForwardList* list = webkit_web_view_get_back_forward_list(webView);
436 webkit_web_back_forward_list_clear(list);
438 SoupSession* session = webkit_get_default_session();
439 SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
441 // We only create the jar when the soup backend needs to do
442 // HTTP. Should we initialize it earlier, perhaps?
444 g_object_set(G_OBJECT(jar), SOUP_COOKIE_JAR_ACCEPT_POLICY, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY, NULL);
446 setlocale(LC_ALL, "");
448 DumpRenderTreeSupportGtk::setLinksIncludedInFocusChain(true);
449 webkit_icon_database_set_path(webkit_get_icon_database(), 0);
450 DumpRenderTreeSupportGtk::setSelectTrailingWhitespaceEnabled(false);
451 DumpRenderTreeSupportGtk::setSmartInsertDeleteEnabled(webView, true);
452 DumpRenderTreeSupportGtk::setDefersLoading(webView, false);
453 DumpRenderTreeSupportGtk::setSerializeHTTPLoads(false);
456 axController->resetToConsistentState();
458 DumpRenderTreeSupportGtk::clearOpener(mainFrame);
460 DumpRenderTreeSupportGtk::resetGeolocationClientMock(webView);
462 DumpRenderTreeSupportGtk::setHixie76WebSocketProtocolEnabled(webView, true);
465 static bool useLongRunningServerMode(int argc, char *argv[])
467 // This assumes you've already called getopt_long
468 return (argc == optind+1 && !strcmp(argv[optind], "-"));
471 static void runTestingServerLoop()
473 // When DumpRenderTree runs in server mode, we just wait around for file names
474 // to be passed to us and read each in turn, passing the results back to the client
475 char filenameBuffer[2048];
476 while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
477 char* newLineCharacter = strchr(filenameBuffer, '\n');
478 if (newLineCharacter)
479 *newLineCharacter = '\0';
481 if (!strlen(filenameBuffer))
484 runTest(filenameBuffer);
488 static void initializeGlobalsFromCommandLineOptions(int argc, char *argv[])
490 struct option options[] = {
491 {"notree", no_argument, &dumpTree, false},
492 {"pixel-tests", no_argument, &dumpPixels, true},
493 {"tree", no_argument, &dumpTree, true},
494 {"no-timeout", no_argument, &useTimeoutWatchdog, false},
499 while ((option = getopt_long(argc, (char * const *)argv, "", options, NULL)) != -1) {
501 case '?': // unknown or ambiguous option
502 case ':': // missing argument
512 invalidateAnyPreviousWaitToDumpWatchdog();
514 // Grab widget focus before dumping the contents of a widget, in
515 // case it was lost in the course of the test.
516 gtk_widget_grab_focus(GTK_WIDGET(webView));
520 gchar* responseMimeType = webkit_web_frame_get_response_mime_type(mainFrame);
522 if (g_str_equal(responseMimeType, "text/plain")) {
523 gLayoutTestController->setDumpAsText(true);
524 gLayoutTestController->setGeneratePixelResults(false);
526 g_free(responseMimeType);
528 if (gLayoutTestController->dumpAsText())
529 result = dumpFramesAsText(mainFrame);
531 // Widget resizing is done asynchronously in GTK+. We pump the main
532 // loop here, to flush any pending resize requests. This prevents
533 // timing issues which affect the size of elements in the output.
534 // We only enable this workaround for tests that print the render tree
535 // because this seems to break some dumpAsText tests: see bug 39988
536 // After fixing that test, we should apply this approach to all dumps.
537 while (gtk_events_pending())
538 gtk_main_iteration();
540 result = g_strdup(DumpRenderTreeSupportGtk::dumpRenderTree(mainFrame).data());
544 const char* errorMessage;
545 if (gLayoutTestController->dumpAsText())
546 errorMessage = "[documentElement innerText]";
547 else if (gLayoutTestController->dumpDOMAsWebArchive())
548 errorMessage = "[[mainFrame DOMDocument] webArchive]";
549 else if (gLayoutTestController->dumpSourceAsWebArchive())
550 errorMessage = "[[mainFrame dataSource] webArchive]";
552 errorMessage = "[mainFrame renderTreeAsExternalRepresentation]";
553 printf("ERROR: nil result from %s", errorMessage);
555 printf("%s", result);
557 if (!gLayoutTestController->dumpAsText() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive())
558 dumpFrameScrollPosition(mainFrame);
560 if (gLayoutTestController->dumpBackForwardList())
561 dumpBackForwardListForAllWebViews();
564 if (printSeparators) {
565 puts("#EOF"); // terminate the content block
566 fputs("#EOF\n", stderr);
573 && gLayoutTestController->generatePixelResults()
574 && !gLayoutTestController->dumpDOMAsWebArchive()
575 && !gLayoutTestController->dumpSourceAsWebArchive()) {
576 DumpRenderTreeSupportGtk::forceWebViewPaint(webView);
577 dumpWebViewAsPixelsAndCompareWithExpected(gLayoutTestController->expectedPixelHash());
580 // FIXME: call displayWebView here when we support --paint
586 static void setDefaultsToConsistentStateValuesForTesting()
588 resetDefaultsToConsistentValues();
590 /* Disable the default auth dialog for testing */
591 SoupSession* session = webkit_get_default_session();
592 soup_session_remove_feature_by_type(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG);
595 webkit_web_settings_add_extra_plugin_directory(webView, TEST_PLUGIN_DIR);
598 gchar* databaseDirectory = g_build_filename(g_get_user_data_dir(), "gtkwebkitdrt", "databases", NULL);
599 webkit_set_web_database_directory_path(databaseDirectory);
600 g_free(databaseDirectory);
602 #if defined(GTK_API_VERSION_2)
603 gtk_rc_parse_string("style \"nix_scrollbar_spacing\" "
605 " GtkScrolledWindow::scrollbar-spacing = 0 "
607 "class \"GtkWidget\" style \"nix_scrollbar_spacing\"");
610 GtkCssProvider* cssProvider = gtk_css_provider_new();
611 gtk_css_provider_load_from_data(cssProvider,
613 " -GtkScrolledWindow-scrollbar-spacing: 0;"
616 gtk_style_context_add_provider_for_screen(gdk_display_get_default_screen(gdk_display_get_default()),
617 GTK_STYLE_PROVIDER(cssProvider),
618 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
619 g_object_unref(cssProvider);
623 static void sendPixelResultsEOF()
631 static void runTest(const string& testPathOrURL)
633 ASSERT(!testPathOrURL.empty());
635 // Look for "'" as a separator between the path or URL, and the pixel dump hash that follows.
636 string testURL(testPathOrURL);
637 string expectedPixelHash;
638 size_t separatorPos = testURL.find("'");
639 if (separatorPos != string::npos) {
640 testURL = string(testPathOrURL, 0, separatorPos);
641 expectedPixelHash = string(testPathOrURL, separatorPos + 1);
644 // Convert the path into a full file URL if it does not look
645 // like an HTTP/S URL (doesn't start with http:// or https://).
646 if (testURL.find("http://") && testURL.find("https://")) {
647 GFile* testFile = g_file_new_for_path(testURL.c_str());
648 gchar* testURLCString = g_file_get_uri(testFile);
649 testURL = testURLCString;
650 g_free(testURLCString);
651 g_object_unref(testFile);
654 resetDefaultsToConsistentValues();
656 gLayoutTestController = LayoutTestController::create(testURL, expectedPixelHash);
660 gLayoutTestController->setIconDatabaseEnabled(false);
662 if (shouldLogFrameLoadDelegates(testURL))
663 gLayoutTestController->setDumpFrameLoadCallbacks(true);
665 if (shouldEnableDeveloperExtras(testURL)) {
666 gLayoutTestController->setDeveloperExtrasEnabled(true);
667 if (shouldOpenWebInspector(testURL))
668 gLayoutTestController->showWebInspector();
669 if (shouldDumpAsText(testURL)) {
670 gLayoutTestController->setDumpAsText(true);
671 gLayoutTestController->setGeneratePixelResults(false);
675 WorkQueue::shared()->clear();
676 WorkQueue::shared()->setFrozen(false);
678 bool isSVGW3CTest = (testURL.find("svg/W3C-SVG-1.1") != string::npos);
681 size.width = isSVGW3CTest ? 480 : LayoutTestController::maxViewWidth;
682 size.height = isSVGW3CTest ? 360 : LayoutTestController::maxViewHeight;
683 gtk_window_resize(GTK_WINDOW(window), size.width, size.height);
684 gtk_widget_size_allocate(container, &size);
687 g_object_unref(prevTestBFItem);
688 WebKitWebBackForwardList* bfList = webkit_web_view_get_back_forward_list(webView);
689 prevTestBFItem = webkit_web_back_forward_list_get_current_item(bfList);
691 g_object_ref(prevTestBFItem);
693 initializeFonts(testURL.c_str());
695 // Focus the web view before loading the test to avoid focusing problems
696 gtk_widget_grab_focus(GTK_WIDGET(webView));
697 webkit_web_view_open(webView, testURL.c_str());
701 // If developer extras enabled Web Inspector may have been open by the test.
702 if (shouldEnableDeveloperExtras(testURL)) {
703 gLayoutTestController->closeWebInspector();
704 gLayoutTestController->setDeveloperExtrasEnabled(false);
707 // Also check if we still have opened webViews and free them.
708 if (gLayoutTestController->closeRemainingWindowsWhenComplete() || webViewList) {
709 while (webViewList) {
710 g_object_unref(WEBKIT_WEB_VIEW(webViewList->data));
711 webViewList = g_slist_next(webViewList);
713 g_slist_free(webViewList);
717 WebCoreTestSupport::resetInternalsObject(webkit_web_frame_get_global_context(mainFrame));
719 // A blank load seems to be necessary to reset state after certain tests.
720 webkit_web_view_open(webView, "about:blank");
722 gLayoutTestController.clear();
724 // terminate the (possibly empty) pixels block after all the state reset
725 sendPixelResultsEOF();
728 void webViewLoadStarted(WebKitWebView* view, WebKitWebFrame* frame, void*)
730 // Make sure we only set this once per test. If it gets cleared, and then set again, we might
731 // end up doing two dumps for one test.
732 if (!topLoadingFrame && !done)
733 topLoadingFrame = frame;
736 static gboolean processWork(void* data)
738 // if we finish all the commands, we're ready to dump state
739 if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
745 static char* getFrameNameSuitableForTestResult(WebKitWebView* view, WebKitWebFrame* frame)
747 char* frameName = g_strdup(webkit_web_frame_get_name(frame));
749 if (frame == webkit_web_view_get_main_frame(view)) {
750 // This is a bit strange. Shouldn't web_frame_get_name return NULL?
751 if (frameName && (frameName[0] != '\0')) {
752 char* tmp = g_strdup_printf("main frame \"%s\"", frameName);
757 frameName = g_strdup("main frame");
759 } else if (!frameName || (frameName[0] == '\0')) {
761 frameName = g_strdup("frame (anonymous)");
763 char* tmp = g_strdup_printf("frame \"%s\"", frameName);
771 static void webViewLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*)
773 // The deprecated "load-finished" signal is triggered by postProgressFinishedNotification(),
774 // so we can use it here in the DRT to provide the correct dump.
775 if (frame != topLoadingFrame)
777 if (gLayoutTestController->dumpProgressFinishedCallback())
778 printf("postProgressFinishedNotification\n");
781 static gboolean webViewLoadError(WebKitWebView*, WebKitWebFrame*, gchar*, gpointer, gpointer)
783 return TRUE; // Return true here to disable the default error page.
786 static void webViewDocumentLoadFinished(WebKitWebView* view, WebKitWebFrame* frame, void*)
788 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
789 char* frameName = getFrameNameSuitableForTestResult(view, frame);
790 printf("%s - didFinishDocumentLoadForFrame\n", frameName);
793 guint pendingFrameUnloadEvents = DumpRenderTreeSupportGtk::getPendingUnloadEventCount(frame);
794 if (pendingFrameUnloadEvents) {
795 char* frameName = getFrameNameSuitableForTestResult(view, frame);
796 printf("%s - has %u onunload handler(s)\n", frameName, pendingFrameUnloadEvents);
802 static void webViewOnloadEvent(WebKitWebView* view, WebKitWebFrame* frame, void*)
804 if (!done && gLayoutTestController->dumpFrameLoadCallbacks()) {
805 char* frameName = getFrameNameSuitableForTestResult(view, frame);
806 printf("%s - didHandleOnloadEventsForFrame\n", frameName);
811 static void addControllerToWindow(JSContextRef context, JSObjectRef windowObject, const char* controllerName, JSValueRef controller)
813 JSStringRef controllerNameStr = JSStringCreateWithUTF8CString(controllerName);
814 JSObjectSetProperty(context, windowObject, controllerNameStr, controller, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
815 JSStringRelease(controllerNameStr);
818 static void webViewWindowObjectCleared(WebKitWebView* view, WebKitWebFrame* frame, JSGlobalContextRef context, JSObjectRef windowObject, gpointer data)
820 JSValueRef exception = 0;
821 ASSERT(gLayoutTestController);
823 gLayoutTestController->makeWindowObject(context, windowObject, &exception);
826 gcController->makeWindowObject(context, windowObject, &exception);
829 axController->makeWindowObject(context, windowObject, &exception);
832 addControllerToWindow(context, windowObject, "eventSender", makeEventSender(context, !webkit_web_frame_get_parent(frame)));
833 addControllerToWindow(context, windowObject, "textInputController", makeTextInputController(context));
834 WebCoreTestSupport::injectInternalsObject(context);
837 static gboolean webViewConsoleMessage(WebKitWebView* view, const gchar* message, unsigned int line, const gchar* sourceId, gpointer data)
839 gchar* testMessage = 0;
840 const gchar* uriScheme;
842 // Tests expect only the filename part of local URIs
843 uriScheme = g_strstr_len(message, -1, "file://");
845 GString* tempString = g_string_sized_new(strlen(message));
846 gchar* filename = g_strrstr(uriScheme, G_DIR_SEPARATOR_S);
849 // If the path is a lone slash, keep it to avoid empty output.
850 if (strlen(filename) > 1)
851 filename += strlen(G_DIR_SEPARATOR_S);
852 tempString = g_string_append_len(tempString, message, (uriScheme - message));
853 tempString = g_string_append_len(tempString, filename, strlen(filename));
854 testMessage = g_string_free(tempString, FALSE);
858 fprintf(stdout, "CONSOLE MESSAGE: ");
860 fprintf(stdout, "line %d: ", line);
861 fprintf(stdout, "%s\n", testMessage ? testMessage : message);
868 static gboolean webViewScriptAlert(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gpointer data)
870 fprintf(stdout, "ALERT: %s\n", message);
874 static gboolean webViewScriptPrompt(WebKitWebView* webView, WebKitWebFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value, gpointer data)
876 fprintf(stdout, "PROMPT: %s, default text: %s\n", message, defaultValue);
877 *value = g_strdup(defaultValue);
881 static gboolean webViewScriptConfirm(WebKitWebView* view, WebKitWebFrame* frame, const gchar* message, gboolean* didConfirm, gpointer data)
883 fprintf(stdout, "CONFIRM: %s\n", message);
888 static void webViewTitleChanged(WebKitWebView* view, WebKitWebFrame* frame, const gchar* title, gpointer data)
890 if (gLayoutTestController->dumpTitleChanges() && !done)
891 printf("TITLE CHANGED: %s\n", title ? title : "");
894 static bool webViewNavigationPolicyDecisionRequested(WebKitWebView* view, WebKitWebFrame* frame,
895 WebKitNetworkRequest* request,
896 WebKitWebNavigationAction* navAction,
897 WebKitWebPolicyDecision* policyDecision)
899 // Use the default handler if we're not waiting for policy,
900 // i.e., LayoutTestController::waitForPolicyDelegate
904 gchar* typeDescription;
905 WebKitWebNavigationReason reason;
906 g_object_get(G_OBJECT(navAction), "reason", &reason, NULL);
909 case WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED:
910 typeDescription = g_strdup("link clicked");
912 case WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED:
913 typeDescription = g_strdup("form submitted");
915 case WEBKIT_WEB_NAVIGATION_REASON_BACK_FORWARD:
916 typeDescription = g_strdup("back/forward");
918 case WEBKIT_WEB_NAVIGATION_REASON_RELOAD:
919 typeDescription = g_strdup("reload");
921 case WEBKIT_WEB_NAVIGATION_REASON_FORM_RESUBMITTED:
922 typeDescription = g_strdup("form resubmitted");
924 case WEBKIT_WEB_NAVIGATION_REASON_OTHER:
925 typeDescription = g_strdup("other");
928 typeDescription = g_strdup("illegal value");
931 printf("Policy delegate: attempt to load %s with navigation type '%s'\n", webkit_network_request_get_uri(request), typeDescription);
932 g_free(typeDescription);
934 webkit_web_policy_decision_ignore(policyDecision);
935 gLayoutTestController->notifyDone();
940 static void webViewStatusBarTextChanged(WebKitWebView* view, const gchar* message, gpointer data)
942 // Are we doing anything wrong? One test that does not call
943 // dumpStatusCallbacks gets true here
944 if (gLayoutTestController->dumpStatusCallbacks())
945 printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", message);
948 static gboolean webViewClose(WebKitWebView* view)
952 webViewList = g_slist_remove(webViewList, view);
953 g_object_unref(view);
958 static void databaseQuotaExceeded(WebKitWebView* view, WebKitWebFrame* frame, WebKitWebDatabase *database)
964 WebKitSecurityOrigin* origin = webkit_web_database_get_security_origin(database);
965 if (gLayoutTestController->dumpDatabaseCallbacks()) {
966 printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n",
967 webkit_security_origin_get_protocol(origin),
968 webkit_security_origin_get_host(origin),
969 webkit_security_origin_get_port(origin),
970 webkit_web_database_get_name(database));
972 webkit_security_origin_set_web_database_quota(origin, 5 * 1024 * 1024);
976 geolocationPolicyDecisionRequested(WebKitWebView*, WebKitWebFrame*, WebKitGeolocationPolicyDecision* decision)
978 if (!gLayoutTestController->isGeolocationPermissionSet())
980 if (gLayoutTestController->geolocationPermission())
981 webkit_geolocation_policy_allow(decision);
983 webkit_geolocation_policy_deny(decision);
989 static WebKitWebView* webViewCreate(WebKitWebView*, WebKitWebFrame*);
991 static gboolean webInspectorShowWindow(WebKitWebInspector*, gpointer data)
993 gtk_window_set_default_size(GTK_WINDOW(webInspectorWindow), 800, 600);
994 gtk_widget_show_all(webInspectorWindow);
998 static gboolean webInspectorCloseWindow(WebKitWebInspector*, gpointer data)
1000 gtk_widget_destroy(webInspectorWindow);
1001 webInspectorWindow = 0;
1005 static WebKitWebView* webInspectorInspectWebView(WebKitWebInspector*, gpointer data)
1007 webInspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1009 GtkWidget* webView = self_scrolling_webkit_web_view_new();
1010 gtk_container_add(GTK_CONTAINER(webInspectorWindow),
1013 return WEBKIT_WEB_VIEW(webView);
1016 static void topLoadingFrameLoadFinished()
1018 topLoadingFrame = 0;
1019 WorkQueue::shared()->setFrozen(true); // first complete load freezes the queue for the rest of this test
1020 if (gLayoutTestController->waitToDump())
1023 if (WorkQueue::shared()->count())
1024 g_timeout_add(0, processWork, 0);
1029 static void webFrameLoadStatusNotified(WebKitWebFrame* frame, gpointer user_data)
1031 WebKitLoadStatus loadStatus = webkit_web_frame_get_load_status(frame);
1033 if (gLayoutTestController->dumpFrameLoadCallbacks()) {
1034 GOwnPtr<char> frameName(getFrameNameSuitableForTestResult(webkit_web_frame_get_web_view(frame), frame));
1036 switch (loadStatus) {
1037 case WEBKIT_LOAD_PROVISIONAL:
1039 printf("%s - didStartProvisionalLoadForFrame\n", frameName.get());
1041 case WEBKIT_LOAD_COMMITTED:
1043 printf("%s - didCommitLoadForFrame\n", frameName.get());
1045 case WEBKIT_LOAD_FINISHED:
1047 printf("%s - didFinishLoadForFrame\n", frameName.get());
1054 if ((loadStatus == WEBKIT_LOAD_FINISHED || loadStatus == WEBKIT_LOAD_FAILED)
1055 && frame == topLoadingFrame)
1056 topLoadingFrameLoadFinished();
1059 static void frameCreatedCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, gpointer user_data)
1061 g_signal_connect(webFrame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL);
1062 g_signal_connect(webFrame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL);
1066 static CString pathFromSoupURI(SoupURI* uri)
1071 if (g_str_equal(uri->scheme, "http") || g_str_equal(uri->scheme, "ftp")) {
1072 GOwnPtr<char> uriString(soup_uri_to_string(uri, FALSE));
1073 return CString(uriString.get());
1076 GOwnPtr<gchar> pathDirname(g_path_get_basename(g_path_get_dirname(uri->path)));
1077 GOwnPtr<gchar> pathBasename(g_path_get_basename(uri->path));
1078 GOwnPtr<gchar> urlPath(g_strdup_printf("%s/%s", pathDirname.get(), pathBasename.get()));
1079 return CString(urlPath.get());
1082 static CString convertSoupMessageToURLPath(SoupMessage* soupMessage)
1086 if (SoupURI* requestURI = soup_message_get_uri(soupMessage))
1087 return pathFromSoupURI(requestURI);
1091 static CString convertNetworkRequestToURLPath(WebKitNetworkRequest* request)
1093 return convertSoupMessageToURLPath(webkit_network_request_get_message(request));
1096 static CString convertWebResourceToURLPath(WebKitWebResource* webResource)
1098 SoupURI* uri = soup_uri_new(webkit_web_resource_get_uri(webResource));
1099 CString urlPath(pathFromSoupURI(uri));
1104 static CString urlSuitableForTestResult(const char* uriString)
1106 if (!g_str_has_prefix(uriString, "file://"))
1107 return CString(uriString);
1109 GOwnPtr<gchar> basename(g_path_get_basename(uriString));
1110 return CString(basename.get());
1113 static CString descriptionSuitableForTestResult(SoupURI* uri)
1118 GOwnPtr<char> uriString(soup_uri_to_string(uri, false));
1119 return urlSuitableForTestResult(uriString.get());
1122 static CString descriptionSuitableForTestResult(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource)
1124 SoupURI* uri = soup_uri_new(webkit_web_resource_get_uri(webResource));
1125 CString description;
1126 WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(webFrame);
1128 if (webResource == webkit_web_data_source_get_main_resource(dataSource)
1129 && (!webkit_web_view_get_progress(webView) || g_str_equal(uri->scheme, "file")))
1130 description = CString("<unknown>");
1132 description = convertWebResourceToURLPath(webResource);
1140 static CString descriptionSuitableForTestResult(GError* error, WebKitWebResource* webResource)
1142 const gchar* errorDomain = g_quark_to_string(error->domain);
1143 CString resourceURIString(urlSuitableForTestResult(webkit_web_resource_get_uri(webResource)));
1145 if (g_str_equal(errorDomain, "webkit-network-error-quark") || g_str_equal(errorDomain, "soup_http_error_quark"))
1146 errorDomain = "NSURLErrorDomain";
1148 if (g_str_equal(errorDomain, "WebKitPolicyError"))
1149 errorDomain = "WebKitErrorDomain";
1151 // TODO: the other ports get the failingURL from the ResourceError
1152 GOwnPtr<char> errorString(g_strdup_printf("<NSError domain %s, code %d, failing URL \"%s\">",
1153 errorDomain, error->code, resourceURIString.data()));
1154 return CString(errorString.get());
1157 static CString descriptionSuitableForTestResult(WebKitNetworkRequest* request)
1159 SoupMessage* soupMessage = webkit_network_request_get_message(request);
1164 SoupURI* requestURI = soup_message_get_uri(soupMessage);
1165 SoupURI* mainDocumentURI = soup_message_get_first_party(soupMessage);
1166 CString requestURIString(descriptionSuitableForTestResult(requestURI));
1167 CString mainDocumentURIString(descriptionSuitableForTestResult(mainDocumentURI));
1168 CString path(convertNetworkRequestToURLPath(request));
1169 GOwnPtr<char> description(g_strdup_printf("<NSURLRequest URL %s, main document URL %s, http method %s>",
1170 path.data(), mainDocumentURIString.data(),
1171 soupMessage ? soupMessage->method : "(none)"));
1172 return CString(description.get());
1175 static CString descriptionSuitableForTestResult(WebKitNetworkResponse* response)
1178 return CString("(null)");
1181 CString responseURIString(urlSuitableForTestResult(webkit_network_response_get_uri(response)));
1182 SoupMessage* soupMessage = webkit_network_response_get_message(response);
1186 statusCode = soupMessage->status_code;
1187 path = convertSoupMessageToURLPath(soupMessage);
1191 GOwnPtr<char> description(g_strdup_printf("<NSURLResponse %s, http status code %d>", path.data(), statusCode));
1192 return CString(description.get());
1195 static void willSendRequestCallback(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response)
1199 if (!done && gLayoutTestController->willSendRequestReturnsNull()) {
1200 // As requested by the LayoutTestController, don't perform the request.
1201 webkit_network_request_set_uri(request, "about:blank");
1205 if (!done && gLayoutTestController->dumpResourceLoadCallbacks())
1206 printf("%s - willSendRequest %s redirectResponse %s\n",
1207 convertNetworkRequestToURLPath(request).data(),
1208 descriptionSuitableForTestResult(request).data(),
1209 descriptionSuitableForTestResult(response).data());
1211 SoupMessage* soupMessage = webkit_network_request_get_message(request);
1212 SoupURI* uri = soup_uri_new(webkit_network_request_get_uri(request));
1214 if (SOUP_URI_VALID_FOR_HTTP(uri) && g_strcmp0(uri->host, "127.0.0.1")
1215 && g_strcmp0(uri->host, "255.255.255.255")
1216 && g_ascii_strncasecmp(uri->host, "localhost", 9)) {
1217 printf("Blocked access to external URL %s\n", soup_uri_to_string(uri, FALSE));
1218 // Cancel load of blocked resource to avoid potential
1219 // network-related timeouts in tests.
1220 webkit_network_request_set_uri(request, "about:blank");
1229 const set<string>& clearHeaders = gLayoutTestController->willSendRequestClearHeaders();
1230 for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header)
1231 soup_message_headers_remove(soupMessage->request_headers, header->c_str());
1236 static void didReceiveResponse(WebKitWebView* webView, WebKitWebFrame*, WebKitWebResource* webResource, WebKitNetworkResponse* response)
1238 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
1239 CString responseDescription(descriptionSuitableForTestResult(response));
1240 CString path(convertWebResourceToURLPath(webResource));
1241 printf("%s - didReceiveResponse %s\n", path.data(), responseDescription.data());
1244 // TODO: add "has MIME type" whenever dumpResourceResponseMIMETypes() is supported.
1245 // See https://bugs.webkit.org/show_bug.cgi?id=58222.
1248 static void didFinishLoading(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource)
1250 if (!done && gLayoutTestController->dumpResourceLoadCallbacks())
1251 printf("%s - didFinishLoading\n", descriptionSuitableForTestResult(webView, webFrame, webResource).data());
1254 static void didFailLoadingWithError(WebKitWebView* webView, WebKitWebFrame* webFrame, WebKitWebResource* webResource, GError* webError)
1256 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
1257 CString webErrorString(descriptionSuitableForTestResult(webError, webResource));
1258 printf("%s - didFailLoadingWithError: %s\n", descriptionSuitableForTestResult(webView, webFrame, webResource).data(),
1259 webErrorString.data());
1263 static void didRunInsecureContent(WebKitWebFrame*, WebKitSecurityOrigin*, const char* url)
1265 if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
1266 printf("didRunInsecureContent\n");
1269 static WebKitWebView* createWebView()
1271 // It is important to declare DRT is running early so when creating
1272 // web view mock clients are used instead of proper ones.
1273 DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(true);
1275 WebKitWebView* view = WEBKIT_WEB_VIEW(self_scrolling_webkit_web_view_new());
1277 g_object_connect(G_OBJECT(view),
1278 "signal::load-started", webViewLoadStarted, 0,
1279 "signal::load-finished", webViewLoadFinished, 0,
1280 "signal::load-error", webViewLoadError, 0,
1281 "signal::window-object-cleared", webViewWindowObjectCleared, 0,
1282 "signal::console-message", webViewConsoleMessage, 0,
1283 "signal::script-alert", webViewScriptAlert, 0,
1284 "signal::script-prompt", webViewScriptPrompt, 0,
1285 "signal::script-confirm", webViewScriptConfirm, 0,
1286 "signal::title-changed", webViewTitleChanged, 0,
1287 "signal::navigation-policy-decision-requested", webViewNavigationPolicyDecisionRequested, 0,
1288 "signal::status-bar-text-changed", webViewStatusBarTextChanged, 0,
1289 "signal::create-web-view", webViewCreate, 0,
1290 "signal::close-web-view", webViewClose, 0,
1291 "signal::database-quota-exceeded", databaseQuotaExceeded, 0,
1292 "signal::document-load-finished", webViewDocumentLoadFinished, 0,
1293 "signal::geolocation-policy-decision-requested", geolocationPolicyDecisionRequested, 0,
1294 "signal::onload-event", webViewOnloadEvent, 0,
1295 "signal::drag-begin", dragBeginCallback, 0,
1296 "signal::drag-end", dragEndCallback, 0,
1297 "signal::drag-failed", dragFailedCallback, 0,
1298 "signal::frame-created", frameCreatedCallback, 0,
1299 "signal::resource-request-starting", willSendRequestCallback, 0,
1300 "signal::resource-response-received", didReceiveResponse, 0,
1301 "signal::resource-load-finished", didFinishLoading, 0,
1302 "signal::resource-load-failed", didFailLoadingWithError, 0,
1304 connectEditingCallbacks(view);
1306 WebKitWebInspector* inspector = webkit_web_view_get_inspector(view);
1307 g_object_connect(G_OBJECT(inspector),
1308 "signal::inspect-web-view", webInspectorInspectWebView, 0,
1309 "signal::show-window", webInspectorShowWindow, 0,
1310 "signal::close-window", webInspectorCloseWindow, 0,
1314 WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
1315 webkit_web_view_set_settings(view, settings);
1318 // frame-created is not issued for main frame. That's why we must do this here
1319 WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
1320 g_signal_connect(frame, "notify::load-status", G_CALLBACK(webFrameLoadStatusNotified), NULL);
1321 g_signal_connect(frame, "insecure-content-run", G_CALLBACK(didRunInsecureContent), NULL);
1326 static WebKitWebView* webViewCreate(WebKitWebView* view, WebKitWebFrame* frame)
1328 if (!gLayoutTestController->canOpenWindows())
1331 // Make sure that waitUntilDone has been called.
1332 ASSERT(gLayoutTestController->waitToDump());
1334 WebKitWebView* newWebView = createWebView();
1335 g_object_ref_sink(G_OBJECT(newWebView));
1336 webViewList = g_slist_prepend(webViewList, newWebView);
1340 static void logHandler(const gchar* domain, GLogLevelFlags level, const gchar* message, gpointer data)
1342 if (level < G_LOG_LEVEL_DEBUG)
1343 fprintf(stderr, "%s\n", message);
1346 int main(int argc, char* argv[])
1348 gtk_init(&argc, &argv);
1350 // Some plugins might try to use the GLib logger for printing debug
1351 // messages. This will cause tests to fail because of unexpected output.
1352 // We squelch all debug messages sent to the logger.
1353 g_log_set_default_handler(logHandler, 0);
1355 initializeGlobalsFromCommandLineOptions(argc, argv);
1358 window = gtk_window_new(GTK_WINDOW_POPUP);
1359 #ifdef GTK_API_VERSION_2
1360 container = gtk_hbox_new(TRUE, 0);
1362 container = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
1363 gtk_box_set_homogeneous(GTK_BOX(container), TRUE);
1365 gtk_container_add(GTK_CONTAINER(window), container);
1366 gtk_widget_show_all(window);
1368 webView = createWebView();
1369 gtk_box_pack_start(GTK_BOX(container), GTK_WIDGET(webView), TRUE, TRUE, 0);
1370 gtk_widget_realize(GTK_WIDGET(webView));
1371 gtk_widget_show_all(container);
1372 mainFrame = webkit_web_view_get_main_frame(webView);
1374 setDefaultsToConsistentStateValuesForTesting();
1376 gcController = new GCController();
1377 axController = new AccessibilityController();
1379 if (useLongRunningServerMode(argc, argv)) {
1380 printSeparators = true;
1381 runTestingServerLoop();
1383 printSeparators = (optind < argc-1 || (dumpPixels && dumpTree));
1384 for (int i = optind; i != argc; ++i)
1388 delete gcController;
1391 delete axController;
1394 gtk_widget_destroy(window);