123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- /*
- * Copyright (C) 2011 ProFUSION Embedded Systems
- * Copyright (C) 2011 Samsung Electronics
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "config.h"
- #include "DumpRenderTree.h"
- #include "DumpHistoryItem.h"
- #include "DumpRenderTreeChrome.h"
- #include "DumpRenderTreeView.h"
- #include "EventSender.h"
- #include "FontManagement.h"
- #include "NotImplemented.h"
- #include "PixelDumpSupport.h"
- #include "TestRunner.h"
- #include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
- #include "WebCoreTestSupport.h"
- #include "WorkQueue.h"
- #include "ewk_private.h"
- #include <EWebKit.h>
- #include <Ecore.h>
- #include <Ecore_Evas.h>
- #include <Ecore_File.h>
- #include <Edje.h>
- #include <Evas.h>
- #include <fontconfig/fontconfig.h>
- #include <getopt.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <wtf/Assertions.h>
- #include <wtf/OwnPtr.h>
- #include <wtf/text/CString.h>
- #include <wtf/text/StringBuilder.h>
- OwnPtr<DumpRenderTreeChrome> browser;
- Evas_Object* topLoadingFrame = 0;
- bool waitForPolicy = false;
- bool policyDelegateEnabled = false;
- bool policyDelegatePermissive = false;
- Ecore_Timer* waitToDumpWatchdog = 0;
- extern Ewk_History_Item* prevTestBFItem;
- // From the top-level DumpRenderTree.h
- RefPtr<TestRunner> gTestRunner;
- volatile bool done = false;
- static bool dumpPixelsForCurrentTest;
- static int dumpPixelsForAllTests = false;
- static int dumpTree = true;
- static int printSeparators = true;
- static int useTimeoutWatchdog = true;
- static String dumpFramesAsText(Evas_Object* frame)
- {
- if (!frame)
- return String();
- String result;
- const char* frameContents = ewk_frame_plain_text_get(frame);
- if (!frameContents)
- return String();
- if (browser->mainFrame() != frame) {
- result.append("\n--------\nFrame: '");
- result.append(String::fromUTF8(ewk_frame_name_get(frame)));
- result.append("'\n--------\n");
- }
- result.append(String::fromUTF8(frameContents));
- result.append("\n");
- eina_stringshare_del(frameContents);
- if (gTestRunner->dumpChildFramesAsText()) {
- Eina_List* children = DumpRenderTreeSupportEfl::frameChildren(frame);
- void* iterator;
- EINA_LIST_FREE(children, iterator) {
- Evas_Object* currentFrame = static_cast<Evas_Object*>(iterator);
- String tempText(dumpFramesAsText(currentFrame));
- if (tempText.isEmpty())
- continue;
- result.append(tempText);
- }
- }
- return result;
- }
- static void dumpFrameScrollPosition(Evas_Object* frame)
- {
- int x, y;
- ewk_frame_scroll_pos_get(frame, &x, &y);
- if (abs(x) > 0 || abs(y) > 0) {
- StringBuilder result;
- Evas_Object* parent = evas_object_smart_parent_get(frame);
- // smart parent of main frame is view object.
- if (parent != browser->mainView()) {
- result.append("frame '");
- result.append(ewk_frame_name_get(frame));
- result.append("' ");
- }
- result.append("scrolled to ");
- result.append(WTF::String::number(x));
- result.append(",");
- result.append(WTF::String::number(y));
- result.append("\n");
- printf("%s", result.toString().utf8().data());
- }
- if (gTestRunner->dumpChildFrameScrollPositions()) {
- Eina_List* children = DumpRenderTreeSupportEfl::frameChildren(frame);
- void* iterator;
- EINA_LIST_FREE(children, iterator) {
- Evas_Object* currentFrame = static_cast<Evas_Object*>(iterator);
- dumpFrameScrollPosition(currentFrame);
- }
- }
- }
- static bool shouldLogFrameLoadDelegates(const String& pathOrURL)
- {
- return pathOrURL.contains("loading/");
- }
- static bool shouldDumpAsText(const String& pathOrURL)
- {
- return pathOrURL.contains("dumpAsText/");
- }
- static bool shouldOpenWebInspector(const String& pathOrURL)
- {
- return pathOrURL.contains("inspector/");
- }
- static void sendPixelResultsEOF()
- {
- puts("#EOF");
- fflush(stdout);
- fflush(stderr);
- }
- bool shouldSetWaitToDumpWatchdog()
- {
- return !waitToDumpWatchdog && useTimeoutWatchdog;
- }
- static void invalidateAnyPreviousWaitToDumpWatchdog()
- {
- if (waitToDumpWatchdog) {
- ecore_timer_del(waitToDumpWatchdog);
- waitToDumpWatchdog = 0;
- }
- waitForPolicy = false;
- }
- static void onEcoreEvasResize(Ecore_Evas* ecoreEvas)
- {
- int width, height;
- ecore_evas_geometry_get(ecoreEvas, 0, 0, &width, &height);
- evas_object_move(browser->mainView(), 0, 0);
- evas_object_resize(browser->mainView(), width, height);
- }
- static void onCloseWindow(Ecore_Evas*)
- {
- notImplemented();
- }
- static Eina_Bool useLongRunningServerMode(int argc, char** argv)
- {
- return (argc == optind + 1 && !strcmp(argv[optind], "-"));
- }
- static bool parseCommandLineOptions(int argc, char** argv)
- {
- static const option options[] = {
- {"notree", no_argument, &dumpTree, false},
- {"pixel-tests", no_argument, &dumpPixelsForAllTests, true},
- {"tree", no_argument, &dumpTree, true},
- {"no-timeout", no_argument, &useTimeoutWatchdog, false},
- {0, 0, 0, 0}
- };
- int option;
- while ((option = getopt_long(argc, (char* const*)argv, "", options, 0)) != -1) {
- switch (option) {
- case '?':
- case ':':
- return false;
- }
- }
- return true;
- }
- static inline bool isGlobalHistoryTest(const String& cTestPathOrURL)
- {
- return cTestPathOrURL.contains("/globalhistory/");
- }
- static void createTestRunner(const String& testURL, const String& expectedPixelHash)
- {
- gTestRunner =
- TestRunner::create(std::string(testURL.utf8().data()),
- std::string(expectedPixelHash.utf8().data()));
- topLoadingFrame = 0;
- done = false;
- gTestRunner->setIconDatabaseEnabled(false);
- if (shouldLogFrameLoadDelegates(testURL))
- gTestRunner->setDumpFrameLoadCallbacks(true);
- gTestRunner->setDeveloperExtrasEnabled(true);
- if (shouldOpenWebInspector(testURL))
- gTestRunner->showWebInspector();
- gTestRunner->setDumpHistoryDelegateCallbacks(isGlobalHistoryTest(testURL));
- if (shouldDumpAsText(testURL)) {
- gTestRunner->setDumpAsText(true);
- gTestRunner->setGeneratePixelResults(false);
- }
- }
- static String getFinalTestURL(const String& testURL)
- {
- if (!testURL.startsWith("http://") && !testURL.startsWith("https://")) {
- char* cFilePath = ecore_file_realpath(testURL.utf8().data());
- const String filePath = String::fromUTF8(cFilePath);
- free(cFilePath);
- if (ecore_file_exists(filePath.utf8().data()))
- return String("file://") + filePath;
- }
- return testURL;
- }
- static void runTest(const char* inputLine)
- {
- TestCommand command = parseInputLine(inputLine);
- const String testPathOrURL(command.pathOrURL.c_str());
- ASSERT(!testPathOrURL.isEmpty());
- dumpPixelsForCurrentTest = command.shouldDumpPixels || dumpPixelsForAllTests;
- const String expectedPixelHash(command.expectedPixelHash.c_str());
- // Convert the path into a full file URL if it does not look
- // like an HTTP/S URL (doesn't start with http:// or https://).
- const String testURL = getFinalTestURL(testPathOrURL);
- browser->resetDefaultsToConsistentValues();
- createTestRunner(testURL, expectedPixelHash);
- WorkQueue::shared()->clear();
- WorkQueue::shared()->setFrozen(false);
- const bool isSVGW3CTest = testURL.contains("svg/W3C-SVG-1.1");
- const int width = isSVGW3CTest ? TestRunner::w3cSVGViewWidth : TestRunner::viewWidth;
- const int height = isSVGW3CTest ? TestRunner::w3cSVGViewHeight : TestRunner::viewHeight;
- evas_object_resize(browser->mainView(), width, height);
- if (prevTestBFItem)
- ewk_history_item_free(prevTestBFItem);
- const Ewk_History* history = ewk_view_history_get(browser->mainView());
- prevTestBFItem = ewk_history_history_item_current_get(history);
- evas_object_focus_set(browser->mainView(), EINA_TRUE);
- ewk_view_uri_set(browser->mainView(), testURL.utf8().data());
- ecore_main_loop_begin();
- gTestRunner->closeWebInspector();
- gTestRunner->setDeveloperExtrasEnabled(false);
- browser->clearExtraViews();
- // FIXME: Move to DRTChrome::resetDefaultsToConsistentValues() after bug 85209 lands.
- WebCoreTestSupport::resetInternalsObject(DumpRenderTreeSupportEfl::globalContextRefForFrame(browser->mainFrame()));
- ewk_view_uri_set(browser->mainView(), "about:blank");
- gTestRunner.clear();
- sendPixelResultsEOF();
- }
- static void runTestingServerLoop()
- {
- char filename[PATH_MAX];
- while (fgets(filename, sizeof(filename), stdin)) {
- char* newLine = strrchr(filename, '\n');
- if (newLine)
- *newLine = '\0';
- if (filename[0] != '\0')
- runTest(filename);
- }
- }
- static void adjustOutputTypeByMimeType(const Evas_Object* frame)
- {
- const String responseMimeType(DumpRenderTreeSupportEfl::responseMimeType(frame));
- if (responseMimeType == "text/plain") {
- gTestRunner->setDumpAsText(true);
- gTestRunner->setGeneratePixelResults(false);
- }
- }
- static void dumpFrameContentsAsText(Evas_Object* frame)
- {
- String result;
- if (gTestRunner->dumpAsText())
- result = dumpFramesAsText(frame);
- else
- result = DumpRenderTreeSupportEfl::renderTreeDump(frame);
- printf("%s", result.utf8().data());
- }
- static bool shouldDumpFrameScrollPosition()
- {
- return !gTestRunner->dumpAsText() && !gTestRunner->dumpDOMAsWebArchive() && !gTestRunner->dumpSourceAsWebArchive();
- }
- static bool shouldDumpPixelsAndCompareWithExpected()
- {
- return dumpPixelsForCurrentTest && gTestRunner->generatePixelResults() && !gTestRunner->dumpDOMAsWebArchive() && !gTestRunner->dumpSourceAsWebArchive();
- }
- static bool shouldDumpBackForwardList()
- {
- return gTestRunner->dumpBackForwardList();
- }
- static bool initEfl()
- {
- if (!ecore_evas_init())
- return false;
- if (!ecore_file_init()) {
- ecore_evas_shutdown();
- return false;
- }
- if (!edje_init()) {
- ecore_file_shutdown();
- ecore_evas_shutdown();
- return false;
- }
- if (!ewk_init()) {
- edje_shutdown();
- ecore_file_shutdown();
- ecore_evas_shutdown();
- return false;
- }
- return true;
- }
- static void shutdownEfl()
- {
- ewk_shutdown();
- edje_shutdown();
- ecore_file_shutdown();
- ecore_evas_shutdown();
- }
- void displayWebView()
- {
- DumpRenderTreeSupportEfl::forceLayout(browser->mainFrame());
- DumpRenderTreeSupportEfl::setTracksRepaints(browser->mainFrame(), true);
- DumpRenderTreeSupportEfl::resetTrackedRepaints(browser->mainFrame());
- }
- void dump()
- {
- Evas_Object* frame = browser->mainFrame();
- invalidateAnyPreviousWaitToDumpWatchdog();
- if (dumpTree) {
- adjustOutputTypeByMimeType(frame);
- dumpFrameContentsAsText(frame);
- if (shouldDumpFrameScrollPosition())
- dumpFrameScrollPosition(frame);
- if (shouldDumpBackForwardList())
- dumpBackForwardListForWebViews();
- if (printSeparators) {
- puts("#EOF");
- fputs("#EOF\n", stderr);
- fflush(stdout);
- fflush(stderr);
- }
- }
- if (shouldDumpPixelsAndCompareWithExpected())
- dumpWebViewAsPixelsAndCompareWithExpected(gTestRunner->expectedPixelHash());
- done = true;
- ecore_main_loop_quit();
- }
- static Ecore_Evas* initEcoreEvas()
- {
- const char* engine = 0;
- #if defined(WTF_USE_ACCELERATED_COMPOSITING) && defined(HAVE_ECORE_X)
- engine = "opengl_x11";
- #endif
- Ecore_Evas* ecoreEvas = ecore_evas_new(engine, 0, 0, 800, 600, 0);
- if (!ecoreEvas) {
- shutdownEfl();
- exit(EXIT_FAILURE);
- }
- ecore_evas_title_set(ecoreEvas, "EFL DumpRenderTree");
- ecore_evas_callback_resize_set(ecoreEvas, onEcoreEvasResize);
- ecore_evas_callback_delete_request_set(ecoreEvas, onCloseWindow);
- ecore_evas_show(ecoreEvas);
- return ecoreEvas;
- }
- int main(int argc, char** argv)
- {
- if (!parseCommandLineOptions(argc, argv))
- return EXIT_FAILURE;
- if (!initEfl())
- return EXIT_FAILURE;
- WTFInstallReportBacktraceOnCrashHook();
- OwnPtr<Ecore_Evas> ecoreEvas = adoptPtr(initEcoreEvas());
- browser = DumpRenderTreeChrome::create(ecore_evas_get(ecoreEvas.get()));
- addFontsToEnvironment();
- if (useLongRunningServerMode(argc, argv)) {
- printSeparators = true;
- runTestingServerLoop();
- } else {
- printSeparators = (optind < argc - 1 || (dumpPixelsForCurrentTest && dumpTree));
- for (int i = optind; i != argc; ++i)
- runTest(argv[i]);
- }
- ecoreEvas.clear();
- shutdownEfl();
- return EXIT_SUCCESS;
- }
|