summaryrefslogtreecommitdiff
path: root/Tools/DumpRenderTree/efl
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/DumpRenderTree/efl')
-rw-r--r--Tools/DumpRenderTree/efl/CMakeLists.txt132
-rw-r--r--Tools/DumpRenderTree/efl/DumpHistoryItem.cpp134
-rw-r--r--Tools/DumpRenderTree/efl/DumpHistoryItem.h33
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTree.cpp416
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp282
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h80
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTreeEfl.h41
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp113
-rw-r--r--Tools/DumpRenderTree/efl/DumpRenderTreeView.h32
-rw-r--r--Tools/DumpRenderTree/efl/EventSender.cpp507
-rw-r--r--Tools/DumpRenderTree/efl/EventSender.h41
-rw-r--r--Tools/DumpRenderTree/efl/FontManagement.cpp132
-rw-r--r--Tools/DumpRenderTree/efl/FontManagement.h31
-rw-r--r--Tools/DumpRenderTree/efl/GCControllerEfl.cpp49
-rw-r--r--Tools/DumpRenderTree/efl/ImageDiff.cpp359
-rw-r--r--Tools/DumpRenderTree/efl/JSStringUtils.cpp38
-rw-r--r--Tools/DumpRenderTree/efl/JSStringUtils.h38
-rw-r--r--Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp785
-rw-r--r--Tools/DumpRenderTree/efl/PixelDumpSupportEfl.cpp71
-rw-r--r--Tools/DumpRenderTree/efl/WorkQueueItemEfl.cpp79
20 files changed, 3393 insertions, 0 deletions
diff --git a/Tools/DumpRenderTree/efl/CMakeLists.txt b/Tools/DumpRenderTree/efl/CMakeLists.txt
new file mode 100644
index 000000000..c929191b2
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/CMakeLists.txt
@@ -0,0 +1,132 @@
+SET(DumpRenderTree_SOURCES
+ ${TOOLS_DIR}/DumpRenderTree/CyclicRedundancyCheck.cpp
+ ${TOOLS_DIR}/DumpRenderTree/GCController.cpp
+ ${TOOLS_DIR}/DumpRenderTree/LayoutTestController.cpp
+ ${TOOLS_DIR}/DumpRenderTree/PixelDumpSupport.cpp
+ ${TOOLS_DIR}/DumpRenderTree/WorkQueue.cpp
+ ${TOOLS_DIR}/DumpRenderTree/cairo/PixelDumpSupportCairo.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/DumpHistoryItem.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/DumpRenderTree.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/DumpRenderTreeChrome.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/DumpRenderTreeView.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/EventSender.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/FontManagement.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/GCControllerEfl.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/JSStringUtils.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/LayoutTestControllerEfl.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/PixelDumpSupportEfl.cpp
+ ${TOOLS_DIR}/DumpRenderTree/efl/WorkQueueItemEfl.cpp
+)
+
+SET(ImageDiff_SOURCES
+ ${TOOLS_DIR}/DumpRenderTree/efl/ImageDiff.cpp
+)
+
+SET(DumpRenderTree_LIBRARIES
+ ${JavaScriptCore_LIBRARY_NAME}
+ ${WebCore_LIBRARY_NAME}
+ ${WebKit_LIBRARY_NAME}
+ ${Cairo_LIBRARIES}
+ ${ECORE_X_LIBRARIES}
+ ${EDJE_LIBRARIES}
+ ${EFLDEPS_LIBRARIES}
+ ${EVAS_LIBRARIES}
+ ${LIBXML2_LIBRARIES}
+ ${LIBXSLT_LIBRARIES}
+ ${SQLITE_LIBRARIES}
+)
+
+SET(DumpRenderTree_LIBRARIES ${DumpRenderTree_LIBRARIES})
+SET(DumpRenderTree_INCLUDE_DIRECTORIES
+ "${WEBKIT_DIR}/efl/ewk"
+ ${WEBKIT_DIR}/efl
+ ${WEBCORE_DIR}
+ ${WEBCORE_DIR}/bridge
+ ${WEBCORE_DIR}/bridge/jsc
+ ${WEBCORE_DIR}/bindings
+ ${WEBCORE_DIR}/dom
+ ${WEBCORE_DIR}/editing
+ ${WEBCORE_DIR}/css
+ ${WEBCORE_DIR}/html
+ ${WEBCORE_DIR}/page
+ ${WEBCORE_DIR}/page/animation
+ ${WEBCORE_DIR}/platform
+ ${WEBCORE_DIR}/platform/animation
+ ${WEBCORE_DIR}/platform/text
+ ${WEBCORE_DIR}/platform/graphics
+ ${WEBCORE_DIR}/platform/graphics/cairo
+ ${WEBCORE_DIR}/platform/network
+ ${WEBCORE_DIR}/plugins
+ ${WEBCORE_DIR}/rendering
+ ${WEBCORE_DIR}/rendering/style
+ ${WEBCORE_DIR}/history
+ ${WEBCORE_DIR}/loader
+ ${WEBCORE_DIR}/loader/cache
+ ${WEBCORE_DIR}/loader/icon
+ ${JAVASCRIPTCORE_DIR}
+ ${JAVASCRIPTCORE_DIR}/API
+ ${JAVASCRIPTCORE_DIR}/assembler
+ ${JAVASCRIPTCORE_DIR}/dfg
+ ${JAVASCRIPTCORE_DIR}/heap
+ ${JAVASCRIPTCORE_DIR}/interpreter
+ ${JAVASCRIPTCORE_DIR}/jit
+ ${JAVASCRIPTCORE_DIR}/runtime
+ ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+ ${JAVASCRIPTCORE_DIR}/wtf
+ ${JAVASCRIPTCORE_DIR}/wtf/efl
+ ${TOOLS_DIR}/DumpRenderTree
+ ${TOOLS_DIR}/DumpRenderTree/cairo
+ ${TOOLS_DIR}/DumpRenderTree/efl
+ ${CMAKE_SOURCE_DIR}/Source
+ ${CMAKE_BINARY_DIR}
+ ${DERIVED_SOURCES_WEBCORE_DIR}
+ ${WEBCORE_DIR}/bindings/js
+ ${Cairo_INCLUDE_DIRS}
+ ${EDJE_INCLUDE_DIRS}
+ ${EFLDEPS_INCLUDE_DIRS}
+ ${EVAS_INCLUDE_DIRS}
+)
+
+SET(DumpRenderTree_LINK_FLAGS
+ ${ECORE_X_LDFLAGS}
+ ${EDJE_LDFLAGS}
+ ${EFLDEPS_LDFLAGS}
+ ${EVAS_LDFLAGS}
+)
+
+IF (ENABLE_GLIB_SUPPORT)
+ LIST(APPEND DumpRenderTree_INCLUDE_DIRECTORIES "${JAVASCRIPTCORE_DIR}/wtf/gobject")
+
+ LIST(APPEND DumpRenderTree_LIBRARIES
+ ${Gdk_LIBRARIES}
+ ${Glib_LIBRARIES}
+ ${Gthread_LIBRARIES}
+ )
+ENDIF ()
+
+IF (WTF_USE_SOUP)
+ LIST(APPEND DumpRenderTree_LIBRARIES ${LIBSOUP24_LIBRARIES})
+ LIST(APPEND DumpRenderTree_LINK_FLAGS ${LIBSOUP24_LDFLAGS})
+ LIST(APPEND DumpRenderTree_INCLUDE_DIRECTORIES ${LIBSOUP24_INCLUDE_DIRS} ${WEBCORE_DIR}/platform/network/soup)
+ENDIF ()
+
+IF (WTF_USE_CURL)
+ LIST(APPEND DumpRenderTree_LIBRARIES ${CURL_LIBRARIES})
+ LIST(APPEND DumpRenderTree_LINK_FLAGS ${CURL_LDFLAGS})
+ LIST(APPEND DumpRenderTree_INCLUDE_DIRECTORIES ${WEBCORE_DIR}/platform/network/curl)
+ENDIF ()
+
+ADD_DEFINITIONS(-DFONTS_CONF_DIR="${TOOLS_DIR}/DumpRenderTree/gtk/fonts"
+ -DDATA_DIR="${THEME_BINARY_DIR}")
+
+INCLUDE_DIRECTORIES(${DumpRenderTree_INCLUDE_DIRECTORIES})
+
+ADD_EXECUTABLE(Programs/DumpRenderTree ${DumpRenderTree_SOURCES})
+TARGET_LINK_LIBRARIES(Programs/DumpRenderTree ${DumpRenderTree_LIBRARIES})
+ADD_TARGET_PROPERTIES(Programs/DumpRenderTree LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
+SET_TARGET_PROPERTIES(Programs/DumpRenderTree PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
+
+ADD_EXECUTABLE(Programs/ImageDiff ${ImageDiff_SOURCES})
+TARGET_LINK_LIBRARIES(Programs/ImageDiff ${DumpRenderTree_LIBRARIES})
+ADD_TARGET_PROPERTIES(Programs/ImageDiff LINK_FLAGS "${DumpRenderTree_LINK_FLAGS}")
+SET_TARGET_PROPERTIES(Programs/ImageDiff PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
diff --git a/Tools/DumpRenderTree/efl/DumpHistoryItem.cpp b/Tools/DumpRenderTree/efl/DumpHistoryItem.cpp
new file mode 100644
index 000000000..125b12847
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpHistoryItem.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "DumpHistoryItem.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeChrome.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "ewk_private.h"
+#include <EWebKit.h>
+#include <algorithm>
+#include <cstdio>
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+Ewk_History_Item* prevTestBFItem = 0;
+const unsigned historyItemIndent = 8;
+
+static bool compareHistoryItemsByTarget(const Ewk_History_Item* item1, const Ewk_History_Item* item2)
+{
+ return WTF::codePointCompare(DumpRenderTreeSupportEfl::historyItemTarget(item1),
+ DumpRenderTreeSupportEfl::historyItemTarget(item2)) < 1;
+}
+
+static void dumpHistoryItem(const Ewk_History_Item* item, int indent, bool current)
+{
+ ASSERT(item);
+ int start = 0;
+ if (current) {
+ printf("curr->");
+ start = 6;
+ }
+ for (int i = start; i < indent; i++)
+ putchar(' ');
+
+ // normalize file URLs.
+ const char* uri = ewk_history_item_uri_get(item);
+ if (!strncasecmp(uri, "file://", sizeof("file://") - 1)) {
+ const char* pos = strstr(uri, "/LayoutTests/");
+ if (!pos)
+ return;
+
+ printf("(file test):%s", pos + sizeof("/LayoutTests/") - 1);
+ } else
+ printf("%s", uri);
+
+ const String target = DumpRenderTreeSupportEfl::historyItemTarget(item);
+ if (!target.isEmpty())
+ printf(" (in frame \"%s\")", target.utf8().data());
+ if (DumpRenderTreeSupportEfl::isTargetItem(item))
+ printf(" **nav target**");
+ putchar('\n');
+
+ HistoryItemChildrenVector children = DumpRenderTreeSupportEfl::childHistoryItems(item);
+
+ // Must sort to eliminate arbitrary result ordering which defeats reproducible testing.
+ std::stable_sort(children.begin(), children.end(), compareHistoryItemsByTarget);
+
+ const size_t size = children.size();
+ for (size_t i = 0; i < size; ++i)
+ dumpHistoryItem(children[i], indent + 4, false);
+}
+
+static void dumpBackForwardListForWebView(Evas_Object* view)
+{
+ printf("\n============== Back Forward List ==============\n");
+
+ const Ewk_History* history = ewk_view_history_get(view);
+
+ // Print out all items in the list after prevTestBFItem, which was from the previous test
+ // Gather items from the end of the list, the print them out from oldest to newest
+ Eina_List* itemsToPrint = 0;
+ void* historyItem;
+ Eina_List* backwardList = ewk_history_back_list_get(history);
+ EINA_LIST_FREE(backwardList, historyItem) {
+ if (historyItem == prevTestBFItem) {
+ eina_list_free(backwardList);
+ break;
+ }
+ itemsToPrint = eina_list_append(itemsToPrint, historyItem);
+ }
+
+ const Ewk_History_Item* currentItem = ewk_history_history_item_current_get(history);
+ if (currentItem)
+ itemsToPrint = eina_list_append(itemsToPrint, currentItem);
+
+ Eina_List* forwardList = ewk_history_forward_list_get(history);
+ EINA_LIST_FREE(forwardList, historyItem) {
+ ASSERT(historyItem != prevTestBFItem);
+ itemsToPrint = eina_list_append(itemsToPrint, historyItem);
+ }
+
+ EINA_LIST_FREE(itemsToPrint, historyItem) {
+ dumpHistoryItem(static_cast<Ewk_History_Item*>(historyItem), historyItemIndent, historyItem == currentItem);
+ ewk_history_item_free(static_cast<Ewk_History_Item*>(historyItem));
+ }
+
+ printf("===============================================\n");
+}
+
+void dumpBackForwardListForWebViews()
+{
+ // Dump the back forward list of the main WebView first
+ dumpBackForwardListForWebView(browser->mainView());
+
+ Vector<Evas_Object*>::const_iterator it = browser->extraViews().begin();
+ for (; it != browser->extraViews().end(); ++it)
+ dumpBackForwardListForWebView(*it);
+}
diff --git a/Tools/DumpRenderTree/efl/DumpHistoryItem.h b/Tools/DumpRenderTree/efl/DumpHistoryItem.h
new file mode 100644
index 000000000..ea8afeaaf
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpHistoryItem.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef DumpHistoryItem_h
+#define DumpHistoryItem_h
+
+#include <Evas.h>
+
+void dumpBackForwardListForWebViews();
+
+#endif // DumpHistoryItem_h
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTree.cpp b/Tools/DumpRenderTree/efl/DumpRenderTree.cpp
new file mode 100644
index 000000000..bb8f7d2d7
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTree.cpp
@@ -0,0 +1,416 @@
+/*
+ * 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 "LayoutTestController.h"
+#include "NotImplemented.h"
+#include "PixelDumpSupport.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.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 <text/CString.h>
+#include <unistd.h>
+#include <wtf/OwnPtr.h>
+
+OwnPtr<DumpRenderTreeChrome> browser;
+Evas_Object* topLoadingFrame = 0;
+bool waitForPolicy = false;
+Ecore_Timer* waitToDumpWatchdog = 0;
+extern Ewk_History_Item* prevTestBFItem;
+
+// From the top-level DumpRenderTree.h
+RefPtr<LayoutTestController> gLayoutTestController;
+volatile bool done = false;
+
+static int dumpPixels = false;
+static int dumpTree = true;
+static int printSeparators = true;
+static int useX11Window = false;
+
+static String dumpFramesAsText(Evas_Object* frame)
+{
+ String result;
+
+ if (browser->mainFrame() != frame) {
+ result.append("\n--------\nFrame: '");
+ result.append(String::fromUTF8(ewk_frame_name_get(frame)));
+ result.append("'\n--------\n");
+ }
+
+ char* frameContents = ewk_frame_plain_text_get(frame);
+ result.append(String::fromUTF8(frameContents));
+ result.append("\n");
+ free(frameContents);
+
+ if (gLayoutTestController->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*)
+{
+ notImplemented();
+}
+
+static bool shouldLogFrameLoadDelegates(const String& pathOrURL)
+{
+ return pathOrURL.contains("loading/");
+}
+
+static bool shouldDumpAsText(const String& pathOrURL)
+{
+ return pathOrURL.contains("dumpAsText/");
+}
+
+static void sendPixelResultsEOF()
+{
+ puts("#EOF");
+ fflush(stdout);
+ fflush(stderr);
+}
+
+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, &dumpPixels, true},
+ {"tree", no_argument, &dumpTree, true},
+ {"gui", no_argument, &useX11Window, true},
+ {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 String getFinalTestURL(const String& testURL)
+{
+ const size_t hashSeparatorPos = testURL.find("'");
+ if (hashSeparatorPos != notFound)
+ return getFinalTestURL(testURL.left(hashSeparatorPos));
+
+ // 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://).
+ 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 String getExpectedPixelHash(const String& testURL)
+{
+ const size_t hashSeparatorPos = testURL.find("'");
+ return (hashSeparatorPos != notFound) ? testURL.substring(hashSeparatorPos + 1) : String();
+}
+
+static void createLayoutTestController(const String& testURL, const String& expectedPixelHash)
+{
+ gLayoutTestController =
+ LayoutTestController::create(std::string(testURL.utf8().data()),
+ std::string(expectedPixelHash.utf8().data()));
+
+ topLoadingFrame = 0;
+ done = false;
+
+ gLayoutTestController->setIconDatabaseEnabled(false);
+
+ if (shouldLogFrameLoadDelegates(testURL))
+ gLayoutTestController->setDumpFrameLoadCallbacks(true);
+
+ gLayoutTestController->setDeveloperExtrasEnabled(true);
+
+ if (shouldDumpAsText(testURL)) {
+ gLayoutTestController->setDumpAsText(true);
+ gLayoutTestController->setGeneratePixelResults(false);
+ }
+}
+
+static void runTest(const char* cTestPathOrURL)
+{
+ const String testPathOrURL = String::fromUTF8(cTestPathOrURL);
+ ASSERT(!testPathOrURL.isEmpty());
+
+ const String testURL = getFinalTestURL(testPathOrURL);
+ const String expectedPixelHash = getExpectedPixelHash(testPathOrURL);
+
+ browser->resetDefaultsToConsistentValues();
+ createLayoutTestController(testURL, expectedPixelHash);
+
+ WorkQueue::shared()->clear();
+ WorkQueue::shared()->setFrozen(false);
+
+ const bool isSVGW3CTest = testURL.contains("svg/W3C-SVG-1.1");
+ const int width = isSVGW3CTest ? 480 : LayoutTestController::maxViewWidth;
+ const int height = isSVGW3CTest ? 360 : LayoutTestController::maxViewHeight;
+ 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();
+
+ gLayoutTestController->closeWebInspector();
+ gLayoutTestController->setDeveloperExtrasEnabled(false);
+
+ ewk_view_uri_set(browser->mainView(), "about:blank");
+
+ gLayoutTestController.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") {
+ gLayoutTestController->setDumpAsText(true);
+ gLayoutTestController->setGeneratePixelResults(false);
+ }
+}
+
+static void dumpFrameContentsAsText(Evas_Object* frame)
+{
+ String result;
+ if (gLayoutTestController->dumpAsText())
+ result = dumpFramesAsText(frame);
+ else
+ result = DumpRenderTreeSupportEfl::renderTreeDump(frame);
+
+ printf("%s", result.utf8().data());
+}
+
+static bool shouldDumpFrameScrollPosition()
+{
+ return gLayoutTestController->dumpAsText() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive();
+}
+
+static bool shouldDumpPixelsAndCompareWithExpected()
+{
+ return dumpPixels && gLayoutTestController->generatePixelResults() && !gLayoutTestController->dumpDOMAsWebArchive() && !gLayoutTestController->dumpSourceAsWebArchive();
+}
+
+static bool shouldDumpBackForwardList()
+{
+ return gLayoutTestController->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()
+{
+ notImplemented();
+}
+
+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(gLayoutTestController->expectedPixelHash());
+
+ done = true;
+ ecore_main_loop_quit();
+}
+
+static Ecore_Evas* initEcoreEvas()
+{
+ Ecore_Evas* ecoreEvas = useX11Window ? ecore_evas_new(0, 0, 0, 800, 600, 0) : ecore_evas_buffer_new(800, 600);
+ 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;
+
+ 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 || (dumpPixels && dumpTree));
+ for (int i = optind; i != argc; ++i)
+ runTest(argv[i]);
+ }
+
+ ecoreEvas.clear();
+
+ shutdownEfl();
+ return EXIT_SUCCESS;
+}
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp
new file mode 100644
index 000000000..ce7a00d9f
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
+ * HOLDERS 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 "DumpRenderTreeChrome.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeView.h"
+#include "EventSender.h"
+#include "GCController.h"
+#include "LayoutTestController.h"
+#include "NotImplemented.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "WorkQueue.h"
+#include "ewk_private.h" // FIXME: create some WebCoreSupport/DumpRenderTree.cpp instead
+
+#include <EWebKit.h>
+#include <Ecore.h>
+#include <Eina.h>
+#include <Evas.h>
+#include <cstdio>
+#include <wtf/NotFound.h>
+
+PassOwnPtr<DumpRenderTreeChrome> DumpRenderTreeChrome::create(Evas* evas)
+{
+ OwnPtr<DumpRenderTreeChrome> chrome = adoptPtr(new DumpRenderTreeChrome(evas));
+
+ if (!chrome->initialize())
+ return nullptr;
+
+ return chrome.release();
+}
+
+DumpRenderTreeChrome::DumpRenderTreeChrome(Evas* evas)
+ : m_mainView(0)
+ , m_mainFrame(0)
+ , m_evas(evas)
+ , m_gcController(adoptPtr(new GCController))
+{
+}
+
+DumpRenderTreeChrome::~DumpRenderTreeChrome()
+{
+}
+
+Evas_Object* DumpRenderTreeChrome::createNewWindow()
+{
+ Evas_Object* newView = createView();
+
+ ewk_view_setting_scripts_can_open_windows_set(newView, EINA_TRUE);
+ ewk_view_setting_scripts_can_close_windows_set(newView, EINA_TRUE);
+
+ m_extraViews.append(newView);
+
+ return newView;
+}
+
+Evas_Object* DumpRenderTreeChrome::createView() const
+{
+ Evas_Object* view = drtViewAdd(m_evas);
+ if (!view)
+ return 0;
+
+ ewk_view_theme_set(view, DATA_DIR"/default.edj");
+
+ evas_object_smart_callback_add(view, "load,started", onLoadStarted, 0);
+ evas_object_smart_callback_add(view, "load,finished", onLoadFinished, 0);
+ evas_object_smart_callback_add(view, "title,changed", onTitleChanged, 0);
+ evas_object_smart_callback_add(view, "window,object,cleared", onWindowObjectCleared, m_gcController.get());
+ evas_object_smart_callback_add(view, "statusbar,text,set", onStatusbarTextSet, 0);
+ evas_object_smart_callback_add(view, "load,document,finished", onDocumentLoadFinished, 0);
+
+ return view;
+}
+
+void DumpRenderTreeChrome::removeWindow(Evas_Object* view)
+{
+ const size_t pos = m_extraViews.find(view);
+
+ if (pos == notFound)
+ return;
+
+ m_extraViews.remove(pos);
+ evas_object_del(view);
+}
+
+bool DumpRenderTreeChrome::initialize()
+{
+ DumpRenderTreeSupportEfl::setMockScrollbarsEnabled(true);
+
+ m_mainView = createView();
+ if (!m_mainView)
+ return false;
+
+ ewk_view_theme_set(m_mainView, DATA_DIR"/default.edj");
+
+ evas_object_name_set(m_mainView, "m_mainView");
+ evas_object_move(m_mainView, 0, 0);
+ evas_object_resize(m_mainView, 800, 600);
+ evas_object_layer_set(m_mainView, EVAS_LAYER_MAX);
+ evas_object_show(m_mainView);
+ evas_object_focus_set(m_mainView, EINA_TRUE);
+
+ m_mainFrame = ewk_view_frame_main_get(m_mainView);
+
+ return true;
+}
+
+Vector<Evas_Object*> DumpRenderTreeChrome::extraViews() const
+{
+ return m_extraViews;
+}
+
+Evas_Object* DumpRenderTreeChrome::mainFrame() const
+{
+ return m_mainFrame;
+}
+
+Evas_Object* DumpRenderTreeChrome::mainView() const
+{
+ return m_mainView;
+}
+
+void DumpRenderTreeChrome::resetDefaultsToConsistentValues()
+{
+ Vector<Evas_Object*>::iterator it = m_extraViews.begin();
+ for (; it != m_extraViews.end(); ++it)
+ evas_object_del(*it);
+ m_extraViews.clear();
+
+ ewk_settings_icon_database_clear();
+ ewk_settings_icon_database_path_set(0);
+
+ ewk_view_setting_private_browsing_set(mainView(), EINA_FALSE);
+ ewk_view_setting_spatial_navigation_set(mainView(), EINA_FALSE);
+ ewk_view_setting_enable_frame_flattening_set(mainView(), EINA_FALSE);
+ ewk_view_setting_application_cache_set(mainView(), EINA_TRUE);
+ ewk_view_setting_enable_scripts_set(mainView(), EINA_TRUE);
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_STANDARD, "Times");
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_MONOSPACE, "Courier");
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_SERIF, "Times");
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_SANS_SERIF, "Helvetica");
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_CURSIVE, "cursive");
+ ewk_view_font_family_name_set(mainView(), EWK_FONT_FAMILY_FANTASY, "fantasy");
+ ewk_view_setting_font_default_size_set(mainView(), 16);
+ ewk_view_setting_font_monospace_size_set(mainView(), 13);
+ ewk_view_setting_font_minimum_size_set(mainView(), 0);
+ ewk_view_setting_caret_browsing_set(mainView(), EINA_FALSE);
+ ewk_view_setting_page_cache_set(mainView(), EINA_FALSE);
+ ewk_view_setting_enable_auto_resize_window_set(mainView(), EINA_TRUE);
+ ewk_view_setting_enable_plugins_set(mainView(), EINA_TRUE);
+ ewk_view_setting_scripts_can_open_windows_set(mainView(), EINA_TRUE);
+ ewk_view_setting_scripts_can_close_windows_set(mainView(), EINA_TRUE);
+
+ ewk_view_zoom_set(mainView(), 1.0, 0, 0);
+ ewk_view_scale_set(mainView(), 1.0, 0, 0);
+
+ ewk_history_clear(ewk_view_history_get(mainView()));
+
+ ewk_cookies_clear();
+ ewk_cookies_policy_set(EWK_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
+
+ DumpRenderTreeSupportEfl::clearFrameName(mainFrame());
+ DumpRenderTreeSupportEfl::clearOpener(mainFrame());
+}
+
+// Smart Callbacks
+// ---------------
+
+void DumpRenderTreeChrome::onWindowObjectCleared(void* userData, Evas_Object*, void* eventInfo)
+{
+ Ewk_Window_Object_Cleared_Event* objectClearedInfo = static_cast<Ewk_Window_Object_Cleared_Event*>(eventInfo);
+ JSValueRef exception = 0;
+ ASSERT(gLayoutTestController);
+
+ GCController* gcController = static_cast<GCController*>(userData);
+ ASSERT(gcController);
+
+ gLayoutTestController->makeWindowObject(objectClearedInfo->context, objectClearedInfo->windowObject, &exception);
+ ASSERT(!exception);
+
+ gcController->makeWindowObject(objectClearedInfo->context, objectClearedInfo->windowObject, &exception);
+ ASSERT(!exception);
+
+ JSRetainPtr<JSStringRef> controllerName(JSStringCreateWithUTF8CString("eventSender"));
+ JSObjectSetProperty(objectClearedInfo->context, objectClearedInfo->windowObject,
+ controllerName.get(),
+ makeEventSender(objectClearedInfo->context, !DumpRenderTreeSupportEfl::frameParent(objectClearedInfo->frame)),
+ kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, 0);
+}
+
+void DumpRenderTreeChrome::onLoadStarted(void*, Evas_Object* view, void*)
+{
+ // FIXME: we actually need the frame related to this event
+ Evas_Object* frame = ewk_view_frame_main_get(view);
+
+ // Make sure we only set this once per test. If it gets cleared, and then set again, we might
+ // end up doing two dumps for one test.
+ if (!topLoadingFrame && !done)
+ topLoadingFrame = frame;
+}
+
+Eina_Bool DumpRenderTreeChrome::processWork(void* data)
+{
+ Evas_Object* frame = static_cast<Evas_Object*>(data);
+
+ if (WorkQueue::shared()->processWork() && !gLayoutTestController->waitToDump())
+ dump();
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+void DumpRenderTreeChrome::onLoadFinished(void*, Evas_Object* view, void*)
+{
+ // FIXME: we actually need the frame related to this event
+ Evas_Object* frame = ewk_view_frame_main_get(view);
+
+ if (topLoadingFrame != frame)
+ return;
+
+ topLoadingFrame = 0;
+
+ WorkQueue::shared()->setFrozen(true);
+ if (gLayoutTestController->waitToDump())
+ return;
+
+ if (WorkQueue::shared()->count())
+ ecore_idler_add(processWork, frame);
+ else
+ dump();
+}
+
+void DumpRenderTreeChrome::onStatusbarTextSet(void*, Evas_Object*, void* eventInfo)
+{
+ if (!gLayoutTestController->dumpStatusCallbacks())
+ return;
+
+ const char* statusbarText = static_cast<const char*>(eventInfo);
+ printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", statusbarText);
+}
+
+void DumpRenderTreeChrome::onTitleChanged(void*, Evas_Object*, void*)
+{
+ notImplemented();
+}
+
+void DumpRenderTreeChrome::onDocumentLoadFinished(void*, Evas_Object*, void* eventInfo)
+{
+ const Evas_Object* frame = static_cast<Evas_Object*>(eventInfo);
+ const String frameName(DumpRenderTreeSupportEfl::suitableDRTFrameName(frame));
+
+ if (!done && gLayoutTestController->dumpFrameLoadCallbacks())
+ printf("%s - didFinishDocumentLoadForFrame\n", frameName.utf8().data());
+ else if (!done) {
+ const unsigned pendingFrameUnloadEvents = DumpRenderTreeSupportEfl::pendingUnloadEventCount(frame);
+ if (pendingFrameUnloadEvents)
+ printf("%s - has %u onunload handler(s)\n", frameName.utf8().data(), pendingFrameUnloadEvents);
+ }
+}
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h
new file mode 100644
index 000000000..4ea991806
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTreeChrome.h
@@ -0,0 +1,80 @@
+/*
+ * 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
+ * HOLDERS 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.
+ */
+
+#ifndef DumpRenderTreeChrome_h
+#define DumpRenderTreeChrome_h
+
+#include "GCController.h"
+
+#include <Eina.h>
+#include <Evas.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+class DumpRenderTreeChrome {
+public:
+ ~DumpRenderTreeChrome();
+
+ static PassOwnPtr<DumpRenderTreeChrome> create(Evas*);
+
+ Evas_Object* createNewWindow();
+ void removeWindow(Evas_Object*);
+
+ Vector<Evas_Object*> extraViews() const;
+ Evas_Object* mainFrame() const;
+ Evas_Object* mainView() const;
+
+ void resetDefaultsToConsistentValues();
+
+private:
+ DumpRenderTreeChrome(Evas*);
+
+ Evas_Object* createView() const;
+ bool initialize();
+
+ Evas_Object* m_mainFrame;
+ Evas_Object* m_mainView;
+ Evas* m_evas;
+ OwnPtr<GCController> m_gcController;
+ Vector<Evas_Object*> m_extraViews;
+
+ // Smart callbacks
+ static void onWindowObjectCleared(void*, Evas_Object*, void*);
+ static void onLoadStarted(void*, Evas_Object*, void*);
+
+ static Eina_Bool processWork(void*);
+
+ static void onLoadFinished(void*, Evas_Object*, void*);
+
+ static void onStatusbarTextSet(void*, Evas_Object*, void*);
+
+ static void onTitleChanged(void*, Evas_Object*, void*);
+
+ static void onDocumentLoadFinished(void*, Evas_Object*, void*);
+};
+
+#endif // DumpRenderTreeChrome_h
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeEfl.h b/Tools/DumpRenderTree/efl/DumpRenderTreeEfl.h
new file mode 100644
index 000000000..43812b19b
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTreeEfl.h
@@ -0,0 +1,41 @@
+/*
+ * 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. Red istributions 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
+ * HOLDERS 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.
+ */
+
+#ifndef DumpRenderTreeEfl_h
+#define DumpRenderTreeEfl_h
+
+#include <Ecore.h>
+#include <Evas.h>
+#include <wtf/OwnPtr.h>
+
+class DumpRenderTreeChrome;
+
+extern OwnPtr<DumpRenderTreeChrome> browser;
+extern Evas_Object* topLoadingFrame;
+extern bool waitForPolicy;
+extern Ecore_Timer* waitToDumpWatchdog;
+
+#endif /* DumpRenderTreeEfl_h */
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp b/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp
new file mode 100644
index 000000000..938c3fbdb
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTreeView.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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. Red istributions 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 "DumpRenderTreeView.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeChrome.h"
+#include "LayoutTestController.h"
+#include <EWebKit.h>
+#include <Ecore.h>
+#include <Eina.h>
+#include <Evas.h>
+#include <cstdio>
+#include <cstdlib>
+
+using namespace std;
+
+static Ewk_View_Smart_Class gParentSmartClass = EWK_VIEW_SMART_CLASS_INIT_NULL;
+
+static void onConsoleMessage(Ewk_View_Smart_Data*, const char* message, unsigned int lineNumber, const char*)
+{
+ printf("CONSOLE MESSAGE: line %u: %s\n", lineNumber, message);
+}
+
+static void onJavaScriptAlert(Ewk_View_Smart_Data*, Evas_Object*, const char* message)
+{
+ printf("ALERT: %s\n", message);
+}
+
+static Eina_Bool onJavaScriptConfirm(Ewk_View_Smart_Data*, Evas_Object*, const char* message)
+{
+ printf("CONFIRM: %s\n", message);
+ return EINA_TRUE;
+}
+
+static Eina_Bool onJavaScriptPrompt(Ewk_View_Smart_Data*, Evas_Object*, const char* message, const char* defaultValue, char** value)
+{
+ printf("PROMPT: %s, default text: %s\n", message, defaultValue);
+ *value = strdup(defaultValue);
+ return EINA_TRUE;
+}
+
+static Evas_Object* onWindowCreate(Ewk_View_Smart_Data*, Eina_Bool, const Ewk_Window_Features*)
+{
+ return gLayoutTestController->canOpenWindows() ? browser->createNewWindow() : 0;
+}
+
+static Eina_Bool onWindowCloseDelayed(void* data)
+{
+ Evas_Object* view = static_cast<Evas_Object*>(data);
+ browser->removeWindow(view);
+ return EINA_FALSE;
+}
+
+static void onWindowClose(Ewk_View_Smart_Data* smartData)
+{
+ Evas_Object* view = smartData->self;
+ ecore_idler_add(onWindowCloseDelayed, view);
+}
+
+static bool shouldUseSingleBackingStore()
+{
+ const char* useSingleBackingStore = getenv("DRT_USE_SINGLE_BACKING_STORE");
+ return useSingleBackingStore && *useSingleBackingStore == '1';
+}
+
+static bool chooseAndInitializeAppropriateSmartClass(Ewk_View_Smart_Class* api)
+{
+ return shouldUseSingleBackingStore() ? ewk_view_single_smart_set(api) : ewk_view_tiled_smart_set(api);
+}
+
+Evas_Object* drtViewAdd(Evas* evas)
+{
+ static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("DRT_View");
+
+ if (!chooseAndInitializeAppropriateSmartClass(&api))
+ return 0;
+
+ if (EINA_UNLIKELY(!gParentSmartClass.sc.add))
+ ewk_view_base_smart_set(&gParentSmartClass);
+
+ api.add_console_message = onConsoleMessage;
+ api.run_javascript_alert = onJavaScriptAlert;
+ api.run_javascript_confirm = onJavaScriptConfirm;
+ api.run_javascript_prompt = onJavaScriptPrompt;
+ api.window_create = onWindowCreate;
+ api.window_close = onWindowClose;
+
+ return evas_object_smart_add(evas, evas_smart_class_new(&api.sc));
+}
diff --git a/Tools/DumpRenderTree/efl/DumpRenderTreeView.h b/Tools/DumpRenderTree/efl/DumpRenderTreeView.h
new file mode 100644
index 000000000..72ddab56d
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/DumpRenderTreeView.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 ProFUSION Embedded Systems. All rights reserved.
+ *
+ * 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. Red istributions 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.
+ */
+
+#ifndef DumpRenderTreeView_h
+#define DumpRenderTreeView_h
+
+#include <Evas.h>
+
+Evas_Object* drtViewAdd(Evas*);
+
+#endif // DumpRenderTreeView_h
diff --git a/Tools/DumpRenderTree/efl/EventSender.cpp b/Tools/DumpRenderTree/efl/EventSender.cpp
new file mode 100644
index 000000000..89130f00a
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/EventSender.cpp
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
+ * Copyright (C) 2009 Holger Hans Peter Freyther
+ * Copyright (C) 2010 Igalia S.L.
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "EventSender.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeChrome.h"
+#include "JSStringUtils.h"
+#include "NotImplemented.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "ewk_private.h"
+#include <EWebKit.h>
+#include <JavaScriptCore/JSObjectRef.h>
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/OpaqueJSString.h>
+#include <wtf/ASCIICType.h>
+#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
+
+static bool gDragMode;
+static int gTimeOffset = 0;
+
+static int gLastMousePositionX;
+static int gLastMousePositionY;
+static int gLastClickPositionX;
+static int gLastClickPositionY;
+static int gLastClickTimeOffset;
+static int gLastClickButton;
+static int gButtonCurrentlyDown;
+static int gClickCount;
+
+static const float zoomMultiplierRatio = 1.2f;
+
+// Key event location code defined in DOM Level 3.
+enum KeyLocationCode {
+ DomKeyLocationStandard,
+ DomKeyLocationLeft,
+ DomKeyLocationRight,
+ DomKeyLocationNumpad
+};
+
+enum EvasKeyModifier {
+ EvasKeyModifierNone = 0,
+ EvasKeyModifierControl = 1 << 0,
+ EvasKeyModifierShift = 1 << 1,
+ EvasKeyModifierAlt = 1 << 2,
+ EvasKeyModifierMeta = 1 << 3
+};
+
+enum EvasMouseButton {
+ EvasMouseButtonNone,
+ EvasMouseButtonLeft,
+ EvasMouseButtonMiddle,
+ EvasMouseButtonRight
+};
+
+enum EvasMouseEvent {
+ EvasMouseEventNone = 0,
+ EvasMouseEventDown = 1 << 0,
+ EvasMouseEventUp = 1 << 1,
+ EvasMouseEventMove = 1 << 2,
+ EvasMouseEventScrollUp = 1 << 3,
+ EvasMouseEventScrollDown = 1 << 4,
+ EvasMouseEventScrollLeft = 1 << 5,
+ EvasMouseEventScrollRight = 1 << 6,
+ EvasMouseEventClick = EvasMouseEventMove | EvasMouseEventDown | EvasMouseEventUp,
+};
+
+static void setEvasModifiers(Evas* evas, EvasKeyModifier modifiers)
+{
+ static const char* modifierNames[] = { "Control", "Shift", "Alt", "Super" };
+ for (unsigned modifier = 0; modifier < 4; ++modifier) {
+ if (modifiers & (1 << modifier))
+ evas_key_modifier_on(evas, modifierNames[modifier]);
+ else
+ evas_key_modifier_off(evas, modifierNames[modifier]);
+ }
+}
+
+static EvasMouseButton translateMouseButtonNumber(int eventSenderButtonNumber)
+{
+ static const EvasMouseButton translationTable[] = {
+ EvasMouseButtonLeft,
+ EvasMouseButtonMiddle,
+ EvasMouseButtonRight,
+ EvasMouseButtonMiddle // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
+ };
+ static const unsigned translationTableSize = sizeof(translationTable) / sizeof(translationTable[0]);
+
+ if (eventSenderButtonNumber < translationTableSize)
+ return translationTable[eventSenderButtonNumber];
+
+ return EvasMouseButtonLeft;
+}
+
+static bool sendMouseEvent(Evas* evas, EvasMouseEvent event, int buttonNumber, EvasKeyModifier modifiers)
+{
+ unsigned timeStamp = 0;
+
+ DumpRenderTreeSupportEfl::layoutFrame(browser->mainFrame());
+
+ setEvasModifiers(evas, modifiers);
+ if (event & EvasMouseEventMove)
+ evas_event_feed_mouse_move(evas, gLastMousePositionX, gLastMousePositionY, timeStamp++, 0);
+ if (event & EvasMouseEventDown)
+ evas_event_feed_mouse_down(evas, buttonNumber, EVAS_BUTTON_NONE, timeStamp++, 0);
+ if (event & EvasMouseEventUp)
+ evas_event_feed_mouse_up(evas, buttonNumber, EVAS_BUTTON_NONE, timeStamp++, 0);
+
+ const bool horizontal = !!(event & EvasMouseEventScrollLeft | event & EvasMouseEventScrollRight);
+ const bool vertical = !!(event & EvasMouseEventScrollUp | event & EvasMouseEventScrollDown);
+ if (vertical && horizontal) {
+ evas_event_feed_mouse_wheel(evas, 0, (event & EvasMouseEventScrollUp) ? 10 : -10, timeStamp, 0);
+ evas_event_feed_mouse_wheel(evas, 1, (event & EvasMouseEventScrollLeft) ? 10 : -10, timeStamp, 0);
+ } else if (vertical)
+ evas_event_feed_mouse_wheel(evas, 0, (event & EvasMouseEventScrollUp) ? 10 : -10, timeStamp, 0);
+ else if (horizontal)
+ evas_event_feed_mouse_wheel(evas, 1, (event & EvasMouseEventScrollLeft) ? 10 : -10, timeStamp, 0);
+
+ setEvasModifiers(evas, EvasKeyModifierNone);
+
+ return true;
+}
+
+static Eina_Bool sendClick(void*)
+{
+ return !!sendMouseEvent(evas_object_evas_get(browser->mainFrame()), EvasMouseEventClick, EvasMouseButtonLeft, EvasKeyModifierNone);
+}
+
+static JSValueRef scheduleAsynchronousClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ ecore_idler_add(sendClick, 0);
+ return JSValueMakeUndefined(context);
+}
+
+static void updateClickCount(int button)
+{
+ if (gLastClickPositionX != gLastMousePositionX
+ || gLastClickPositionY != gLastMousePositionY
+ || gLastClickButton != button
+ || gTimeOffset - gLastClickTimeOffset >= 1)
+ gClickCount = 1;
+ else
+ gClickCount++;
+}
+
+static EvasKeyModifier modifierFromJSValue(JSContextRef context, const JSValueRef value)
+{
+ JSRetainPtr<JSStringRef> jsKeyValue(Adopt, JSValueToStringCopy(context, value, 0));
+
+ if (equals(jsKeyValue, "ctrlKey") || equals(jsKeyValue, "addSelectionKey"))
+ return EvasKeyModifierControl;
+ if (equals(jsKeyValue, "shiftKey") || equals(jsKeyValue, "rangeSelectionKey"))
+ return EvasKeyModifierShift;
+ if (equals(jsKeyValue, "altKey"))
+ return EvasKeyModifierAlt;
+ if (equals(jsKeyValue, "metaKey"))
+ return EvasKeyModifierMeta;
+
+ return EvasKeyModifierNone;
+}
+
+static EvasKeyModifier modifiersFromJSValue(JSContextRef context, const JSValueRef modifiers)
+{
+ // The value may either be a string with a single modifier or an array of modifiers.
+ if (JSValueIsString(context, modifiers))
+ return modifierFromJSValue(context, modifiers);
+
+ JSObjectRef modifiersArray = JSValueToObject(context, modifiers, 0);
+ if (!modifiersArray)
+ return EvasKeyModifierNone;
+
+ unsigned modifier = 0;
+ int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, JSStringCreateWithUTF8CString("length"), 0), 0);
+ for (int i = 0; i < modifiersCount; ++i)
+ modifier |= static_cast<unsigned>(modifierFromJSValue(context, JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0)));
+ return static_cast<EvasKeyModifier>(modifier);
+}
+
+static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int button = 0;
+ if (argumentCount == 1) {
+ button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+ }
+
+ button = translateMouseButtonNumber(button);
+ // If the same mouse button is already in the down position don't send another event as it may confuse Xvfb.
+ if (gButtonCurrentlyDown == button)
+ return JSValueMakeUndefined(context);
+
+ updateClickCount(button);
+
+ EvasKeyModifier modifiers = argumentCount >= 2 ? modifiersFromJSValue(context, arguments[1]) : EvasKeyModifierNone;
+ if (!sendMouseEvent(evas_object_evas_get(browser->mainFrame()), EvasMouseEventDown, button, modifiers))
+ return JSValueMakeUndefined(context);
+
+ gButtonCurrentlyDown = button;
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ int button = 0;
+ if (argumentCount == 1) {
+ button = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+ }
+
+ gLastClickPositionX = gLastMousePositionX;
+ gLastClickPositionY = gLastMousePositionY;
+ gLastClickButton = gButtonCurrentlyDown;
+ gLastClickTimeOffset = gTimeOffset;
+ gButtonCurrentlyDown = 0;
+
+ EvasKeyModifier modifiers = argumentCount >= 2 ? modifiersFromJSValue(context, arguments[1]) : EvasKeyModifierNone;
+ sendMouseEvent(evas_object_evas_get(browser->mainFrame()), EvasMouseEventUp, translateMouseButtonNumber(button), modifiers);
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 2)
+ return JSValueMakeUndefined(context);
+
+ gLastMousePositionX = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+ gLastMousePositionY = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+
+ sendMouseEvent(evas_object_evas_get(browser->mainFrame()), EvasMouseEventMove, EvasMouseButtonNone, EvasKeyModifierNone);
+ return JSValueMakeUndefined(context);
+}
+
+static EvasMouseEvent evasMouseEventFromHorizontalAndVerticalOffsets(int horizontalOffset, int verticalOffset)
+{
+ unsigned mouseEvent = 0;
+
+ if (verticalOffset > 0)
+ mouseEvent |= EvasMouseEventScrollUp;
+ else if (verticalOffset < 0)
+ mouseEvent |= EvasMouseEventScrollDown;
+
+ if (horizontalOffset > 0)
+ mouseEvent |= EvasMouseEventScrollRight;
+ else if (horizontalOffset < 0)
+ mouseEvent |= EvasMouseEventScrollLeft;
+
+ return static_cast<EvasMouseEvent>(mouseEvent);
+}
+
+static JSValueRef mouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 2)
+ return JSValueMakeUndefined(context);
+
+ const int horizontal = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+ const int vertical = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+
+ sendMouseEvent(evas_object_evas_get(browser->mainFrame()), evasMouseEventFromHorizontalAndVerticalOffsets(horizontal, vertical), EvasMouseButtonNone, EvasKeyModifierNone);
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef continuousMouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ return JSValueMakeUndefined(context);
+}
+
+static const char* keyPadNameFromJSValue(JSStringRef character)
+{
+ if (equals(character, "leftArrow"))
+ return "KP_Left";
+ if (equals(character, "rightArrow"))
+ return "KP_Right";
+ if (equals(character, "upArrow"))
+ return "KP_Up";
+ if (equals(character, "downArrow"))
+ return "KP_Down";
+ if (equals(character, "pageUp"))
+ return "KP_Prior";
+ if (equals(character, "pageDown"))
+ return "KP_Next";
+ if (equals(character, "home"))
+ return "KP_Home";
+ if (equals(character, "end"))
+ return "KP_End";
+ if (equals(character, "insert"))
+ return "KP_Insert";
+ if (equals(character, "delete"))
+ return "KP_Delete";
+
+ return 0;
+}
+
+static const char* keyNameFromJSValue(JSStringRef character)
+{
+ if (equals(character, "leftArrow"))
+ return "Left";
+ if (equals(character, "rightArrow"))
+ return "Right";
+ if (equals(character, "upArrow"))
+ return "Up";
+ if (equals(character, "downArrow"))
+ return "Down";
+ if (equals(character, "pageUp"))
+ return "Prior";
+ if (equals(character, "pageDown"))
+ return "Next";
+ if (equals(character, "home"))
+ return "Home";
+ if (equals(character, "end"))
+ return "End";
+ if (equals(character, "insert"))
+ return "Insert";
+ if (equals(character, "delete"))
+ return "Delete";
+ if (equals(character, "printScreen"))
+ return "Print";
+ if (equals(character, "menu"))
+ return "Menu";
+ if (equals(character, "F1"))
+ return "F1";
+ if (equals(character, "F2"))
+ return "F2";
+ if (equals(character, "F3"))
+ return "F3";
+ if (equals(character, "F4"))
+ return "F4";
+ if (equals(character, "F5"))
+ return "F5";
+ if (equals(character, "F6"))
+ return "F6";
+ if (equals(character, "F7"))
+ return "F7";
+ if (equals(character, "F8"))
+ return "F8";
+ if (equals(character, "F9"))
+ return "F9";
+ if (equals(character, "F10"))
+ return "F10";
+ if (equals(character, "F11"))
+ return "F11";
+ if (equals(character, "F12"))
+ return "F12";
+
+ int charCode = JSStringGetCharactersPtr(character)[0];
+ if (charCode == '\n' || charCode == '\r')
+ return "Return";
+ if (charCode == '\t')
+ return "Tab";
+ if (charCode == '\x8')
+ return "BackSpace";
+
+ return 0;
+}
+
+static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
+ if (!view)
+ return JSValueMakeUndefined(context);
+
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ // handle location argument.
+ int location = DomKeyLocationStandard;
+ if (argumentCount > 2)
+ location = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
+
+ JSRetainPtr<JSStringRef> character(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+ if (exception && *exception)
+ return JSValueMakeUndefined(context);
+
+ // send the event
+ Evas* evas = evas_object_evas_get(view);
+ if (argumentCount >= 2)
+ setEvasModifiers(evas, modifiersFromJSValue(context, arguments[1]));
+
+ const CString cCharacter = character.get()->ustring().utf8();
+ const char* keyName = (location == DomKeyLocationNumpad) ? keyPadNameFromJSValue(character.get()) : keyNameFromJSValue(character.get());
+
+ if (!keyName)
+ keyName = cCharacter.data();
+
+ DumpRenderTreeSupportEfl::layoutFrame(browser->mainFrame());
+ evas_event_feed_key_down(evas, keyName, keyName, keyName, 0, 0, 0);
+ evas_event_feed_key_up(evas, keyName, keyName, keyName, 0, 1, 0);
+
+ setEvasModifiers(evas, EvasKeyModifierNone);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSValueRef scalePageByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 3)
+ return JSValueMakeUndefined(context);
+
+ Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
+ if (!view)
+ return JSValueMakeUndefined(context);
+
+ float scaleFactor = JSValueToNumber(context, arguments[0], exception);
+ float x = JSValueToNumber(context, arguments[1], exception);
+ float y = JSValueToNumber(context, arguments[2], exception);
+ ewk_view_scale_set(view, scaleFactor, x, y);
+
+ return JSValueMakeUndefined(context);
+}
+
+static JSStaticFunction staticFunctions[] = {
+ { "mouseScrollBy", mouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "continuousMouseScrollBy", continuousMouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scheduleAsynchronousClick", scheduleAsynchronousClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { "scalePageBy", scalePageByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+ { 0, 0, 0 }
+};
+
+static JSStaticValue staticValues[] = {
+ { 0, 0, 0, 0 }
+};
+
+static JSClassRef getClass(JSContextRef context)
+{
+ static JSClassRef eventSenderClass = 0;
+
+ if (!eventSenderClass) {
+ JSClassDefinition classDefinition = {
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ classDefinition.staticFunctions = staticFunctions;
+ classDefinition.staticValues = staticValues;
+
+ eventSenderClass = JSClassCreate(&classDefinition);
+ }
+
+ return eventSenderClass;
+}
+
+JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame)
+{
+ if (isTopFrame) {
+ gDragMode = true;
+
+ // Fly forward in time one second when the main frame loads. This will
+ // ensure that when a test begins clicking in the same location as
+ // a previous test, those clicks won't be interpreted as continuations
+ // of the previous test's click sequences.
+ gTimeOffset += 1000;
+
+ gLastMousePositionX = gLastMousePositionY = 0;
+ gLastClickPositionX = gLastClickPositionY = 0;
+ gLastClickTimeOffset = 0;
+ gLastClickButton = 0;
+ gButtonCurrentlyDown = 0;
+ gClickCount = 0;
+ }
+
+ return JSObjectMake(context, getClass(context), 0);
+}
diff --git a/Tools/DumpRenderTree/efl/EventSender.h b/Tools/DumpRenderTree/efl/EventSender.h
new file mode 100644
index 000000000..bded6552d
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/EventSender.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Holger Hans Peter Freyther
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
+ */
+
+#ifndef EventSender_h
+#define EventSender_h
+
+typedef const struct OpaqueJSContext* JSContextRef;
+typedef struct OpaqueJSValue* JSObjectRef;
+
+// The boolean parameter refers to whether this is being called from a top-level frame.
+JSObjectRef makeEventSender(JSContextRef, bool);
+
+#endif // EventSender_h
diff --git a/Tools/DumpRenderTree/efl/FontManagement.cpp b/Tools/DumpRenderTree/efl/FontManagement.cpp
new file mode 100644
index 000000000..4cf2fb69b
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/FontManagement.cpp
@@ -0,0 +1,132 @@
+/*
+ * 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 "FontManagement.h"
+
+#include <Ecore_File.h>
+#include <cstdio>
+#include <fontconfig/fontconfig.h>
+#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+static Vector<String> getFontDirectories()
+{
+ Vector<String> fontDirPaths;
+
+ fontDirPaths.append(String("/usr/share/fonts/TTF/"));
+ fontDirPaths.append(String("/usr/share/fonts/truetype/ttf-liberation/"));
+ fontDirPaths.append(String("/usr/share/fonts/liberation/"));
+ fontDirPaths.append(String("/usr/share/fonts/truetype/ttf-dejavu/"));
+ fontDirPaths.append(String("/usr/share/fonts/dejavu/"));
+ fontDirPaths.append(String("/usr/share/fonts/OTF/")); // MathML
+ fontDirPaths.append(String("/usr/share/fonts/opentype/stix/")); // MathML
+ fontDirPaths.append(String("/usr/share/fonts/stix/")); // MathML
+
+ return fontDirPaths;
+}
+
+static Vector<String> getFontFiles()
+{
+ Vector<String> fontFilePaths;
+
+ // Ahem is used by many layout tests.
+ fontFilePaths.append(String(FONTS_CONF_DIR "/AHEM____.TTF"));
+ // A font with no valid Fontconfig encoding to test https://bugs.webkit.org/show_bug.cgi?id=47452
+ fontFilePaths.append(String(FONTS_CONF_DIR "/FontWithNoValidEncoding.fon"));
+
+ for (int i = 1; i <= 9; i++) {
+ char fontPath[PATH_MAX];
+ snprintf(fontPath, PATH_MAX - 1,
+ FONTS_CONF_DIR "/../../fonts/WebKitWeightWatcher%i00.ttf", i);
+
+ fontFilePaths.append(String(fontPath));
+ }
+
+ return fontFilePaths;
+}
+
+static size_t addFontDirectories(const Vector<String>& fontDirectories, FcConfig* config)
+{
+ size_t addedDirectories = 0;
+
+ for (Vector<String>::const_iterator it = fontDirectories.begin();
+ it != fontDirectories.end(); ++it) {
+ const CString currentDirectory = (*it).utf8();
+ const char* path = currentDirectory.data();
+
+ if (ecore_file_is_dir(path)) {
+ if (!FcConfigAppFontAddDir(config, reinterpret_cast<const FcChar8*>(path))) {
+ fprintf(stderr, "Could not load font at %s!\n", path);
+ continue;
+ }
+
+ ++addedDirectories;
+ }
+ }
+
+ return addedDirectories;
+}
+
+static void addFontFiles(const Vector<String>& fontFiles, FcConfig* config)
+{
+ for (Vector<String>::const_iterator it = fontFiles.begin(); it != fontFiles.end(); ++it) {
+ const CString currentFile = (*it).utf8();
+ const char* path = currentFile.data();
+
+ if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(path)))
+ fprintf(stderr, "Could not load font at %s!\n", path);
+ }
+}
+
+void addFontsToEnvironment()
+{
+ FcInit();
+
+ // Load our configuration file, which sets up proper aliases for family
+ // names like sans, serif and monospace.
+ FcConfig* config = FcConfigCreate();
+ const char* fontConfigFilename = FONTS_CONF_DIR "/fonts.conf";
+ if (!FcConfigParseAndLoad(config, reinterpret_cast<const FcChar8*>(fontConfigFilename), true)) {
+ fprintf(stderr, "Couldn't load font configuration file from: %s\n", fontConfigFilename);
+ exit(1);
+ }
+
+ if (!addFontDirectories(getFontDirectories(), config)) {
+ fprintf(stderr, "None of the font directories could be added. Either install them "
+ "or file a bug at http://bugs.webkit.org if they are installed in "
+ "another location.\n");
+ exit(1);
+ }
+
+ addFontFiles(getFontFiles(), config);
+
+ if (!FcConfigSetCurrent(config)) {
+ fprintf(stderr, "Could not set the current font configuration!\n");
+ exit(1);
+ }
+}
+
diff --git a/Tools/DumpRenderTree/efl/FontManagement.h b/Tools/DumpRenderTree/efl/FontManagement.h
new file mode 100644
index 000000000..d497513ae
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/FontManagement.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#ifndef FontManagement_h
+#define FontManagement_h
+
+void addFontsToEnvironment();
+
+#endif // FontManagement_h
diff --git a/Tools/DumpRenderTree/efl/GCControllerEfl.cpp b/Tools/DumpRenderTree/efl/GCControllerEfl.cpp
new file mode 100644
index 000000000..1f55a5ce6
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/GCControllerEfl.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "GCController.h"
+
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "ewk_private.h"
+
+void GCController::collect() const
+{
+ DumpRenderTreeSupportEfl::garbageCollectorCollect();
+}
+
+void GCController::collectOnAlternateThread(bool waitUntilDone) const
+{
+ DumpRenderTreeSupportEfl::garbageCollectorCollectOnAlternateThread(waitUntilDone);
+}
+
+size_t GCController::getJSObjectCount() const
+{
+ return DumpRenderTreeSupportEfl::javaScriptObjectsCount();
+}
diff --git a/Tools/DumpRenderTree/efl/ImageDiff.cpp b/Tools/DumpRenderTree/efl/ImageDiff.cpp
new file mode 100644
index 000000000..754ecb22a
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/ImageDiff.cpp
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
+ * Copyright (C) 2010 Igalia S.L.
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Evas.h>
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <getopt.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+enum PixelComponent {
+ Red,
+ Green,
+ Blue,
+ Alpha
+};
+
+static OwnPtr<Ecore_Evas> gEcoreEvas;
+static double gTolerance = 0;
+
+static void abortWithErrorMessage(const char* errorMessage);
+
+static unsigned char* pixelFromImageData(unsigned char* imageData, int rowStride, int x, int y)
+{
+ return imageData + (y * rowStride) + (x << 2);
+}
+
+static Evas_Object* differenceImageFromDifferenceBuffer(Evas* evas, unsigned char* buffer, int width, int height)
+{
+ Evas_Object* image = evas_object_image_filled_add(evas);
+ if (!image)
+ abortWithErrorMessage("could not create difference image");
+
+ evas_object_image_size_set(image, width, height);
+ evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
+
+ unsigned char* diffPixels = static_cast<unsigned char*>(evas_object_image_data_get(image, EINA_TRUE));
+ const int rowStride = evas_object_image_stride_get(image);
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ unsigned char* diffPixel = pixelFromImageData(diffPixels, rowStride, x, y);
+ diffPixel[Red] = diffPixel[Green] = diffPixel[Blue] = *buffer++;
+ diffPixel[Alpha] = 0xff;
+ }
+ }
+
+ evas_object_image_data_set(image, diffPixels);
+
+ return image;
+}
+
+static float computeDistanceBetweenPixelComponents(unsigned char actualComponent, unsigned char baseComponent)
+{
+ return (actualComponent - baseComponent) / std::max<float>(255 - baseComponent, baseComponent);
+}
+
+static float computeDistanceBetweenPixelComponents(unsigned char* actualPixel, unsigned char* basePixel, PixelComponent component)
+{
+ return computeDistanceBetweenPixelComponents(actualPixel[component], basePixel[component]);
+}
+
+static float calculatePixelDifference(unsigned char* basePixel, unsigned char* actualPixel)
+{
+ const float red = computeDistanceBetweenPixelComponents(actualPixel, basePixel, Red);
+ const float green = computeDistanceBetweenPixelComponents(actualPixel, basePixel, Green);
+ const float blue = computeDistanceBetweenPixelComponents(actualPixel, basePixel, Blue);
+ const float alpha = computeDistanceBetweenPixelComponents(actualPixel, basePixel, Alpha);
+ return sqrtf(red * red + green * green + blue * blue + alpha * alpha) / 2.0f;
+}
+
+static float calculateDifference(Evas_Object* baselineImage, Evas_Object* actualImage, OwnPtr<Evas_Object>& differenceImage)
+{
+ int width, height, baselineWidth, baselineHeight;
+ evas_object_image_size_get(actualImage, &width, &height);
+ evas_object_image_size_get(baselineImage, &baselineWidth, &baselineHeight);
+
+ if (width != baselineWidth || height != baselineHeight) {
+ printf("Error, test and reference image have different sizes.\n");
+ return 100; // Completely different.
+ }
+
+ OwnArrayPtr<unsigned char> diffBuffer = adoptArrayPtr(new unsigned char[width * height]);
+ if (!diffBuffer)
+ abortWithErrorMessage("could not create difference buffer");
+
+ const int actualRowStride = evas_object_image_stride_get(actualImage);
+ const int baseRowStride = evas_object_image_stride_get(baselineImage);
+ unsigned numberOfDifferentPixels = 0;
+ float totalDistance = 0;
+ float maxDistance = 0;
+ unsigned char* actualPixels = static_cast<unsigned char*>(evas_object_image_data_get(actualImage, EINA_FALSE));
+ unsigned char* basePixels = static_cast<unsigned char*>(evas_object_image_data_get(baselineImage, EINA_FALSE));
+ unsigned char* currentDiffPixel = diffBuffer.get();
+
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ unsigned char* actualPixel = pixelFromImageData(actualPixels, actualRowStride, x, y);
+ unsigned char* basePixel = pixelFromImageData(basePixels, baseRowStride, x, y);
+
+ const float distance = calculatePixelDifference(basePixel, actualPixel);
+ *currentDiffPixel++ = static_cast<unsigned char>(distance * 255.0f);
+
+ if (distance >= 1.0f / 255.0f) {
+ ++numberOfDifferentPixels;
+ totalDistance += distance;
+ maxDistance = std::max<float>(maxDistance, distance);
+ }
+ }
+ }
+
+ // When using evas_object_image_data_get(), a complementary evas_object_data_set() must be
+ // issued to balance the reference count, even if the image hasn't been changed.
+ evas_object_image_data_set(baselineImage, basePixels);
+ evas_object_image_data_set(actualImage, actualPixels);
+
+ // Compute the difference as a percentage combining both the number of
+ // different pixels and their difference amount i.e. the average distance
+ // over the entire image
+ float difference = 0;
+ if (numberOfDifferentPixels)
+ difference = 100.0f * totalDistance / (height * width);
+ if (difference <= gTolerance)
+ difference = 0;
+ else {
+ difference = roundf(difference * 100.0f) / 100.0f;
+ difference = std::max(difference, 0.01f); // round to 2 decimal places
+
+ differenceImage = adoptPtr(differenceImageFromDifferenceBuffer(evas_object_evas_get(baselineImage), diffBuffer.get(), width, height));
+ }
+
+ return difference;
+}
+
+static int getTemporaryFile(char *fileName, size_t fileNameLength)
+{
+ char* tempDirectory = getenv("TMPDIR");
+ if (!tempDirectory)
+ tempDirectory = getenv("TEMP");
+
+ if (tempDirectory)
+ snprintf(fileName, fileNameLength, "%s/ImageDiffXXXXXX.png", tempDirectory);
+ else {
+#if __linux__
+ strcpy(fileName, "/dev/shm/ImageDiffXXXXXX.png");
+ const int fileDescriptor = mkstemps(fileName, sizeof(".png") - 1);
+ if (fileDescriptor >= 0)
+ return fileDescriptor;
+#endif // __linux__
+
+ strcpy(fileName, "ImageDiffXXXXXX.png");
+ }
+
+ return mkstemps(fileName, sizeof(".png") - 1);
+}
+
+static void printImage(Evas_Object* image)
+{
+ char fileName[PATH_MAX];
+
+ const int tempImageFd = getTemporaryFile(fileName, PATH_MAX);
+ if (tempImageFd == -1)
+ abortWithErrorMessage("could not create temporary file");
+
+ evas_render(evas_object_evas_get(image));
+
+ if (evas_object_image_save(image, fileName, 0, 0)) {
+ struct stat fileInfo;
+ if (!stat(fileName, &fileInfo)) {
+ printf("Content-Length: %ld\n", fileInfo.st_size);
+ fflush(stdout);
+
+ unsigned char buffer[2048];
+ ssize_t bytesRead;
+ while ((bytesRead = read(tempImageFd, buffer, sizeof(buffer))) > 0)
+ write(1, buffer, bytesRead);
+ }
+ }
+ close(tempImageFd);
+ unlink(fileName);
+}
+
+static void printImageDifferences(Evas_Object* baselineImage, Evas_Object* actualImage)
+{
+ OwnPtr<Evas_Object> differenceImage;
+ const float difference = calculateDifference(baselineImage, actualImage, differenceImage);
+
+ if (difference > 0.0f) {
+ if (differenceImage)
+ printImage(differenceImage.get());
+
+ printf("diff: %01.2f%% failed\n", difference);
+ } else
+ printf("diff: %01.2f%% passed\n", difference);
+}
+
+static void resizeEcoreEvasIfNeeded(Evas_Object* image)
+{
+ int newWidth, newHeight;
+ evas_object_image_size_get(image, &newWidth, &newHeight);
+
+ int currentWidth, currentHeight;
+ ecore_evas_screen_geometry_get(gEcoreEvas.get(), 0, 0, &currentWidth, &currentHeight);
+
+ if (newWidth > currentWidth)
+ currentWidth = newWidth;
+ if (newHeight > currentHeight)
+ currentHeight = newHeight;
+
+ ecore_evas_resize(gEcoreEvas.get(), currentWidth, currentHeight);
+}
+
+static PassOwnPtr<Evas_Object> readImageFromStdin(Evas* evas, long imageSize)
+{
+ OwnArrayPtr<unsigned char> imageBuffer = adoptArrayPtr(new unsigned char[imageSize]);
+ if (!imageBuffer)
+ abortWithErrorMessage("cannot allocate image");
+
+ const size_t bytesRead = fread(imageBuffer.get(), 1, imageSize, stdin);
+ if (!bytesRead)
+ return PassOwnPtr<Evas_Object>();
+
+ Evas_Object* image = evas_object_image_filled_add(evas);
+ evas_object_image_colorspace_set(image, EVAS_COLORSPACE_ARGB8888);
+ evas_object_image_memfile_set(image, imageBuffer.get(), bytesRead, 0, 0);
+
+ resizeEcoreEvasIfNeeded(image);
+
+ return adoptPtr(image);
+}
+
+static bool parseCommandLineOptions(int argc, char** argv)
+{
+ static const option options[] = {
+ { "tolerance", required_argument, 0, 't' },
+ { 0, 0, 0, 0 }
+ };
+ int option;
+
+ while ((option = getopt_long(argc, (char* const*)argv, "t:", options, 0)) != -1) {
+ switch (option) {
+ case 't':
+ gTolerance = atof(optarg);
+ break;
+ case '?':
+ case ':':
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void shutdownEfl()
+{
+ ecore_evas_shutdown();
+ ecore_shutdown();
+ evas_shutdown();
+}
+
+static void abortWithErrorMessage(const char* errorMessage)
+{
+ shutdownEfl();
+
+ printf("Error, %s.\n", errorMessage);
+ exit(EXIT_FAILURE);
+}
+
+static Evas* initEfl()
+{
+ evas_init();
+ ecore_init();
+ ecore_evas_init();
+
+ gEcoreEvas = adoptPtr(ecore_evas_buffer_new(1, 1));
+ Evas* evas = ecore_evas_get(gEcoreEvas.get());
+ if (!evas)
+ abortWithErrorMessage("could not create Ecore_Evas buffer");
+
+ return evas;
+}
+
+int main(int argc, char* argv[])
+{
+ if (!parseCommandLineOptions(argc, argv))
+ return EXIT_FAILURE;
+
+ Evas* evas = initEfl();
+
+ OwnPtr<Evas_Object> actualImage;
+ OwnPtr<Evas_Object> baselineImage;
+
+ char buffer[2048];
+ while (fgets(buffer, sizeof(buffer), stdin)) {
+ char* contentLengthStart = strstr(buffer, "Content-Length: ");
+ if (!contentLengthStart)
+ continue;
+ long imageSize;
+ if (sscanf(contentLengthStart, "Content-Length: %ld", &imageSize) == 1) {
+ if (imageSize <= 0)
+ abortWithErrorMessage("image size must be specified");
+
+ if (!actualImage)
+ actualImage = readImageFromStdin(evas, imageSize);
+ else if (!baselineImage) {
+ baselineImage = readImageFromStdin(evas, imageSize);
+
+ printImageDifferences(baselineImage.get(), actualImage.get());
+
+ actualImage.clear();
+ baselineImage.clear();
+ }
+ }
+
+ fflush(stdout);
+ }
+
+ gEcoreEvas.clear(); // Make sure ecore_evas_free is called before the EFL are shut down
+
+ shutdownEfl();
+ return EXIT_SUCCESS;
+}
diff --git a/Tools/DumpRenderTree/efl/JSStringUtils.cpp b/Tools/DumpRenderTree/efl/JSStringUtils.cpp
new file mode 100644
index 000000000..19ca55736
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/JSStringUtils.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
+ * HOLDERS 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 "JSStringUtils.h"
+
+bool equals(JSStringRef jsString, const char* cString)
+{
+ return JSStringIsEqualToUTF8CString(jsString, cString);
+}
+
+bool equals(JSRetainPtr<JSStringRef> jsString, const char* cString)
+{
+ return equals(jsString.get(), cString);
+}
diff --git a/Tools/DumpRenderTree/efl/JSStringUtils.h b/Tools/DumpRenderTree/efl/JSStringUtils.h
new file mode 100644
index 000000000..04d7e0812
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/JSStringUtils.h
@@ -0,0 +1,38 @@
+/*
+ * 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 THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
+ * HOLDERS 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.
+ */
+
+
+#ifndef JSStringUtils_h
+#define JSStringUtils_h
+
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <JavaScriptCore/JSStringRef.h>
+
+bool equals(JSStringRef, const char*);
+bool equals(JSRetainPtr<JSStringRef>, const char*);
+
+#endif // JSStringUtils_h
+
diff --git a/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp b/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp
new file mode 100644
index 000000000..8dd0a37ca
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/LayoutTestControllerEfl.cpp
@@ -0,0 +1,785 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008 Nuanti Ltd.
+ * Copyright (C) 2009 Jan Michael Alonzo <jmalonzo@gmail.com>
+ * Copyright (C) 2009,2011 Collabora Ltd.
+ * Copyright (C) 2010 Joone Hur <joone@kldp.org>
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "LayoutTestController.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeChrome.h"
+#include "JSStringUtils.h"
+#include "NotImplemented.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "WorkQueue.h"
+#include "WorkQueueItem.h"
+#include "ewk_private.h"
+#include <EWebKit.h>
+#include <Ecore_File.h>
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/OpaqueJSString.h>
+#include <JavaScriptCore/wtf/text/WTFString.h>
+#include <KURL.h>
+#include <editing/FindOptions.h>
+#include <stdio.h>
+
+LayoutTestController::~LayoutTestController()
+{
+}
+
+void LayoutTestController::addDisallowedURL(JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::clearBackForwardList()
+{
+ notImplemented();
+}
+
+JSStringRef LayoutTestController::copyDecodedHostName(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+JSStringRef LayoutTestController::copyEncodedHostName(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+void LayoutTestController::dispatchPendingLoadRequests()
+{
+ // FIXME: Implement for testing fix for 6727495
+ notImplemented();
+}
+
+void LayoutTestController::display()
+{
+ displayWebView();
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::counterValueForElementById(JSStringRef id)
+{
+ const Evas_Object* mainFrame = browser->mainFrame();
+ const String counterValue(DumpRenderTreeSupportEfl::counterValueByElementId(mainFrame, id->ustring().utf8().data()));
+ return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(counterValue.utf8().data()));
+}
+
+void LayoutTestController::keepWebHistory()
+{
+ notImplemented();
+}
+
+JSValueRef LayoutTestController::computedStyleIncludingVisitedInfo(JSContextRef context, JSValueRef)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+JSValueRef LayoutTestController::nodesFromRect(JSContextRef context, JSValueRef, int, int, unsigned, unsigned, unsigned, unsigned, bool)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::layerTreeAsText() const
+{
+ notImplemented();
+ return JSRetainPtr<JSStringRef>(Adopt, JSStringCreateWithUTF8CString(""));
+}
+
+int LayoutTestController::pageNumberForElementById(JSStringRef id, float pageWidth, float pageHeight)
+{
+ return DumpRenderTreeSupportEfl::numberOfPagesForElementId(browser->mainFrame(), id->ustring().utf8().data(), pageWidth, pageHeight);
+}
+
+int LayoutTestController::numberOfPages(float pageWidth, float pageHeight)
+{
+ return DumpRenderTreeSupportEfl::numberOfPages(browser->mainFrame(), pageWidth, pageHeight);
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::pageProperty(const char*, int) const
+{
+ notImplemented();
+ return 0;
+}
+
+bool LayoutTestController::isPageBoxVisible(int) const
+{
+ notImplemented();
+ return false;
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::pageSizeAndMarginsInPixels(int, int, int, int, int, int, int) const
+{
+ notImplemented();
+ return 0;
+}
+
+size_t LayoutTestController::webHistoryItemCount()
+{
+ const Ewk_History* history = ewk_view_history_get(browser->mainView());
+ if (!history)
+ return -1;
+
+ return ewk_history_back_list_length(history) + ewk_history_forward_list_length(history);
+}
+
+unsigned LayoutTestController::workerThreadCount() const
+{
+ return DumpRenderTreeSupportEfl::workerThreadCount();
+}
+
+void LayoutTestController::notifyDone()
+{
+ if (m_waitToDump && !topLoadingFrame && !WorkQueue::shared()->count())
+ dump();
+ m_waitToDump = false;
+ waitForPolicy = false;
+}
+
+JSStringRef LayoutTestController::pathToLocalResource(JSContextRef context, JSStringRef url)
+{
+ // Function introduced in r28690. This may need special-casing on Windows.
+ return JSStringRetain(url); // Do nothing on Unix.
+}
+
+void LayoutTestController::queueLoad(JSStringRef url, JSStringRef target)
+{
+ WebCore::KURL baseURL(WebCore::KURL(), String::fromUTF8(ewk_frame_uri_get(browser->mainFrame())));
+ WebCore::KURL absoluteURL(baseURL, WTF::String(url->characters(), url->length()));
+
+ JSRetainPtr<JSStringRef> jsAbsoluteURL(
+ Adopt, JSStringCreateWithUTF8CString(absoluteURL.string().utf8().data()));
+
+ WorkQueue::shared()->queue(new LoadItem(jsAbsoluteURL.get(), target));
+}
+
+void LayoutTestController::setAcceptsEditing(bool acceptsEditing)
+{
+ ewk_view_editable_set(browser->mainView(), acceptsEditing);
+}
+
+void LayoutTestController::setAlwaysAcceptCookies(bool alwaysAcceptCookies)
+{
+ ewk_cookies_policy_set(alwaysAcceptCookies ? EWK_COOKIE_JAR_ACCEPT_ALWAYS : EWK_COOKIE_JAR_ACCEPT_NEVER);
+}
+
+void LayoutTestController::setCustomPolicyDelegate(bool, bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::waitForPolicyDelegate()
+{
+ waitForPolicy = true;
+ setWaitToDump(true);
+}
+
+void LayoutTestController::setScrollbarPolicy(JSStringRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::addOriginAccessWhitelistEntry(JSStringRef, JSStringRef, JSStringRef, bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::removeOriginAccessWhitelistEntry(JSStringRef, JSStringRef, JSStringRef, bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setMainFrameIsFirstResponder(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setTabKeyCyclesThroughElements(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setUseDashboardCompatibilityMode(bool)
+{
+ notImplemented();
+}
+
+static CString gUserStyleSheet;
+static bool gUserStyleSheetEnabled = true;
+
+void LayoutTestController::setUserStyleSheetEnabled(bool flag)
+{
+ gUserStyleSheetEnabled = flag;
+ ewk_view_setting_user_stylesheet_set(browser->mainView(), flag ? gUserStyleSheet.data() : 0);
+}
+
+void LayoutTestController::setUserStyleSheetLocation(JSStringRef path)
+{
+ gUserStyleSheet = path->ustring().utf8();
+
+ if (gUserStyleSheetEnabled)
+ setUserStyleSheetEnabled(true);
+}
+
+void LayoutTestController::setValueForUser(JSContextRef, JSValueRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setViewModeMediaFeature(JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setWindowIsKey(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setSmartInsertDeleteEnabled(bool)
+{
+ notImplemented();
+}
+
+static Eina_Bool waitToDumpWatchdogFired(void*)
+{
+ waitToDumpWatchdog = 0;
+ gLayoutTestController->waitToDumpWatchdogTimerFired();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+void LayoutTestController::setWaitToDump(bool waitUntilDone)
+{
+ static const double timeoutSeconds = 30;
+
+ m_waitToDump = waitUntilDone;
+ if (m_waitToDump && !waitToDumpWatchdog)
+ waitToDumpWatchdog = ecore_timer_add(timeoutSeconds, waitToDumpWatchdogFired, 0);
+}
+
+int LayoutTestController::windowCount()
+{
+ return browser->extraViews().size() + 1; // + 1 for the main view.
+}
+
+void LayoutTestController::setPrivateBrowsingEnabled(bool flag)
+{
+ ewk_view_setting_private_browsing_set(browser->mainView(), flag);
+}
+
+void LayoutTestController::setJavaScriptCanAccessClipboard(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setXSSAuditorEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setFrameFlatteningEnabled(bool flag)
+{
+ ewk_view_setting_enable_frame_flattening_set(browser->mainView(), flag);
+}
+
+void LayoutTestController::setSpatialNavigationEnabled(bool flag)
+{
+ ewk_view_setting_spatial_navigation_set(browser->mainView(), flag);
+}
+
+void LayoutTestController::setAllowUniversalAccessFromFileURLs(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setAllowFileAccessFromFileURLs(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setAuthorAndUserStylesEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setAutofilled(JSContextRef, JSValueRef, bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::disableImageLoading()
+{
+ // FIXME: Implement for testing fix for https://bugs.webkit.org/show_bug.cgi?id=27896
+ // Also need to make sure image loading is re-enabled for each new test.
+ notImplemented();
+}
+
+void LayoutTestController::setMockDeviceOrientation(bool, double, bool, double, bool, double)
+{
+ // FIXME: Implement for DeviceOrientation layout tests.
+ // See https://bugs.webkit.org/show_bug.cgi?id=30335.
+ notImplemented();
+}
+
+void LayoutTestController::setMockGeolocationPosition(double, double, double)
+{
+ // FIXME: Implement for Geolocation layout tests.
+ // See https://bugs.webkit.org/show_bug.cgi?id=28264.
+ notImplemented();
+}
+
+void LayoutTestController::setMockGeolocationError(int, JSStringRef)
+{
+ // FIXME: Implement for Geolocation layout tests.
+ // See https://bugs.webkit.org/show_bug.cgi?id=28264.
+ notImplemented();
+}
+
+void LayoutTestController::setGeolocationPermission(bool allow)
+{
+ // FIXME: Implement for Geolocation layout tests.
+ setGeolocationPermissionCommon(allow);
+}
+
+int LayoutTestController::numberOfPendingGeolocationPermissionRequests()
+{
+ // FIXME: Implement for Geolocation layout tests.
+ return -1;
+}
+
+void LayoutTestController::addMockSpeechInputResult(JSStringRef, double, JSStringRef)
+{
+ // FIXME: Implement for speech input layout tests.
+ // See https://bugs.webkit.org/show_bug.cgi?id=39485.
+ notImplemented();
+}
+
+void LayoutTestController::startSpeechInput(JSContextRef inputElement)
+{
+ // FIXME: Implement for speech input layout tests.
+ // See https://bugs.webkit.org/show_bug.cgi?id=39485.
+ notImplemented();
+}
+
+void LayoutTestController::setIconDatabaseEnabled(bool enabled)
+{
+ ewk_settings_icon_database_path_set(0);
+
+ if (!enabled)
+ return;
+
+ String databasePath;
+ const char* tempDir = getenv("TMPDIR");
+
+ if (tempDir)
+ databasePath = String::fromUTF8(tempDir);
+ else if (tempDir = getenv("TEMP"))
+ databasePath = String::fromUTF8(tempDir);
+ else
+ databasePath = String::fromUTF8("/tmp");
+
+ databasePath.append("/DumpRenderTree/IconDatabase");
+
+ if (ecore_file_mkpath(databasePath.utf8().data()))
+ ewk_settings_icon_database_path_set(databasePath.utf8().data());
+}
+
+void LayoutTestController::setJavaScriptProfilingEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setSelectTrailingWhitespaceEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setPopupBlockingEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setPluginsEnabled(bool flag)
+{
+ ewk_view_setting_enable_plugins_set(browser->mainView(), flag);
+}
+
+bool LayoutTestController::elementDoesAutoCompleteForElementWithId(JSStringRef)
+{
+ notImplemented();
+ return false;
+}
+
+void LayoutTestController::execCommand(JSStringRef, JSStringRef)
+{
+ notImplemented();
+}
+
+bool LayoutTestController::findString(JSContextRef context, JSStringRef target, JSObjectRef optionsArray)
+{
+ JSRetainPtr<JSStringRef> lengthPropertyName(Adopt, JSStringCreateWithUTF8CString("length"));
+ JSValueRef lengthValue = JSObjectGetProperty(context, optionsArray, lengthPropertyName.get(), 0);
+ if (!JSValueIsNumber(context, lengthValue))
+ return false;
+
+ WebCore::FindOptions options = 0;
+
+ const size_t length = static_cast<size_t>(JSValueToNumber(context, lengthValue, 0));
+ for (size_t i = 0; i < length; ++i) {
+ JSValueRef value = JSObjectGetPropertyAtIndex(context, optionsArray, i, 0);
+ if (!JSValueIsString(context, value))
+ continue;
+
+ JSRetainPtr<JSStringRef> optionName(Adopt, JSValueToStringCopy(context, value, 0));
+
+ if (equals(optionName, "CaseInsensitive"))
+ options |= WebCore::CaseInsensitive;
+ else if (equals(optionName, "AtWordStarts"))
+ options |= WebCore::AtWordStarts;
+ else if (equals(optionName, "TreatMedialCapitalAsWordStart"))
+ options |= WebCore::TreatMedialCapitalAsWordStart;
+ else if (equals(optionName, "Backwards"))
+ options |= WebCore::Backwards;
+ else if (equals(optionName, "WrapAround"))
+ options |= WebCore::WrapAround;
+ else if (equals(optionName, "StartInSelection"))
+ options |= WebCore::StartInSelection;
+ }
+
+ return DumpRenderTreeSupportEfl::findString(browser->mainView(), target->ustring().utf8().data(), options);
+}
+
+bool LayoutTestController::isCommandEnabled(JSStringRef name)
+{
+ return false;
+}
+
+void LayoutTestController::setCacheModel(int)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setPersistentUserStyleSheetLocation(JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::clearPersistentUserStyleSheet()
+{
+ notImplemented();
+}
+
+void LayoutTestController::clearAllApplicationCaches()
+{
+ ewk_settings_application_cache_clear();
+}
+
+void LayoutTestController::setApplicationCacheOriginQuota(unsigned long long)
+{
+ // FIXME: Implement to support application cache quotas.
+ notImplemented();
+}
+
+void LayoutTestController::clearApplicationCacheForOrigin(OpaqueJSString*)
+{
+ // FIXME: Implement to support deleting all application caches for an origin.
+ notImplemented();
+}
+
+long long LayoutTestController::localStorageDiskUsageForOrigin(JSStringRef)
+{
+ // FIXME: Implement to support getting disk usage in bytes for an origin.
+ notImplemented();
+ return 0;
+}
+
+JSValueRef LayoutTestController::originsWithApplicationCache(JSContextRef context)
+{
+ // FIXME: Implement to get origins that contain application caches.
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+long long LayoutTestController::applicationCacheDiskUsageForOrigin(JSStringRef)
+{
+ notImplemented();
+ return 0;
+}
+
+void LayoutTestController::clearAllDatabases()
+{
+ ewk_settings_web_database_clear();
+}
+
+void LayoutTestController::setDatabaseQuota(unsigned long long quota)
+{
+ ewk_settings_web_database_default_quota_set(quota);
+}
+
+JSValueRef LayoutTestController::originsWithLocalStorage(JSContextRef context)
+{
+ notImplemented();
+ return JSValueMakeUndefined(context);
+}
+
+void LayoutTestController::deleteAllLocalStorage()
+{
+ notImplemented();
+}
+
+void LayoutTestController::deleteLocalStorageForOrigin(JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::observeStorageTrackerNotifications(unsigned)
+{
+ notImplemented();
+}
+
+void LayoutTestController::syncLocalStorage()
+{
+ notImplemented();
+}
+
+void LayoutTestController::setDomainRelaxationForbiddenForURLScheme(bool, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::goBack()
+{
+ // FIXME: implement to enable loader/navigation-while-deferring-loads.html
+ notImplemented();
+}
+
+void LayoutTestController::setDefersLoading(bool)
+{
+ // FIXME: implement to enable loader/navigation-while-deferring-loads.html
+ notImplemented();
+}
+
+void LayoutTestController::setAppCacheMaximumSize(unsigned long long size)
+{
+ ewk_settings_application_cache_max_quota_set(size);
+}
+
+bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId)
+{
+ return DumpRenderTreeSupportEfl::pauseAnimation(browser->mainFrame(), animationName->ustring().utf8().data(), elementId->ustring().utf8().data(), time);
+}
+
+bool LayoutTestController::pauseTransitionAtTimeOnElementWithId(JSStringRef propertyName, double time, JSStringRef elementId)
+{
+ return DumpRenderTreeSupportEfl::pauseTransition(browser->mainFrame(), propertyName->ustring().utf8().data(), elementId->ustring().utf8().data(), time);
+}
+
+bool LayoutTestController::sampleSVGAnimationForElementAtTime(JSStringRef animationId, double time, JSStringRef elementId)
+{
+ return DumpRenderTreeSupportEfl::pauseSVGAnimation(browser->mainFrame(), animationId->ustring().utf8().data(), elementId->ustring().utf8().data(), time);
+}
+
+unsigned LayoutTestController::numberOfActiveAnimations() const
+{
+ return DumpRenderTreeSupportEfl::activeAnimationsCount(browser->mainFrame());
+}
+
+void LayoutTestController::suspendAnimations() const
+{
+ DumpRenderTreeSupportEfl::suspendAnimations(browser->mainFrame());
+}
+
+void LayoutTestController::resumeAnimations() const
+{
+ DumpRenderTreeSupportEfl::resumeAnimations(browser->mainFrame());
+}
+
+void LayoutTestController::overridePreference(JSStringRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::addUserScript(JSStringRef, bool, bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::addUserStyleSheet(JSStringRef, bool)
+{
+ // FIXME: needs more investigation why userscripts/user-style-top-frame-only.html fails when allFrames is false.
+ notImplemented();
+}
+
+void LayoutTestController::setDeveloperExtrasEnabled(bool enabled)
+{
+ ewk_view_setting_enable_developer_extras_set(browser->mainView(), enabled);
+}
+
+void LayoutTestController::setAsynchronousSpellCheckingEnabled(bool)
+{
+ notImplemented();
+}
+
+void LayoutTestController::showWebInspector()
+{
+ notImplemented();
+}
+
+void LayoutTestController::closeWebInspector()
+{
+ notImplemented();
+}
+
+void LayoutTestController::evaluateInWebInspector(long, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::evaluateScriptInIsolatedWorld(unsigned, JSObjectRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::removeAllVisitedLinks()
+{
+ notImplemented();
+}
+
+bool LayoutTestController::callShouldCloseOnWebView()
+{
+ notImplemented();
+ return false;
+}
+
+void LayoutTestController::apiTestNewWindowDataLoadBaseURL(JSStringRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::apiTestGoToCurrentBackForwardItem()
+{
+ notImplemented();
+}
+
+void LayoutTestController::setWebViewEditable(bool)
+{
+ ewk_frame_editable_set(browser->mainFrame(), EINA_TRUE);
+}
+
+JSRetainPtr<JSStringRef> LayoutTestController::markerTextForListItem(JSContextRef, JSValueRef) const
+{
+ notImplemented();
+ return 0;
+}
+
+void LayoutTestController::authenticateSession(JSStringRef, JSStringRef, JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setEditingBehavior(const char*)
+{
+ notImplemented();
+}
+
+void LayoutTestController::abortModal()
+{
+ notImplemented();
+}
+
+bool LayoutTestController::hasSpellingMarker(int, int)
+{
+ notImplemented();
+ return false;
+}
+
+bool LayoutTestController::hasGrammarMarker(int, int)
+{
+ notImplemented();
+ return false;
+}
+
+void LayoutTestController::dumpConfigurationForViewport(int, int, int, int, int)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setSerializeHTTPLoads(bool)
+{
+ // FIXME: Implement if needed for https://bugs.webkit.org/show_bug.cgi?id=50758.
+ notImplemented();
+}
+
+void LayoutTestController::setMinimumTimerInterval(double)
+{
+ notImplemented();
+}
+
+void LayoutTestController::setTextDirection(JSStringRef)
+{
+ notImplemented();
+}
+
+void LayoutTestController::allowRoundingHacks()
+{
+ notImplemented();
+}
+
+void LayoutTestController::addChromeInputField()
+{
+ notImplemented();
+}
+
+void LayoutTestController::removeChromeInputField()
+{
+ notImplemented();
+}
+
+void LayoutTestController::focusWebView()
+{
+ notImplemented();
+}
+
+void LayoutTestController::setBackingScaleFactor(double)
+{
+ notImplemented();
+}
+
+void LayoutTestController::simulateDesktopNotificationClick(JSStringRef title)
+{
+}
diff --git a/Tools/DumpRenderTree/efl/PixelDumpSupportEfl.cpp b/Tools/DumpRenderTree/efl/PixelDumpSupportEfl.cpp
new file mode 100644
index 000000000..109374ec9
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/PixelDumpSupportEfl.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
+ * Copyright (C) 2010 Igalia S.L.
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "DumpRenderTreeChrome.h"
+#include "IntRect.h"
+#include "PixelDumpSupportCairo.h"
+#include "RefPtrCairo.h"
+#include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
+#include "ewk_private.h"
+
+PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool drawSelectionRect)
+{
+ Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(browser->mainView()));
+ Ewk_View_Private_Data* privateData = static_cast<Ewk_View_Private_Data*>(smartData->_priv);
+ const Evas_Object* mainFrame = browser->mainFrame();
+
+ int x, y, width, height;
+ if (!ewk_frame_visible_content_geometry_get(mainFrame, EINA_TRUE, &x, &y, &width, &height))
+ return 0;
+
+ RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height));
+ RefPtr<cairo_t> context = adoptRef(cairo_create(surface.get()));
+
+ const Eina_Rectangle rect = { x, y, width, height };
+ if (!ewk_view_paint(privateData, context.get(), &rect))
+ return 0;
+
+ if (drawSelectionRect) {
+ const WebCore::IntRect selectionRect = DumpRenderTreeSupportEfl::selectionRectangle(mainFrame);
+
+ if (!selectionRect.isEmpty()) {
+ cairo_set_line_width(context.get(), 1.0);
+ cairo_rectangle(context.get(), selectionRect.x(), selectionRect.y(), selectionRect.width(), selectionRect.height());
+ cairo_set_source_rgba(context.get(), 1.0, 0.0, 0.0, 1.0);
+ cairo_stroke(context.get());
+ }
+ }
+
+ return BitmapContext::createByAdoptingBitmapAndContext(0, context.release().leakRef());
+}
diff --git a/Tools/DumpRenderTree/efl/WorkQueueItemEfl.cpp b/Tools/DumpRenderTree/efl/WorkQueueItemEfl.cpp
new file mode 100644
index 000000000..356a6553c
--- /dev/null
+++ b/Tools/DumpRenderTree/efl/WorkQueueItemEfl.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2011 ProFUSION Embedded Systems
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "WorkQueueItem.h"
+
+#include "DumpRenderTree.h"
+#include "DumpRenderTreeChrome.h"
+
+#include <EWebKit.h>
+#include <JavaScriptCore/JSStringRef.h>
+#include <JavaScriptCore/OpaqueJSString.h>
+#include <JavaScriptCore/runtime/UString.h>
+#include <JavaScriptCore/wtf/text/CString.h>
+
+bool LoadItem::invoke() const
+{
+ Evas_Object* targetFrame;
+
+ if (!m_target->length())
+ targetFrame = browser->mainFrame();
+ else
+ targetFrame = ewk_frame_child_find(browser->mainFrame(), m_target->ustring().utf8().data());
+
+ ewk_frame_uri_set(targetFrame, m_url->ustring().utf8().data());
+
+ return true;
+}
+
+bool LoadHTMLStringItem::invoke() const
+{
+ if (!m_unreachableURL->length())
+ ewk_frame_contents_set(browser->mainFrame(), m_content->ustring().utf8().data(), 0, 0, 0, m_baseURL->ustring().utf8().data());
+ else
+ ewk_frame_contents_alternate_set(browser->mainFrame(), m_content->ustring().utf8().data(), 0, 0, 0, m_baseURL->ustring().utf8().data(), m_unreachableURL->ustring().utf8().data());
+
+ return true;
+}
+
+bool ReloadItem::invoke() const
+{
+ ewk_view_reload(browser->mainView());
+ return true;
+}
+
+bool ScriptItem::invoke() const
+{
+ return ewk_frame_script_execute(browser->mainFrame(), m_script->ustring().utf8().data());
+}
+
+bool BackForwardItem::invoke() const
+{
+ if (m_howFar == 1)
+ ewk_view_forward(browser->mainView());
+ else if (m_howFar == -1)
+ ewk_view_back(browser->mainView());
+ else
+ ewk_view_navigate(browser->mainView(), m_howFar);
+
+ return true;
+}