<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[212517] trunk/Tools</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/212517">212517</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2017-02-16 18:15:35 -0800 (Thu, 16 Feb 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Unreviewed, rolling out <a href="http://trac.webkit.org/projects/webkit/changeset/212514">r212514</a>.
https://bugs.webkit.org/show_bug.cgi?id=168489
broke test runner (Requested by alexchristensen on #webkit).
Reverted changeset:
"Remove EFL-specific files in Tools."
http://trac.webkit.org/changeset/212514
Patch by Commit Queue <commit-queue@webkit.org> on 2017-02-16</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li>trunk/Tools/ImageDiff/efl/</li>
<li><a href="#trunkToolsImageDiffeflImageDiffcpp">trunk/Tools/ImageDiff/efl/ImageDiff.cpp</a></li>
<li>trunk/Tools/MiniBrowser/efl/</li>
<li><a href="#trunkToolsMiniBrowsereflCMakeListstxt">trunk/Tools/MiniBrowser/efl/CMakeLists.txt</a></li>
<li><a href="#trunkToolsMiniBrowsereflmainc">trunk/Tools/MiniBrowser/efl/main.c</a></li>
<li><a href="#trunkToolsScriptsrunefltests">trunk/Tools/Scripts/run-efl-tests</a></li>
<li><a href="#trunkToolsScriptsupdatewebkitefllibs">trunk/Tools/Scripts/update-webkitefl-libs</a></li>
<li><a href="#trunkToolsScriptswebkitpyporteflpy">trunk/Tools/Scripts/webkitpy/port/efl.py</a></li>
<li><a href="#trunkToolsScriptswebkitpyportefl_unittestpy">trunk/Tools/Scripts/webkitpy/port/efl_unittest.py</a></li>
<li>trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/</li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2eflWKViewClientWebProcessCallbackscpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2eflWKViewClientWebProcessCallbacks_Bundlecpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks_Bundle.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2eflWKViewScrollTocpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewScrollTo.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2eflscrollTohtml">trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/scrollTo.html</a></li>
<li>trunk/Tools/TestWebKitAPI/efl/</li>
<li><a href="#trunkToolsTestWebKitAPIeflInjectedBundleControllercpp">trunk/Tools/TestWebKitAPI/efl/InjectedBundleController.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPIeflPlatformUtilitiescpp">trunk/Tools/TestWebKitAPI/efl/PlatformUtilities.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPIeflPlatformWebViewcpp">trunk/Tools/TestWebKitAPI/efl/PlatformWebView.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPIeflmaincpp">trunk/Tools/TestWebKitAPI/efl/main.cpp</a></li>
<li>trunk/Tools/WebKitTestRunner/InjectedBundle/efl/</li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleeflActivateFontsEflcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/efl/ActivateFontsEfl.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleeflFontManagementcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleeflFontManagementh">trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.h</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleeflInjectedBundleEflcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/efl/InjectedBundleEfl.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnerInjectedBundleeflTestRunnerEflcpp">trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp</a></li>
<li>trunk/Tools/WebKitTestRunner/efl/</li>
<li><a href="#trunkToolsWebKitTestRunnereflEventSenderProxyEflcpp">trunk/Tools/WebKitTestRunner/efl/EventSenderProxyEfl.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnereflPlatformWebViewEflcpp">trunk/Tools/WebKitTestRunner/efl/PlatformWebViewEfl.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnereflTestControllerEflcpp">trunk/Tools/WebKitTestRunner/efl/TestControllerEfl.cpp</a></li>
<li><a href="#trunkToolsWebKitTestRunnereflmaincpp">trunk/Tools/WebKitTestRunner/efl/main.cpp</a></li>
<li>trunk/Tools/efl/</li>
<li><a href="#trunkToolseflinstalldependencies">trunk/Tools/efl/install-dependencies</a></li>
<li><a href="#trunkToolsefljhbuildoptionalmodules">trunk/Tools/efl/jhbuild-optional.modules</a></li>
<li><a href="#trunkToolsefljhbuildmodules">trunk/Tools/efl/jhbuild.modules</a></li>
<li><a href="#trunkToolsefljhbuildrc">trunk/Tools/efl/jhbuildrc</a></li>
<li>trunk/Tools/efl/patches/</li>
<li><a href="#trunkToolseflpatchesevasfixbuildwithgiflib5patch">trunk/Tools/efl/patches/evas-fix-build-with-giflib5.patch</a></li>
<li><a href="#trunkToolseflpatchesfontconfigC11requiresaspacebetweenliteralandidentifierpatch">trunk/Tools/efl/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch</a></li>
<li><a href="#trunkToolseflpatchesgstlibavpatch">trunk/Tools/efl/patches/gst-libav.patch</a></li>
<li><a href="#trunkToolseflpatchesgstpluginsbasertprtcpbufferfixtypoinenumpatch">trunk/Tools/efl/patches/gst-plugins-base-rtp-rtcpbuffer-fix-typo-in-enum.patch</a></li>
<li><a href="#trunkToolseflpatchesgstpluginsgoodRevertqtdemuxexposestreamswithfirstmoofforfrpatch">trunk/Tools/efl/patches/gst-plugins-good-Revert-qtdemux-expose-streams-with-first-moof-for-fr.patch</a></li>
<li><a href="#trunkToolseflpatchesgstpluginsgoodusethetfdtdecodetimepatch">trunk/Tools/efl/patches/gst-plugins-good-use-the-tfdt-decode-time.patch</a></li>
<li><a href="#trunkToolseflpatchesopenwebrtcgstpluginsclangwarningfixpatch">trunk/Tools/efl/patches/openwebrtc-gst-plugins-clang-warning-fix.patch</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (212516 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-02-17 01:54:10 UTC (rev 212516)
+++ trunk/Tools/ChangeLog        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2017-02-16 Commit Queue <commit-queue@webkit.org>
+
+ Unreviewed, rolling out r212514.
+ https://bugs.webkit.org/show_bug.cgi?id=168489
+
+ broke test runner (Requested by alexchristensen on #webkit).
+
+ Reverted changeset:
+
+ "Remove EFL-specific files in Tools."
+ http://trac.webkit.org/changeset/212514
+
</ins><span class="cx"> 2017-02-16 Alex Christensen <achristensen@webkit.org>
</span><span class="cx">
</span><span class="cx"> Remove EFL-specific files in Tools.
</span></span></pre></div>
<a id="trunkToolsImageDiffeflImageDiffcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/ImageDiff/efl/ImageDiff.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ImageDiff/efl/ImageDiff.cpp         (rev 0)
+++ trunk/Tools/ImageDiff/efl/ImageDiff.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,365 @@
</span><ins>+/*
+ * 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 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/StdLibExtras.h>
+#include <wtf/efl/UniquePtrEfl.h>
+
+enum PixelComponent {
+ Red,
+ Green,
+ Blue,
+ Alpha
+};
+
+static EflUniquePtr<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, EflUniquePtr<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.
+ }
+
+ auto diffBuffer = std::make_unique<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 = EflUniquePtr<Evas_Object>(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) {
+ ssize_t bytesWritten = 0;
+ ssize_t count;
+ do {
+ if ((count = write(1, buffer + bytesWritten, bytesRead - bytesWritten)) <= 0)
+ break;
+ bytesWritten += count;
+ } while (bytesWritten < bytesRead);
+ }
+ }
+ }
+ close(tempImageFd);
+ unlink(fileName);
+}
+
+static void printImageDifferences(Evas_Object* baselineImage, Evas_Object* actualImage)
+{
+ EflUniquePtr<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 EflUniquePtr<Evas_Object> readImageFromStdin(Evas* evas, long imageSize)
+{
+ auto imageBuffer = std::make_unique<unsigned char[]>(imageSize);
+ if (!imageBuffer)
+ abortWithErrorMessage("cannot allocate image");
+
+ const size_t bytesRead = fread(imageBuffer.get(), 1, imageSize, stdin);
+ if (!bytesRead)
+ return nullptr;
+
+ 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 EflUniquePtr<Evas_Object>(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 = EflUniquePtr<Ecore_Evas>(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();
+
+ EflUniquePtr<Evas_Object> actualImage;
+ EflUniquePtr<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.reset();
+ baselineImage.reset();
+ }
+ }
+
+ fflush(stdout);
+ }
+
+ gEcoreEvas = nullptr; // Make sure ecore_evas_free is called before the EFL are shut down
+
+ shutdownEfl();
+ return EXIT_SUCCESS;
+}
</ins></span></pre></div>
<a id="trunkToolsMiniBrowsereflCMakeListstxt"></a>
<div class="addfile"><h4>Added: trunk/Tools/MiniBrowser/efl/CMakeLists.txt (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/efl/CMakeLists.txt         (rev 0)
+++ trunk/Tools/MiniBrowser/efl/CMakeLists.txt        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,70 @@
</span><ins>+set(MiniBrowser_DIR "${TOOLS_DIR}/MiniBrowser/efl")
+
+# Elementary is needed to build MiniBrowser
+find_package(Eldbus ${EFL_REQUIRED_VERSION} ${EFL_CONFIG_MODE})
+find_package(Elementary ${EFL_REQUIRED_VERSION} ${EFL_CONFIG_MODE})
+find_package(Ethumb ${EFL_REQUIRED_VERSION} ${EFL_CONFIG_MODE})
+find_package(EthumbClient ${EFL_REQUIRED_VERSION} ${EFL_CONFIG_MODE})
+
+set(MiniBrowser_SOURCES
+ ${MiniBrowser_DIR}/main.c
+)
+
+set(MiniBrowser_INCLUDE_DIRECTORIES
+ ${DERIVED_SOURCES_WEBKIT2_DIR}/include
+ ${WEBKIT2_DIR}/UIProcess/API/efl
+ ${WEBKIT2_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+)
+
+set(MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES
+ ${CAIRO_INCLUDE_DIRS}
+ ${ECORE_INCLUDE_DIRS}
+ ${ECORE_EVAS_INCLUDE_DIRS}
+ ${ECORE_CON_INCLUDE_DIRS}
+ ${ECORE_FILE_INCLUDE_DIRS}
+ ${ECORE_IMF_INCLUDE_DIRS}
+ ${ECORE_INPUT_INCLUDE_DIRS}
+ ${EDJE_INCLUDE_DIRS}
+ ${EET_INCLUDE_DIRS}
+ ${EO_INCLUDE_DIRS}
+ ${DBUS_INCLUDE_DIRS}
+ ${EFREET_INCLUDE_DIRS}
+ ${EINA_INCLUDE_DIRS}
+ ${ELDBUS_INCLUDE_DIRS}
+ ${ELEMENTARY_INCLUDE_DIRS}
+ ${ETHUMB_INCLUDE_DIRS}
+ ${ETHUMB_CLIENT_INCLUDE_DIRS}
+ ${EVAS_INCLUDE_DIRS}
+)
+
+set(MiniBrowser_LIBRARIES
+ JavaScriptCore
+ WebCore
+ WebKit2
+ ${CAIRO_LIBRARIES}
+ ${ECORE_LIBRARIES}
+ ${ECORE_EVAS_LIBRARIES}
+ ${ECORE_FILE_LIBRARIES}
+ ${EDJE_LIBRARIES}
+ ${EET_LIBRARIES}
+ ${EINA_LIBRARIES}
+ ${ELEMENTARY_LIBRARIES}
+ ${EO_LIBRARIES}
+ ${EVAS_LIBRARIES}
+ ${FONTCONFIG_LIBRARIES}
+ ${GLIB_LIBRARIES}
+ ${GLIB_GTHREAD_LIBRARIES}
+ ${LIBSOUP_LIBRARIES}
+ ${LIBXML2_LIBRARIES}
+ ${LIBXSLT_LIBRARIES} -lm
+ ${OPENGL_LIBRARIES}
+ ${SQLITE_LIBRARIES}
+)
+
+if (ELEMENTARY_FOUND)
+ include_directories(${MiniBrowser_INCLUDE_DIRECTORIES})
+ include_directories(SYSTEM ${MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES})
+ add_executable(MiniBrowser ${MiniBrowser_SOURCES})
+ target_link_libraries(MiniBrowser ${MiniBrowser_LIBRARIES})
+endif ()
</ins></span></pre></div>
<a id="trunkToolsMiniBrowsereflmainc"></a>
<div class="addfile"><h4>Added: trunk/Tools/MiniBrowser/efl/main.c (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/MiniBrowser/efl/main.c         (rev 0)
+++ trunk/Tools/MiniBrowser/efl/main.c        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,2536 @@
</span><ins>+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "EWebKit2.h"
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Ecore_Getopt.h>
+#include <Eet.h>
+#include <Eina.h>
+#include <Elementary.h>
+#include <Evas.h>
+
+extern int efreet_cache_update;
+
+static const char DEFAULT_URL[] = "http://www.ewebkit.org/";
+static const char APP_NAME[] = "EFL MiniBrowser";
+static const char JAVASCRIPT_SCHEME[] = "javascript:";
+static const char FILE_SCHEME[] = "file://";
+static const char HTTP_SCHEME[] = "http://";
+static const int TOOL_BAR_ICON_SIZE = 24;
+static const int TOOL_BAR_BUTTON_SIZE = 32;
+static const int SEARCH_FIELD_SIZE = 200;
+static const int SEARCH_BUTTON_SIZE = 30;
+static const int MAX_SEARCH_COUNT = 1000;
+static const double TOOLTIP_DELAY_SECONDS = 1.0;
+static const double LONGPRESS_INTERVAL_SECONDS = 1.5;
+static const double LIST_ITEM_HEIGHT = 24.35;
+
+static Eina_List *windows = NULL;
+static char *evas_engine_name = NULL;
+static char *user_agent_string = NULL;
+static char *extensions_path = NULL;
+static char *background_color_string = NULL;
+static Eina_Bool encoding_detector_enabled = EINA_FALSE;
+static Eina_Bool frame_flattening_enabled = EINA_FALSE;
+static Eina_Bool local_storage_enabled = EINA_TRUE;
+static Eina_Bool offline_web_application_cache_enabled = EINA_TRUE;
+static Eina_Bool fullscreen_enabled = EINA_FALSE;
+static Eina_Bool spell_checking_enabled = EINA_FALSE;
+static Eina_Bool web_security_enabled = EINA_TRUE;
+static Eina_Bool touch_events_enabled = EINA_FALSE;
+static Eina_Bool fixed_layout_enabled = EINA_TRUE;
+static Eina_Bool separated_process_enabled = EINA_FALSE;
+static Eina_Bool longpress_enabled = EINA_FALSE;
+static int window_width = 1000;
+static int window_height = 800;
+static int color_picker_width = 350;
+static int color_picker_height = 500;
+static int search_flags = EWK_FIND_OPTIONS_SHOW_HIGHLIGHT | EWK_FIND_OPTIONS_WRAP_AROUND | EWK_FIND_OPTIONS_CASE_INSENSITIVE;
+/* Default value of device_pixel_ratio is '0' so that we don't set custom device
+ * scale factor unless it's required by the User. */
+static double device_pixel_ratio = 0;
+static Eina_Bool legacy_behavior_enabled = EINA_FALSE;
+
+#define DEFAULT_ZOOM_LEVEL 5 // Set default zoom level to 1.0 (index 5 on zoomLevels).
+// The zoom values are chosen to be like in Mozilla Firefox 3.
+const static float zoomLevels[] = {0.3, 0.5, 0.67, 0.8, 0.9, 1.0, 1.1, 1.2, 1.33, 1.5, 1.7, 2.0, 2.4, 3.0};
+static int _log_domain_id = -1;
+
+#define INFO(...) EINA_LOG_DOM_INFO(_log_domain_id, __VA_ARGS__)
+#define ERROR(...) EINA_LOG_DOM_ERR(_log_domain_id, __VA_ARGS__)
+
+static Eina_Bool
+zoom_level_set(Evas_Object *webview, int level)
+{
+ if (level < 0 || level >= sizeof(zoomLevels) / sizeof(float))
+ return EINA_FALSE;
+
+ return ewk_view_page_zoom_set(webview, zoomLevels[level]);
+}
+
+static Ewk_View_Smart_Class *miniBrowserViewSmartClass()
+{
+ static Ewk_View_Smart_Class ewkViewClass = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("MiniBrowser_View");
+ return &ewkViewClass;
+}
+
+typedef struct _Tooltip_Information {
+ Ecore_Timer *show_timer;
+ Eina_Bool activated;
+ Eina_Bool text_set;
+ Eina_Bool shown;
+} Tooltip_Information;
+
+typedef struct _Color_Selector {
+ Ewk_Color_Picker *ewk_picker;
+ Evas_Object *elm_selector;
+ Evas_Object *elm_selector_window;
+} Color_Selector;
+
+typedef struct _Browser_Window {
+ Evas_Object *elm_window;
+ Evas_Object *ewk_view;
+ Evas_Object *horizontal_layout;
+ Evas_Object *vertical_layout;
+ Evas_Object *url_bar;
+ Evas_Object *back_button;
+ Evas_Object *forward_button;
+ struct {
+ Evas_Object *elm_menu;
+ Ewk_Popup_Menu *ewk_menu;
+ } popup;
+ struct {
+ Evas_Object *search_bar;
+ Evas_Object *search_field;
+ Evas_Object *search_field_count;
+ Evas_Object *backward_button;
+ Evas_Object *forward_button;
+ Evas_Object *search_case_check_box;
+ Evas_Object *search_word_start_check_box;
+ Evas_Object *close_button;
+ } search;
+ struct {
+ Evas_Object *history_box;
+ Evas_Object *history_list;
+ Eina_List *history_list_items;
+ } history;
+ int current_zoom_level;
+ Tooltip_Information tooltip;
+ Color_Selector color_selector;
+ struct {
+ Evas_Object *elm_menu;
+ Ewk_Context_Menu *ewk_menu;
+ } context_menu;
+} Browser_Window;
+
+typedef struct _File_Selector_Data {
+ Browser_Window* parent;
+ Evas_Object *elm_window;
+ Ewk_File_Chooser_Request *request;
+} File_Selector_Data;
+
+typedef struct _Auth_Data {
+ Evas_Object *popup;
+ Ewk_Auth_Request *request;
+ Evas_Object *username_entry;
+ Evas_Object *password_entry;
+} Auth_Data;
+
+static const Ecore_Getopt options = {
+ "MiniBrowser",
+ "%prog [options] [url]",
+ "0.0.1",
+ "(C)2012 Samsung Electronics\n (C)2012 Intel Corporation\n",
+ "",
+ "Test Web Browser using the Enlightenment Foundation Libraries (EFL) port of WebKit2",
+ EINA_TRUE, {
+ ECORE_GETOPT_STORE_STR
+ ('e', "engine", "Ecore-evas engine to use."),
+ ECORE_GETOPT_STORE_STR
+ ('s', "window-size", "Window size in following format (width)x(height)."),
+ ECORE_GETOPT_STORE_STR
+ ('u', "user-agent", "User agent to set."),
+ ECORE_GETOPT_STORE_STR
+ ('x', "extensions-path", "The path which extensions are stored."),
+ ECORE_GETOPT_STORE_DOUBLE
+ ('r', "device-pixel-ratio", "Ratio between the CSS units and device pixels."),
+ ECORE_GETOPT_CALLBACK_NOARGS
+ ('E', "list-engines", "List ecore-evas engines.",
+ ecore_getopt_callback_ecore_evas_list_engines, NULL),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('c', "encoding-detector", "Enable/disable encoding detector.", EINA_FALSE),
+ ECORE_GETOPT_STORE_STR
+ ('C', "background-color", "Background color of page. ex) -C=255:255:255:255"),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('f', "flattening", "Enable/disable frame flattening.", EINA_FALSE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('l', "local-storage", "Enable/disable HTML5 local storage.", EINA_TRUE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('o', "offline-web-application-cache", "Enable/disable offline web application cache.", EINA_TRUE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('F', "full-screen", "Start in full-screen.", EINA_FALSE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('t', "text-checking", "Enable/disable text spell checking.", EINA_FALSE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('T', "touch-events", "Enable/disable touch events.", EINA_FALSE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('L', "fixed-layout", "Enable/disable fixed layout.", EINA_TRUE),
+ ECORE_GETOPT_STORE_DEF_STR
+ ('p', "policy-cookies", "Cookies policy:\n always - always accept,\n never - never accept,\n no-third-party - don't accept third-party cookies.", "no-third-party"),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('w', "web-security", "enable/disable web security.", EINA_TRUE),
+ ECORE_GETOPT_STORE_DEF_BOOL
+ ('S', "separate-process", "Create new window in separated web process.", EINA_FALSE),
+ ECORE_GETOPT_VERSION
+ ('V', "version"),
+ ECORE_GETOPT_COPYRIGHT
+ ('R', "copyright"),
+ ECORE_GETOPT_HELP
+ ('h', "help"),
+ ECORE_GETOPT_SENTINEL
+ }
+};
+
+static Eina_Stringshare *_file_entry_dialog_show(Browser_Window *window, const char *label_tag, const char *default_text);
+static Browser_Window *window_create(Ewk_View_Configuration* configuration, int width, int height);
+static Ewk_View_Configuration* configuration();
+
+static Browser_Window *window_find_with_ewk_view(Evas_Object *ewk_view)
+{
+ Eina_List *l;
+ void *data;
+
+ if (!ewk_view)
+ return NULL;
+
+ EINA_LIST_FOREACH(windows, l, data) {
+ Browser_Window *window = (Browser_Window *)data;
+ if (window->ewk_view == ewk_view)
+ return window;
+ }
+ return NULL;
+}
+
+static Eina_Bool
+_tooltip_show(void *user_data)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ window->tooltip.show_timer = NULL;
+ elm_object_tooltip_show(window->elm_window);
+ window->tooltip.shown = EINA_TRUE;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+window_tooltip_hide(Browser_Window *window)
+{
+ if (window->tooltip.show_timer) {
+ ecore_timer_del(window->tooltip.show_timer);
+ window->tooltip.show_timer = NULL;
+ }
+
+ if (window->tooltip.shown) {
+ elm_object_tooltip_hide(window->elm_window);
+ window->tooltip.shown = EINA_FALSE;
+ }
+}
+
+static void
+window_tooltip_update(Browser_Window *window)
+{
+ window_tooltip_hide(window);
+
+ if (window->tooltip.activated && window->tooltip.text_set)
+ window->tooltip.show_timer = ecore_timer_add(TOOLTIP_DELAY_SECONDS, _tooltip_show, window);
+}
+
+static void
+_mouse_in_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ window->tooltip.activated = EINA_TRUE;
+ window_tooltip_update(window);
+}
+
+static void
+_mouse_move_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ window_tooltip_update((Browser_Window *)user_data);
+}
+
+static void
+_mouse_out_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ window->tooltip.activated = EINA_FALSE;
+ window_tooltip_update(window);
+}
+
+static void
+_mouse_wheel_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ const Evas_Modifier *mod = evas_key_modifier_get(e);
+ Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel *)event_info;
+ Eina_Bool shiftPressed = evas_key_modifier_is_set(mod, "Shift");
+ Eina_Bool ctrlPressed = evas_key_modifier_is_set(mod, "Control");
+
+ if (!shiftPressed && !ctrlPressed)
+ return;
+
+ /* navigate history or zoom web page based on mouse wheel scroll action with shift or control key */
+ if (shiftPressed) {
+ if (ev->z == -1 && ewk_view_forward_possible(ewk_view)) {
+ ewk_view_forward(ewk_view);
+ elm_object_disabled_set(window->forward_button, !ewk_view_forward_possible(ewk_view));
+ } else if (ev->z == 1 && ewk_view_back_possible(ewk_view)) {
+ ewk_view_back(ewk_view);
+ elm_object_disabled_set(window->back_button, !ewk_view_back_possible(ewk_view));
+ }
+ } else if (ctrlPressed) {
+ if (ev->z == -1 && zoom_level_set(ewk_view, window->current_zoom_level + 1)) {
+ window->current_zoom_level++;
+ INFO("Zoom in (Ctrl + 'scroll up') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
+ } else if (ev->z == 1 && zoom_level_set(ewk_view, window->current_zoom_level - 1)) {
+ window->current_zoom_level--;
+ INFO("Zoom out (Ctrl + 'scroll down') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
+ }
+ }
+}
+
+static void
+_window_resize_cb(void *user_data, Evas *e, Evas_Object *elm_window, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ if (!window) {
+ ERROR("Window is NULL.");
+ return;
+ }
+
+ if (window->context_menu.ewk_menu)
+ ewk_context_menu_hide(window->context_menu.ewk_menu);
+ if (window->popup.ewk_menu)
+ ewk_popup_menu_close(window->popup.ewk_menu);
+ if (window->popup.elm_menu)
+ elm_menu_close(window->popup.elm_menu);
+}
+
+static void
+update_view_favicon(Browser_Window *window, Evas_Object *icon)
+{
+ /* Remove previous icon from URL bar */
+ Evas_Object *old_icon = elm_object_part_content_unset(window->url_bar, "icon");
+ if (old_icon) {
+ evas_object_unref(old_icon);
+ evas_object_del(old_icon);
+ }
+
+ /* Show new icon in URL bar */
+ if (icon) {
+ evas_object_size_hint_min_set(icon, 32, 32);
+ elm_object_part_content_set(window->url_bar, "icon", icon);
+ evas_object_ref(icon);
+ }
+}
+
+static void
+_icon_changed_cb(Ewk_Favicon_Database *database, const char *url, void *user_data)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ Evas_Object *ewk_view = window->ewk_view;
+
+ if (strcmp(url, ewk_view_url_get(ewk_view)))
+ return;
+
+ Evas_Object *favicon = ewk_favicon_database_icon_get(database, url, evas_object_evas_get(ewk_view));
+ update_view_favicon(window, favicon);
+
+ if (favicon)
+ evas_object_unref(favicon);
+}
+
+static void window_free(Browser_Window *window)
+{
+ evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb);
+ evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb);
+ evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb);
+ evas_object_event_callback_del(window->ewk_view, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb);
+
+ evas_object_event_callback_del(window->elm_window, EVAS_CALLBACK_RESIZE, _window_resize_cb);
+
+ ewk_favicon_database_icon_change_callback_del(ewk_context_favicon_database_get(ewk_view_context_get(window->ewk_view)), _icon_changed_cb);
+
+ evas_object_del(window->ewk_view);
+ /* The elm_win will take care of freeing its children */
+ evas_object_del(window->elm_window);
+
+ if (window->tooltip.show_timer)
+ ecore_timer_del(window->tooltip.show_timer);
+
+ if (window->color_selector.elm_selector_window)
+ evas_object_del(window->color_selector.elm_selector_window);
+
+ free(window);
+}
+
+static void window_close(Browser_Window *window)
+{
+ windows = eina_list_remove(windows, window);
+ window_free(window);
+
+ if (!windows)
+ elm_exit();
+}
+
+static void
+search_icon_show(Browser_Window *window)
+{
+ Evas_Object *icon = elm_icon_add(window->elm_window);
+ elm_icon_standard_set(icon, "edit-find");
+ elm_object_part_content_set(window->search.search_field, "icon", icon);
+ evas_object_size_hint_min_set(icon, 20, 20);
+ evas_object_size_hint_max_set(icon, 20, 20);
+ elm_entry_icon_visible_set(window->search.search_field, EINA_TRUE);
+ evas_object_show(icon);
+}
+
+static void
+search_box_show(Browser_Window *window)
+{
+ evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
+
+ search_icon_show(window);
+ evas_object_show(window->search.search_bar);
+ evas_object_show(window->search.search_field);
+ evas_object_show(window->search.search_field_count);
+ evas_object_show(window->search.backward_button);
+ evas_object_show(window->search.forward_button);
+ evas_object_show(window->search.search_case_check_box);
+ evas_object_show(window->search.search_word_start_check_box);
+ evas_object_show(window->search.close_button);
+
+ /* Grab focus from the view */
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(window->search.search_field, EINA_TRUE);
+}
+
+static void
+search_box_hide(Browser_Window *window)
+{
+ ewk_view_text_find_highlight_clear(window->ewk_view);
+
+ evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
+ evas_object_hide(window->search.search_bar);
+ evas_object_hide(window->search.search_field);
+ evas_object_hide(window->search.search_field_count);
+ evas_object_hide(window->search.backward_button);
+ evas_object_hide(window->search.forward_button);
+ evas_object_hide(window->search.search_case_check_box);
+ evas_object_hide(window->search.search_word_start_check_box);
+ evas_object_hide(window->search.close_button);
+
+ /* Give focus back to the view */
+ elm_object_focus_set(window->search.search_field, EINA_FALSE);
+ evas_object_focus_set(window->ewk_view, EINA_TRUE);
+}
+
+static void
+history_list_hide(Browser_Window *window)
+{
+ /* Hide history list */
+ evas_object_hide(window->history.history_box);
+ evas_object_hide(window->history.history_list);
+
+ /* Dereference the list items and clear the history list */
+ void *data;
+ EINA_LIST_FREE(window->history.history_list_items, data) {
+ ewk_object_unref(data);
+ }
+
+ elm_genlist_clear(window->history.history_list);
+
+ /* Give focus back to the view */
+ elm_object_focus_set(window->history.history_box, EINA_FALSE);
+ elm_object_focus_set(window->history.history_list, EINA_FALSE);
+ evas_object_focus_set(window->ewk_view, EINA_TRUE);
+
+ /* Reset flags */
+ longpress_enabled = EINA_FALSE;
+}
+
+static void save_page_contents_callback(Ewk_Page_Contents_Type type, const char *data, void *user_data)
+{
+ Eet_File *ef;
+ Eina_Stringshare *fileName = (Eina_Stringshare *)user_data;
+
+ if (!eina_str_has_extension(fileName, ".mht")) {
+ Eina_Strbuf *fileNameWithMht = eina_strbuf_new();
+ eina_strbuf_append_printf(fileNameWithMht, "%s.mht", fileName);
+ ef = eet_open(eina_strbuf_string_get(fileNameWithMht), EET_FILE_MODE_WRITE);
+ INFO("Saving file to: %s", eina_strbuf_string_get(fileNameWithMht));
+ eina_strbuf_free(fileNameWithMht);
+ } else {
+ ef = eet_open(fileName, EET_FILE_MODE_WRITE);
+ INFO("Saving file to: %s", fileName);
+ }
+
+ if (!ef) {
+ ERROR("Could not create File");
+ return;
+ }
+
+ eet_write(ef, "MHTML data", data, strlen(data), 0 /* compress */);
+ eet_close(ef);
+ INFO("SUCCESS: saved.");
+
+ eina_stringshare_del(fileName);
+}
+
+static void
+script_execute_callback(Evas_Object *ewk_view, const char *return_value, void *user_data)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ Eina_Strbuf *text_buffer = eina_strbuf_new();
+
+ if (return_value) {
+ eina_strbuf_append(text_buffer, return_value);
+ INFO("selected text is: %s", eina_strbuf_string_get(text_buffer));
+ elm_entry_entry_set(window->search.search_field, eina_strbuf_string_get(text_buffer));
+ }
+ eina_strbuf_free(text_buffer);
+ search_box_show(window);
+}
+
+static void
+toggle_window_fullscreen(Browser_Window *window, Eina_Bool isFullScreen)
+{
+ if (isFullScreen) {
+ evas_object_hide(window->horizontal_layout);
+ elm_box_unpack(window->vertical_layout, window->horizontal_layout);
+ elm_win_fullscreen_set(window->elm_window, EINA_TRUE);
+ } else {
+ elm_win_fullscreen_set(window->elm_window, EINA_FALSE);
+ elm_box_pack_start(window->vertical_layout, window->horizontal_layout);
+ evas_object_show(window->horizontal_layout);
+ }
+}
+
+static void
+_key_down_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ Evas_Event_Key_Down *ev = (Evas_Event_Key_Down*) event_info;
+
+ static const char *encodings[] = {
+ "ISO-8859-1",
+ "UTF-8",
+ NULL
+ };
+ static int currentEncoding = -1;
+ const Evas_Modifier *mod = evas_key_modifier_get(e);
+ Eina_Bool ctrlPressed = evas_key_modifier_is_set(mod, "Control");
+ Eina_Bool altPressed = evas_key_modifier_is_set(mod, "Alt");
+ Eina_Bool shiftPressed = evas_key_modifier_is_set(mod, "Shift");
+
+ if (!strcmp(ev->key, "Left") && altPressed) {
+ INFO("Back (Alt+Left) was pressed");
+ if (!ewk_view_back(ewk_view))
+ INFO("Back ignored: No back history");
+ } else if (!strcmp(ev->key, "Right") && altPressed) {
+ INFO("Forward (Alt+Right) was pressed");
+ if (!ewk_view_forward(ewk_view))
+ INFO("Forward ignored: No forward history");
+ } else if (!strcmp(ev->key, "Home") && altPressed) {
+ INFO("Home (Alt+Home) was pressed");
+ ewk_view_url_set(window->ewk_view, DEFAULT_URL);
+ } else if (!strcmp(ev->key, "F3")) {
+ currentEncoding = (currentEncoding + 1) % (sizeof(encodings) / sizeof(encodings[0]));
+ INFO("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
+ ewk_view_custom_encoding_set(ewk_view, encodings[currentEncoding]);
+ } else if ((!strcmp(ev->key, "F5") && ctrlPressed) || (!strcmp(ev->key, "r") && (shiftPressed & ctrlPressed))) {
+ INFO("Reload ignoring cache (Ctrl+F5 or Ctrl+Shift+r) was pressed, reloading and bypassing cache...");
+ ewk_view_reload_bypass_cache(ewk_view);
+ } else if (!strcmp(ev->key, "F5") || (!strcmp(ev->key, "r") && ctrlPressed)) {
+ INFO("Reload (F5 or Ctrl+r) was pressed, reloading...");
+ ewk_view_reload(ewk_view);
+ } else if (!strcmp(ev->key, "F6")) {
+ INFO("Stop (F6) was pressed, stop loading.");
+ ewk_view_stop(ewk_view);
+ } else if (!strcmp(ev->key, "F7")) {
+ Ewk_Pagination_Mode mode = ewk_view_pagination_mode_get(ewk_view);
+ mode = (mode + 1) % (EWK_PAGINATION_MODE_BOTTOM_TO_TOP + 1);
+ if (ewk_view_pagination_mode_set(ewk_view, mode))
+ INFO("Change Pagination Mode (F7) was pressed, changed to: %d", mode);
+ else
+ INFO("Change Pagination Mode (F7) was pressed, but NOT changed!");
+ } else if (!strcmp(ev->key, "F11")) {
+ INFO("Fullscreen (F11) was pressed, toggling window/fullscreen.");
+ toggle_window_fullscreen(window, !elm_win_fullscreen_get(window->elm_window));
+ } else if (!strcmp(ev->key, "n") && ctrlPressed) {
+ INFO("Create new window (Ctrl+n) was pressed.");
+ Browser_Window *window = window_create(configuration(), 0, 0);
+ ewk_view_url_set(window->ewk_view, DEFAULT_URL);
+ // 0 equals default width and height.
+ windows = eina_list_append(windows, window);
+ } else if (!strcmp(ev->key, "i") && ctrlPressed) {
+ INFO("Show Inspector (Ctrl+i) was pressed.");
+ ewk_view_inspector_show(ewk_view);
+ } else if (!strcmp(ev->key, "f") && ctrlPressed) {
+ INFO("Show Search Box (Ctrl+f) was pressed.");
+ const char get_data_script[] = "window.getSelection().toString();";
+ ewk_view_script_execute(ewk_view, get_data_script, script_execute_callback, (void*)(window));
+ } else if (!strcmp(ev->key, "Escape")) {
+ if (evas_object_visible_get(window->search.search_bar))
+ search_box_hide(window);
+ else if (evas_object_visible_get(window->history.history_box))
+ history_list_hide(window);
+ else if (elm_win_fullscreen_get(window->elm_window))
+ ewk_view_fullscreen_exit(ewk_view);
+ else
+ ewk_view_stop(ewk_view);
+ } else if (ctrlPressed && (!strcmp(ev->key, "minus") || !strcmp(ev->key, "KP_Subtract"))) {
+ if (zoom_level_set(ewk_view, window->current_zoom_level - 1))
+ window->current_zoom_level--;
+ INFO("Zoom out (Ctrl + '-') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
+ } else if (ctrlPressed && (!strcmp(ev->key, "equal") || !strcmp(ev->key, "KP_Add"))) {
+ if (zoom_level_set(ewk_view, window->current_zoom_level + 1))
+ window->current_zoom_level++;
+ INFO("Zoom in (Ctrl + '+') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
+ } else if (ctrlPressed && !strcmp(ev->key, "0")) {
+ if (zoom_level_set(ewk_view, DEFAULT_ZOOM_LEVEL))
+ window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
+ INFO("Zoom to default (Ctrl + '0') was pressed, zoom level became %.2f", zoomLevels[window->current_zoom_level]);
+ } else if (ctrlPressed && !strcmp(ev->key, "s")) {
+ Eina_Strbuf *default_file = eina_strbuf_new();
+ const char *home_path = getenv("HOME");
+ const char *title = ewk_view_title_get(window->ewk_view);
+ eina_strbuf_append_printf(default_file, "%s/%s.mht", home_path ? home_path : "/home", title ? title : "title");
+ INFO("Pressed (CTRL + S) : Saving Current Page.");
+ Eina_Stringshare *save_file_name = _file_entry_dialog_show(window, "SAVE", eina_strbuf_string_get(default_file));
+ if (!save_file_name)
+ return;
+ ewk_view_page_contents_get(ewk_view, EWK_PAGE_CONTENTS_TYPE_MHTML, save_page_contents_callback, (void *)save_file_name);
+ eina_strbuf_free(default_file);
+ } else if (ctrlPressed && !strcmp(ev->key, "l")) {
+ const char *home_path = getenv("HOME");
+ Eina_Stringshare *open_file_name = _file_entry_dialog_show(window, "LOAD", home_path ? home_path : "/home");
+ if (!open_file_name)
+ return;
+ Eina_Strbuf *uri_path = eina_strbuf_new();
+ eina_strbuf_append_printf(uri_path, "%s%s", FILE_SCHEME, open_file_name);
+ INFO("pressed (CTRL + L) : Loading Page %s", eina_strbuf_string_get(uri_path));
+ ewk_view_url_set(ewk_view, eina_strbuf_string_get(uri_path));
+ eina_strbuf_free(uri_path);
+ eina_stringshare_del(open_file_name);
+ }
+}
+
+static void
+view_focus_set(Browser_Window *window, Eina_Bool focus)
+{
+ /* We steal focus away from elm's focus model and start to do things
+ * manually here, so elm now has no clue what's up. Tell elm that its
+ * toplevel widget is to be unfocused so elm gives up the focus */
+ elm_object_focus_set(elm_object_top_widget_get(window->elm_window), EINA_FALSE);
+ evas_object_focus_set(window->ewk_view, focus);
+}
+
+static void
+_mouse_down_cb(void *user_data, Evas *e, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
+
+ /* Clear selection from the URL bar */
+ elm_entry_select_none(window->url_bar);
+
+ if (longpress_enabled)
+ history_list_hide(window);
+ if (ev->button == 1)
+ view_focus_set(window, EINA_TRUE);
+ else if (ev->button == 2)
+ view_focus_set(window, !evas_object_focus_get(ewk_view));
+}
+
+static void
+title_set(Evas_Object *elm_window, const char *title, int progress)
+{
+ Eina_Strbuf *buffer;
+
+ if (!title || !*title) {
+ elm_win_title_set(elm_window, APP_NAME);
+ return;
+ }
+
+ buffer = eina_strbuf_new();
+ if (progress < 100)
+ eina_strbuf_append_printf(buffer, "%s (%d%%) - %s", title, progress, APP_NAME);
+ else
+ eina_strbuf_append_printf(buffer, "%s - %s", title, APP_NAME);
+
+ elm_win_title_set(elm_window, eina_strbuf_string_get(buffer));
+ eina_strbuf_free(buffer);
+}
+
+static void
+_title_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ const char *title = (const char *)event_info;
+
+ title_set(window->elm_window, title, 100);
+}
+
+static void
+_url_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ const char *url = ewk_view_url_get(window->ewk_view);
+ char *converted_url = elm_entry_utf8_to_markup(url);
+ elm_entry_entry_set(window->url_bar, converted_url);
+
+ _icon_changed_cb(ewk_context_favicon_database_get(ewk_view_context_get(ewk_view)), url, user_data);
+
+ free(converted_url);
+
+ search_box_hide(window);
+}
+
+static void
+_back_forward_list_changed_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ /* Update navigation buttons state */
+ elm_object_disabled_set(window->back_button, !ewk_view_back_possible(ewk_view));
+ elm_object_disabled_set(window->forward_button, !ewk_view_forward_possible(ewk_view));
+}
+
+static void
+_progress_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ double progress = *(double *)event_info;
+
+ title_set(window->elm_window, ewk_view_title_get(window->ewk_view), progress * 100);
+}
+
+static void
+_error_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Eina_Strbuf *buffer;
+ const Ewk_Error *error = (const Ewk_Error *)event_info;
+
+ /* This is a cancellation, do not display the error page */
+ if (ewk_error_cancellation_get(error))
+ return;
+
+ buffer = eina_strbuf_new();
+ eina_strbuf_append_printf(buffer,
+ "<html><body><div style=\"color:#ff0000\">ERROR!</div><br><div>Code: %d<br>Description: %s<br>URL: %s</div></body</html>",
+ ewk_error_code_get(error), ewk_error_description_get(error), ewk_error_url_get(error));
+
+ ewk_view_html_string_load(ewk_view, eina_strbuf_string_get(buffer), 0, ewk_error_url_get(error));
+ eina_strbuf_free(buffer);
+}
+
+static void
+_download_request_cb(Ewk_Download_Job *download, void *user_data)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ Eina_Strbuf *destination_path = eina_strbuf_new();
+
+ const char *home_path = getenv("HOME");
+ Eina_Stringshare *save_file_path = _file_entry_dialog_show(window, "DOWNLOAD", home_path ? home_path : "/tmp");
+
+ if (save_file_path)
+ eina_strbuf_append_printf(destination_path, "%s", save_file_path);
+ else
+ eina_strbuf_append(destination_path, "/tmp");
+
+ const char *suggested_name = ewk_download_job_suggested_filename_get(download);
+ if (suggested_name && *suggested_name)
+ eina_strbuf_append_printf(destination_path, "/%s", suggested_name);
+ else {
+ // Generate a unique file name since no name was suggested.
+ eina_strbuf_append(destination_path, "/downloaded-file.XXXXXX");
+ char *url = NULL;
+ url = eina_strbuf_string_steal(destination_path);
+ if (mkstemp(url) == -1) {
+ ERROR("Could not generate a unique file name.");
+ return;
+ }
+ eina_strbuf_append(destination_path, url);
+ }
+
+ ewk_download_job_destination_set(download, eina_strbuf_string_get(destination_path));
+ INFO("Downloading: %s", eina_strbuf_string_get(destination_path));
+ eina_strbuf_free(destination_path);
+ eina_stringshare_del(save_file_path);
+}
+
+static void _filepicker_parent_deletion_cb(void *user_data, Evas *evas, Evas_Object *elm_window, void *event);
+
+static void close_file_picker(File_Selector_Data *fs_data)
+{
+ evas_object_event_callback_del(fs_data->parent->elm_window, EVAS_CALLBACK_DEL, _filepicker_parent_deletion_cb);
+ evas_object_del(fs_data->elm_window);
+ ewk_object_unref(fs_data->request);
+ free(fs_data);
+}
+
+static void
+_filepicker_parent_deletion_cb(void *user_data, Evas *evas, Evas_Object *elm_window, void *event)
+{
+ close_file_picker((File_Selector_Data *)user_data);
+}
+
+static void
+_filepicker_deletion_cb(void *user_data, Evas_Object *elm_window, void *event_info)
+{
+ close_file_picker((File_Selector_Data *)user_data);
+}
+
+static void
+_fileselector_done_cb(void *user_data, Evas_Object *file_selector, void *event_info)
+{
+ File_Selector_Data *fs_data = (File_Selector_Data *)user_data;
+
+ const char *selected = (const char *)event_info;
+ if (selected && *selected)
+ ewk_file_chooser_request_file_choose(fs_data->request, selected);
+
+ close_file_picker(fs_data);
+}
+
+static void
+_file_chooser_request_cb(void *user_data, Evas_Object *ewk_view, void *event_info)
+{
+ Evas_Object *bg;
+ Browser_Window *window = (Browser_Window *)user_data;
+ Ewk_File_Chooser_Request *request = (Ewk_File_Chooser_Request *)event_info;
+
+ // Show basic file picker which does not currently support multiple files
+ // or MIME type filtering.
+ Evas_Object *elm_window = elm_win_add(window->elm_window, "file-picker-window", ELM_WIN_DIALOG_BASIC);
+ elm_win_title_set(elm_window, "File picker");
+ elm_win_modal_set(elm_window, EINA_TRUE);
+
+ bg = elm_bg_add(elm_window);
+ evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(elm_window, bg);
+ evas_object_show(bg);
+
+ File_Selector_Data *fs_data = (File_Selector_Data *)malloc(sizeof(File_Selector_Data));
+ fs_data->parent = window;
+ fs_data->elm_window = elm_window;
+ fs_data->request = ewk_object_ref(request);
+ evas_object_smart_callback_add(elm_window, "delete,request", _filepicker_deletion_cb, fs_data);
+ evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_DEL, _filepicker_parent_deletion_cb, fs_data);
+
+ Evas_Object *file_selector = elm_fileselector_add(elm_window);
+ const char *home_path = getenv("HOME");
+ elm_fileselector_path_set(file_selector, home_path ? home_path : "/home");
+ evas_object_size_hint_weight_set(file_selector, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(elm_window, file_selector);
+ evas_object_show(file_selector);
+
+ evas_object_smart_callback_add(file_selector, "done", _fileselector_done_cb, fs_data);
+
+ int x, y, width, height;
+ evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
+
+ int picker_x = x + width / 2 - color_picker_width / 2;
+ int picker_y = y + height / 2 - color_picker_height / 2;
+ evas_object_geometry_set(window->color_selector.elm_selector_window, picker_x, picker_y,
+ color_picker_width, color_picker_height);
+}
+
+static void
+_download_finished_cb(Ewk_Download_Job *download, void *user_data)
+{
+ INFO("Download finished: %s", ewk_download_job_destination_get(download));
+}
+
+static void
+_download_failed_cb(Ewk_Download_Job_Error *download_error, void *user_data)
+{
+ Ewk_Error *error = download_error->error;
+
+ INFO("Download failed! Error code: %d, Error description: %s, Error URL: %s", ewk_error_code_get(error), ewk_error_description_get(error), ewk_error_url_get(error));
+}
+
+static void
+_color_changed_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ int r, g, b, a;
+
+ elm_colorselector_color_get(obj, &r, &g, &b, &a);
+ evas_object_color_set(data, r, g, b, a);
+}
+
+static void
+_color_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ int r, g, b, a;
+ Elm_Object_Item *color_item = (Elm_Object_Item *)event_info;
+
+ elm_colorselector_palette_item_color_get(color_item, &r, &g, &b, &a);
+ evas_object_color_set(data, r, g, b, a);
+}
+
+static void
+_color_picker_ok_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ int r, g, b, a;
+ Color_Selector *color_selector = (Color_Selector *)data;
+
+ elm_colorselector_color_get(color_selector->elm_selector, &r, &g, &b, &a);
+ ewk_color_picker_color_set(color_selector->ewk_picker, r, g, b, a);
+}
+
+static void
+_color_picker_cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ int r, g, b, a;
+
+ ewk_color_picker_color_get(data, &r, &g, &b, &a);
+ ewk_color_picker_color_set(data, r, g, b, a);
+}
+
+static Eina_Bool
+_color_picker_dismiss_cb(Ewk_View_Smart_Data *sd)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ evas_object_del(window->color_selector.elm_selector_window);
+ window->color_selector.elm_selector_window = NULL;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_color_picker_request_cb(Ewk_View_Smart_Data *sd, Ewk_Color_Picker *color_picker)
+{
+ int r, g, b, a;
+ Evas_Object *background, *rect, *box, *button_box, *rect_frame, *cs_frame, *ok_button, *cancel_button;
+
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+ window->color_selector.elm_selector_window = elm_win_add(window->elm_window, "color selector", ELM_WIN_BASIC);
+ window->color_selector.ewk_picker = color_picker;
+
+ elm_win_title_set(window->color_selector.elm_selector_window, "Color selector");
+
+ /* Show color view */
+ background = elm_bg_add(window->color_selector.elm_selector_window);
+ evas_object_size_hint_weight_set(background, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(window->color_selector.elm_selector_window, background);
+ evas_object_show(background);
+
+ box = elm_box_add(window->color_selector.elm_selector_window);
+ evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(window->color_selector.elm_selector_window, box);
+ evas_object_show(box);
+
+ rect_frame = elm_frame_add(window->color_selector.elm_selector_window);
+ evas_object_size_hint_weight_set(rect_frame, EVAS_HINT_EXPAND, 0.3);
+ evas_object_size_hint_align_set(rect_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_text_set(rect_frame, "Color View");
+ elm_box_pack_end(box, rect_frame);
+ evas_object_show(rect_frame);
+
+ rect = evas_object_rectangle_add(evas_object_evas_get(window->color_selector.elm_selector_window));
+ elm_object_content_set(rect_frame, rect);
+ ewk_color_picker_color_get(window->color_selector.ewk_picker, &r, &g, &b, &a);
+ evas_object_color_set(rect, r, g, b, a);
+ evas_object_show(rect);
+
+ /* Show color selector */
+ cs_frame = elm_frame_add(window->color_selector.elm_selector_window);
+ evas_object_size_hint_weight_set(cs_frame, EVAS_HINT_EXPAND, 0.7);
+ evas_object_size_hint_align_set(cs_frame, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_text_set(cs_frame, "Color Selector");
+ elm_box_pack_end(box, cs_frame);
+ evas_object_show(cs_frame);
+
+ window->color_selector.elm_selector = elm_colorselector_add(window->color_selector.elm_selector_window);
+ elm_object_content_set(cs_frame, window->color_selector.elm_selector);
+ evas_object_show(window->color_selector.elm_selector);
+
+ /* OK, Cancel Buttons */
+ button_box = elm_box_add(window->color_selector.elm_selector_window);
+ elm_box_horizontal_set(button_box, EINA_TRUE);
+ evas_object_size_hint_min_set(button_box, 200, 50);
+ elm_box_pack_end(box, button_box);
+ evas_object_show(button_box);
+
+ ok_button = elm_button_add(window->color_selector.elm_selector_window);
+ elm_object_text_set(ok_button, "OK");
+ elm_box_pack_end(button_box, ok_button);
+ evas_object_show(ok_button);
+
+ cancel_button = elm_button_add(window->color_selector.elm_selector_window);
+ elm_object_text_set(cancel_button, "Cancel");
+ elm_box_pack_end(button_box, cancel_button);
+ evas_object_show(cancel_button);
+
+ evas_object_smart_callback_add(ok_button, "clicked", _color_picker_ok_clicked_cb, &(window->color_selector));
+ evas_object_smart_callback_add(cancel_button, "clicked", _color_picker_cancel_clicked_cb,
+ window->color_selector.ewk_picker);
+ evas_object_smart_callback_add(window->color_selector.elm_selector_window, "delete,request",
+ _color_picker_cancel_clicked_cb, window->color_selector.ewk_picker);
+ evas_object_smart_callback_add(window->color_selector.elm_selector, "changed", _color_changed_cb, rect);
+ evas_object_smart_callback_add(window->color_selector.elm_selector, "color,item,selected", _color_item_selected_cb,
+ rect);
+
+ int x, y, width, height;
+ evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
+
+ elm_win_center(window->color_selector.elm_selector_window, EINA_TRUE, EINA_TRUE);
+ evas_object_resize(window->color_selector.elm_selector_window, 350, 500);
+ evas_object_show(window->color_selector.elm_selector_window);
+
+ return EINA_TRUE;
+}
+
+static int
+quit(Eina_Bool success, const char *msg)
+{
+ if (msg)
+ success ? INFO("%s", msg) : ERROR("%s", msg);
+
+ ewk_object_unref(configuration());
+ ewk_shutdown();
+ elm_shutdown();
+ eina_log_domain_unregister(_log_domain_id);
+
+ if (!success)
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+
+static Eina_Bool
+has_scheme(const char *url)
+{
+ return !!strstr(url, "://");
+}
+
+static char *
+url_from_user_input(const char *arg)
+{
+ /* If it is already a URL, return the argument as is. */
+ if (has_scheme(arg) || eina_str_has_prefix(arg, JAVASCRIPT_SCHEME) || !strcasecmp(arg, "about:blank"))
+ return strdup(arg);
+
+ Eina_Strbuf *buf = eina_strbuf_manage_new(eina_file_path_sanitize(arg));
+
+ /* Check if the path exists. */
+ if (ecore_file_exists(eina_strbuf_string_get(buf))) {
+ /* File exists, convert local path to a URL. */
+ eina_strbuf_prepend(buf, FILE_SCHEME);
+ } else {
+ /* The path does not exist, convert it to a URL by
+ prepending http:// scheme:
+ www.google.com -> http://www.google.com */
+ eina_strbuf_string_free(buf);
+ eina_strbuf_append_printf(buf, "%s%s", HTTP_SCHEME, arg);
+ }
+ char *url = eina_strbuf_string_steal(buf);
+ eina_strbuf_free(buf);
+
+ return url;
+}
+
+static Eina_Bool
+url_load_from_user_input(Evas_Object *ewk_view, const char *url)
+{
+ if (!ewk_view || !url)
+ return EINA_FALSE;
+
+ if (eina_str_has_prefix(url, JAVASCRIPT_SCHEME))
+ return ewk_view_script_execute(ewk_view, strstr(url, JAVASCRIPT_SCHEME), 0, 0);
+
+ return ewk_view_url_set(ewk_view, url);
+}
+
+static void
+_url_bar_activated_cb(void *user_data, Evas_Object *url_bar, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ const char *markup_url = elm_entry_entry_get(url_bar);
+ char *user_url = elm_entry_markup_to_utf8(markup_url);
+ char *url = url_from_user_input(user_url);
+ url_load_from_user_input(window->ewk_view, url);
+
+ free(user_url);
+ free(url);
+
+ /* Give focus back to the view */
+ view_focus_set(window, EINA_TRUE);
+}
+
+static void
+_url_bar_clicked_cb(void *user_data, Evas_Object *url_bar, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ /* Grab focus from the view */
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(url_bar, EINA_TRUE);
+}
+
+static void
+_search_field_aborted_cb(void *user_data, Evas_Object *search_field, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ search_box_hide(window);
+
+ /* Give focus back to the view */
+ view_focus_set(window, EINA_TRUE);
+}
+
+static void
+_search_field_activated_cb(void *user_data, Evas_Object *search_field, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ const char *markup_text = elm_entry_entry_get(search_field);
+ char *text = elm_entry_markup_to_utf8(markup_text);
+ ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
+ free(text);
+
+ /* Grab focus from the view */
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(search_field, EINA_TRUE);
+}
+
+static void
+_search_field_clicked_cb(void *user_data, Evas_Object *search_field, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ /* Grab focus from the view */
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(search_field, EINA_TRUE);
+}
+
+static void
+_back_button_clicked_cb(void *user_data, Evas_Object *back_button, void *event_info)
+{
+ if (longpress_enabled)
+ return;
+
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ ewk_view_back(window->ewk_view);
+ /* Update back button state */
+ elm_object_disabled_set(back_button, !ewk_view_back_possible(window->ewk_view));
+}
+
+static void
+_forward_button_clicked_cb(void *user_data, Evas_Object *forward_button, void *event_info)
+{
+ if (longpress_enabled)
+ return;
+
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ ewk_view_forward(window->ewk_view);
+ /* Update forward button state */
+ elm_object_disabled_set(forward_button, !ewk_view_forward_possible(window->ewk_view));
+}
+
+static void
+_search_backward_button_clicked_cb(void *user_data, Evas_Object *search_backward_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
+ ewk_view_text_find(window->ewk_view, text, search_flags | EWK_FIND_OPTIONS_BACKWARDS, MAX_SEARCH_COUNT);
+ free(text);
+}
+
+static void
+_search_forward_button_clicked_cb(void *user_data, Evas_Object *search_forward_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
+ ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
+ free(text);
+}
+
+static void
+_search_case_option_changed(void *user_data, Evas_Object *search_case_check_box, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
+
+ /* Bit toggle the case sensitive flag */
+ search_flags = search_flags ^ EWK_FIND_OPTIONS_CASE_INSENSITIVE;
+
+ ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
+ free(text);
+}
+
+static void
+_search_word_start_option_changed_cb(void *user_data, Evas_Object *search_word_start_check_box, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ char *text = elm_entry_markup_to_utf8(elm_entry_entry_get(window->search.search_field));
+
+ /* Bit toggle the word start flag */
+ search_flags = search_flags ^ EWK_FIND_OPTIONS_AT_WORD_STARTS;
+
+ ewk_view_text_find(window->ewk_view, text, search_flags, MAX_SEARCH_COUNT);
+ free(text);
+}
+
+static void
+_search_close_button_clicked_cb(void *user_data, Evas_Object *search_close_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ search_box_hide(window);
+}
+
+static void
+_refresh_button_clicked_cb(void *user_data, Evas_Object *refresh_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ Evas *evas = evas_object_evas_get(refresh_button);
+ Eina_Bool ctrlPressed = evas_key_modifier_is_set(evas_key_modifier_get(evas), "Control");
+ if (ctrlPressed) {
+ INFO("Reloading and bypassing cache...");
+ ewk_view_reload_bypass_cache(window->ewk_view);
+ } else {
+ INFO("Reloading...");
+ ewk_view_reload(window->ewk_view);
+ }
+}
+
+static void
+_stop_button_clicked_cb(void *user_data, Evas_Object *stop_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ INFO("Stop was Pressed. Aborting load...");
+ ewk_view_stop(window->ewk_view);
+}
+
+static char *
+list_item_label_get(void *data, Evas_Object *obj, const char *part)
+{
+ int len = strlen((char *)data);
+ char *buf = (char *)malloc(sizeof(char) * (len + 1));
+ snprintf(buf, len + 1, "%s", (char *)data);
+ return buf;
+}
+
+static void
+_list_item_select_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = evas_object_data_get(obj, "Browser_Window");
+ ewk_view_navigate_to(window->ewk_view, user_data);
+ history_list_hide(window);
+ evas_object_data_del(obj, "Browser_Window");
+}
+
+static void
+navigation_button_longpress_process(void *user_data, Eina_Bool forward_navigation_enabled)
+{
+ if (longpress_enabled)
+ return;
+
+ longpress_enabled = EINA_TRUE;
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ Ewk_Back_Forward_List *list = ewk_view_back_forward_list_get(window->ewk_view);
+ const Eina_List *l;
+ void *data;
+ static Elm_Genlist_Item_Class *list_item = NULL;
+ const char *title = NULL;
+ int item_count;
+ int x;
+ int y;
+ int width;
+ int height;
+ size_t index;
+
+ evas_object_data_set(window->history.history_list, "Browser_Window", window);
+
+ if (forward_navigation_enabled)
+ window->history.history_list_items = ewk_back_forward_list_forward_items_copy(list);
+ else
+ window->history.history_list_items = ewk_back_forward_list_back_items_copy(list);
+
+ if (!list_item) {
+ list_item = elm_genlist_item_class_new();
+ list_item->item_style = "default";
+ list_item->func.text_get = list_item_label_get;
+ list_item->func.content_get = NULL;
+ list_item->func.state_get = NULL;
+ list_item->func.del = NULL;
+ }
+
+ item_count = eina_list_count(window->history.history_list_items);
+ INFO("navigation_button_longpress_process : Item count = %d forward_navigation_enabled = %d", item_count, forward_navigation_enabled);
+
+ EINA_LIST_FOREACH(window->history.history_list_items, l, data) {
+ title = ewk_back_forward_list_item_title_get(data);
+ INFO(" title = %s", title);
+ elm_genlist_item_append(window->history.history_list, list_item, (void *)(title), NULL, ELM_GENLIST_ITEM_NONE, _list_item_select_cb, data);
+ }
+
+ if (item_count > 0) {
+ evas_object_geometry_get(window->elm_window, &x, &y, &width, &height);
+ elm_list_go(window->history.history_list);
+ evas_object_resize(window->history.history_box , width / 3 , LIST_ITEM_HEIGHT * item_count);
+
+ if (forward_navigation_enabled) {
+ evas_object_move(window->history.history_box , x + TOOL_BAR_BUTTON_SIZE + 1, y + TOOL_BAR_BUTTON_SIZE);
+ evas_object_move(window->history.history_list , x + TOOL_BAR_BUTTON_SIZE + 1, y + TOOL_BAR_BUTTON_SIZE);
+ } else {
+ evas_object_move(window->history.history_box , x, y + TOOL_BAR_BUTTON_SIZE);
+ evas_object_move(window->history.history_list , x, y + TOOL_BAR_BUTTON_SIZE);
+ }
+
+ elm_genlist_mode_set(window->history.history_list, ELM_LIST_COMPRESS);
+ evas_object_show(window->history.history_box);
+ evas_object_show(window->history.history_list);
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(window->history.history_list, EINA_TRUE);
+ } else
+ longpress_enabled = EINA_FALSE;
+}
+
+static void
+_forward_button_longpress_cb(void *user_data, Evas_Object *forward_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ navigation_button_longpress_process(user_data, EINA_TRUE);
+ elm_object_disabled_set(forward_button, !ewk_view_back_possible(window->ewk_view));
+}
+
+static void
+_back_button_longpress_cb(void *user_data, Evas_Object *back_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ navigation_button_longpress_process(user_data, EINA_FALSE);
+ elm_object_disabled_set(back_button, !ewk_view_back_possible(window->ewk_view));
+}
+
+static void
+_ok_clicked_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Eina_Bool *confirmed = (Eina_Bool *)user_data;
+ *confirmed = EINA_TRUE;
+}
+
+static Eina_Stringshare *
+_file_entry_dialog_show(Browser_Window *window, const char *label_tag, const char *default_text)
+{
+ Evas_Object *file_popup = elm_popup_add(window->elm_window);
+ evas_object_size_hint_weight_set(file_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(file_popup);
+
+ Evas_Object *vbox = elm_box_add(file_popup);
+ evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_content_set(file_popup, vbox);
+ evas_object_show(vbox);
+
+ Evas_Object *label = elm_label_add(window->elm_window);
+ elm_object_text_set(label, label_tag);
+ evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(label, EVAS_HINT_FILL, 0.5);
+ evas_object_color_set(label, 23, 45, 67, 142);
+ elm_box_pack_end(vbox, label);
+ evas_object_show(label);
+
+ Evas_Object *fs_entry = elm_fileselector_entry_add(file_popup);
+ elm_fileselector_is_save_set(fs_entry, EINA_TRUE);
+ evas_object_size_hint_align_set(fs_entry, EVAS_HINT_FILL, 0);
+ elm_fileselector_path_set(fs_entry, default_text);
+ elm_object_text_set(fs_entry, "FileChooser");
+ elm_box_pack_end(vbox, fs_entry);
+ evas_object_show(fs_entry);
+
+ Evas_Object *hbox = elm_box_add(file_popup);
+ evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_box_horizontal_set(hbox, EINA_TRUE);
+ evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(vbox, hbox);
+ evas_object_show(hbox);
+
+ Eina_Bool ok = EINA_FALSE;
+ Evas_Object *ok_button = elm_button_add(file_popup);
+ elm_object_text_set(ok_button, "OK");
+ evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
+ elm_box_pack_end(hbox, ok_button);
+ evas_object_show(ok_button);
+
+ Eina_Bool cancel = EINA_FALSE;
+ Evas_Object *cancel_button = elm_button_add(file_popup);
+ elm_object_text_set(cancel_button, "Cancel");
+ evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
+ elm_box_pack_end(hbox, cancel_button);
+ evas_object_show(cancel_button);
+
+ while (ok != EINA_TRUE && cancel != EINA_TRUE)
+ ecore_main_loop_iterate();
+
+ Eina_Stringshare *file_path = ok ? eina_stringshare_add(elm_fileselector_path_get(fs_entry)) : NULL;
+ evas_object_del(file_popup);
+ return file_path;
+}
+
+static void
+_javascript_alert_cb(Ewk_View_Smart_Data *smartData, const char *message)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+
+ Evas_Object *alert_popup = elm_popup_add(window->elm_window);
+ evas_object_size_hint_weight_set(alert_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_text_set(alert_popup, message);
+ elm_object_part_text_set(alert_popup, "title,text", "Alert");
+
+ /* Popup buttons */
+ Eina_Bool ok = EINA_FALSE;
+ Evas_Object *button = elm_button_add(alert_popup);
+ elm_object_text_set(button, "OK");
+ elm_object_part_content_set(alert_popup, "button1", button);
+ evas_object_smart_callback_add(button, "clicked", _ok_clicked_cb, &ok);
+ elm_object_focus_set(button, EINA_TRUE);
+ evas_object_show(alert_popup);
+
+ while (ok != EINA_TRUE)
+ ecore_main_loop_iterate();
+
+ evas_object_del(alert_popup);
+}
+
+static Eina_Bool
+_javascript_confirm_cb(Ewk_View_Smart_Data *smartData, const char *message)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+
+ Evas_Object *confirm_popup = elm_popup_add(window->elm_window);
+ evas_object_size_hint_weight_set(confirm_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_text_set(confirm_popup, message);
+ elm_object_part_text_set(confirm_popup, "title,text", "Confirmation");
+
+ /* Popup buttons */
+ Eina_Bool cancel = EINA_FALSE;
+ Evas_Object *cancel_button = elm_button_add(confirm_popup);
+ elm_object_text_set(cancel_button, "Cancel");
+ elm_object_part_content_set(confirm_popup, "button1", cancel_button);
+ evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
+ Evas_Object *ok_button = elm_button_add(confirm_popup);
+ Eina_Bool ok = EINA_FALSE;
+ elm_object_text_set(ok_button, "OK");
+ elm_object_part_content_set(confirm_popup, "button2", ok_button);
+ evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
+ elm_object_focus_set(ok_button, EINA_TRUE);
+ evas_object_show(confirm_popup);
+
+ while (cancel != EINA_TRUE && ok != EINA_TRUE)
+ ecore_main_loop_iterate();
+
+ evas_object_del(confirm_popup);
+
+ return ok;
+}
+
+static const char *
+_javascript_prompt_cb(Ewk_View_Smart_Data *smartData, const char *message, const char *default_value)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+
+ Evas_Object *prompt_popup = elm_popup_add(window->elm_window);
+ evas_object_size_hint_weight_set(prompt_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_part_text_set(prompt_popup, "title,text", "Prompt");
+
+ /* Popup Content */
+ Evas_Object *box = elm_box_add(window->elm_window);
+ elm_box_padding_set(box, 0, 4);
+ evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_show(box);
+
+ Evas_Object *prompt = elm_label_add(window->elm_window);
+ elm_object_text_set(prompt, message);
+ evas_object_size_hint_weight_set(prompt, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(prompt, EVAS_HINT_FILL, 0.5);
+ elm_box_pack_end(box, prompt);
+ evas_object_show(prompt);
+
+ Evas_Object *entry = elm_entry_add(window->elm_window);
+ elm_entry_scrollable_set(entry, EINA_TRUE);
+ elm_entry_single_line_set(entry, EINA_TRUE);
+ elm_entry_text_style_user_push(entry, "DEFAULT='font_size=18'");
+ elm_entry_entry_set(entry, default_value ? default_value : "");
+ elm_entry_select_all(entry);
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
+ elm_box_pack_end(box, entry);
+ elm_object_focus_set(entry, EINA_TRUE);
+ evas_object_show(entry);
+
+ elm_object_content_set(prompt_popup, box);
+
+ /* Popup buttons */
+ Eina_Bool cancel = EINA_FALSE;
+ Evas_Object *cancel_button = elm_button_add(prompt_popup);
+ elm_object_text_set(cancel_button, "Cancel");
+ elm_object_part_content_set(prompt_popup, "button1", cancel_button);
+ evas_object_smart_callback_add(cancel_button, "clicked", _ok_clicked_cb, &cancel);
+ Eina_Bool ok = EINA_FALSE;
+ Evas_Object *ok_button = elm_button_add(prompt_popup);
+ elm_object_text_set(ok_button, "OK");
+ elm_object_part_content_set(prompt_popup, "button2", ok_button);
+ evas_object_smart_callback_add(ok_button, "clicked", _ok_clicked_cb, &ok);
+ evas_object_show(prompt_popup);
+
+ while (cancel != EINA_TRUE && ok != EINA_TRUE)
+ ecore_main_loop_iterate();
+
+ /* The return string need to be stringshared */
+ const char *prompt_text = ok ? eina_stringshare_add(elm_entry_entry_get(entry)) : NULL;
+ evas_object_del(prompt_popup);
+
+ return prompt_text;
+}
+
+static Eina_Bool
+_javascript_before_unload_confirm_cb(Ewk_View_Smart_Data *smartData, const char *message)
+{
+ return _javascript_confirm_cb(smartData, "Will you leave this page?");
+}
+
+static void
+_popup_menu_item_clicked_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ Elm_Object_Item *item = (Elm_Object_Item *)event_info;
+
+ INFO("Selected popup menu index: %u", elm_menu_item_index_get(item));
+ ewk_popup_menu_selected_index_set(window->popup.ewk_menu, elm_menu_item_index_get(item));
+
+ // Close popup menu.
+ ewk_popup_menu_close(window->popup.ewk_menu);
+}
+
+static void
+popup_menu_populate(Evas_Object *elm_menu, Ewk_Popup_Menu *ewk_menu, void *user_data)
+{
+ const Eina_List* ewk_items = ewk_popup_menu_items_get(ewk_menu);
+
+ void *data;
+ const Eina_List *l;
+ EINA_LIST_FOREACH(ewk_items, l, data) {
+ Ewk_Popup_Menu_Item *ewk_item = (Ewk_Popup_Menu_Item *)data;
+ switch (ewk_popup_menu_item_type_get(ewk_item)) {
+ case EWK_POPUP_MENU_SEPARATOR:
+ elm_menu_item_separator_add(elm_menu, NULL);
+ break;
+ case EWK_POPUP_MENU_ITEM:
+ if (ewk_popup_menu_item_is_label_get(ewk_item)) {
+ Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), NULL, NULL);
+ elm_object_item_disabled_set(item, EINA_TRUE);
+ } else {
+ Elm_Object_Item *item = elm_menu_item_add(elm_menu, NULL, NULL, ewk_popup_menu_item_text_get(ewk_item), _popup_menu_item_clicked_cb, user_data);
+ const char *tooltip_text = ewk_popup_menu_item_tooltip_get(ewk_item);
+ if (tooltip_text && tooltip_text[0] != '\0')
+ elm_object_item_tooltip_text_set(item, tooltip_text);
+ elm_object_item_disabled_set(item, !ewk_popup_menu_item_enabled_get(ewk_item));
+ elm_menu_item_selected_set(item, ewk_popup_menu_item_selected_get(ewk_item));
+ }
+ break;
+ default:
+ INFO("Unrecognized popup menu item type!");
+ break;
+ }
+ }
+}
+
+static Eina_Bool
+_popup_menu_show(Ewk_View_Smart_Data *smartData, Eina_Rectangle rect, Ewk_Text_Direction text_direction, double page_scale_factor, Ewk_Popup_Menu *ewk_menu)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+
+ if (window->popup.elm_menu)
+ evas_object_del(window->popup.elm_menu);
+
+ window->popup.elm_menu = elm_menu_add(window->elm_window);
+ window->popup.ewk_menu = ewk_menu;
+
+ popup_menu_populate(window->popup.elm_menu, ewk_menu, window);
+
+ INFO("Showing popup menu at (%d, %d)", rect.x, rect.y);
+ elm_menu_move(window->popup.elm_menu, rect.x, rect.y);
+ evas_object_show(window->popup.elm_menu);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_popup_menu_hide(Ewk_View_Smart_Data *smartData)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+
+ if (!window->popup.elm_menu)
+ return EINA_FALSE;
+
+ elm_menu_close(window->popup.elm_menu);
+ window->popup.ewk_menu = NULL;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_window_geometry_get(Ewk_View_Smart_Data *sd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *width, Evas_Coord *height)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ evas_object_geometry_get(window->elm_window, x, y, width, height);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_window_geometry_set(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ evas_object_move(window->elm_window, x, y);
+ evas_object_resize(window->elm_window, width, height);
+
+ return EINA_TRUE;
+}
+
+typedef struct {
+ Evas_Object *ewk_view;
+ Evas_Object *permission_popup;
+} PermissionData;
+
+static void
+_fullscreen_accept_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ PermissionData *permission_data = (PermissionData *)user_data;
+ Browser_Window *window = window_find_with_ewk_view(permission_data->ewk_view);
+
+ elm_win_resize_object_del(window->elm_window, permission_data->permission_popup);
+ evas_object_del(permission_data->permission_popup);
+ evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
+ free(permission_data);
+}
+
+static void
+_fullscreen_deny_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ PermissionData *permission_data = (PermissionData *)user_data;
+ Browser_Window *window = window_find_with_ewk_view(permission_data->ewk_view);
+
+ ewk_view_fullscreen_exit(permission_data->ewk_view);
+ elm_win_resize_object_del(window->elm_window, permission_data->permission_popup);
+ evas_object_del(permission_data->permission_popup);
+ evas_object_focus_set(permission_data->ewk_view, EINA_TRUE);
+ free(permission_data);
+}
+
+static Eina_Bool
+_fullscreen_enter_cb(Ewk_View_Smart_Data *sd, Ewk_Security_Origin *origin)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ /* Go fullscreen */
+ toggle_window_fullscreen(window, EINA_TRUE);
+
+ /* Show user popup */
+ Evas_Object *permission_popup = elm_popup_add(window->elm_window);
+ evas_object_size_hint_weight_set(permission_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ Eina_Strbuf *message = eina_strbuf_new();
+ eina_strbuf_append_printf(message, "%s is now fullscreen.<br>Press ESC at any time to exit fullscreen.<br>Allow fullscreen?", ewk_security_origin_host_get(origin));
+ elm_object_text_set(permission_popup, eina_strbuf_string_get(message));
+ eina_strbuf_free(message);
+ elm_object_part_text_set(permission_popup, "title,text", "Fullscreen Permission");
+
+ /* Popup buttons */
+ PermissionData *permission_data = (PermissionData *)malloc(sizeof(PermissionData));
+ permission_data->ewk_view = window->ewk_view;
+ permission_data->permission_popup = permission_popup;
+ Evas_Object *accept_button = elm_button_add(permission_popup);
+ elm_object_text_set(accept_button, "Accept");
+ elm_object_part_content_set(permission_popup, "button1", accept_button);
+ evas_object_smart_callback_add(accept_button, "clicked", _fullscreen_accept_cb, permission_data);
+
+ Evas_Object *deny_button = elm_button_add(permission_popup);
+ elm_object_text_set(deny_button, "Deny");
+ elm_object_part_content_set(permission_popup, "button2", deny_button);
+ evas_object_smart_callback_add(deny_button, "clicked", _fullscreen_deny_cb, permission_data);
+ elm_win_resize_object_add(window->elm_window, permission_popup);
+ evas_object_show(permission_popup);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool _fullscreen_exit_cb(Ewk_View_Smart_Data *sd)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ toggle_window_fullscreen(window, EINA_FALSE);
+
+ return EINA_TRUE;
+}
+
+static Evas_Object *
+_window_create_cb(Ewk_View_Smart_Data *smartData, Ewk_View_Configuration* configuration, const Ewk_Window_Features *window_features)
+{
+ int x = 0;
+ int y = 0;
+ int width = 0;
+ int height = 0;
+
+ ewk_window_features_geometry_get(window_features, &x, &y, &width, &height);
+
+ if (!width)
+ width = window_width;
+
+ if (!height)
+ height = window_height;
+
+ Browser_Window *window = window_create(configuration, width, height);
+ Evas_Object *new_view = window->ewk_view;
+
+ windows = eina_list_append(windows, window);
+
+ INFO("minibrowser: location(%d,%d) size=(%d,%d)", x, y, width, height);
+
+ return new_view;
+}
+
+static void
+_window_close_cb(Ewk_View_Smart_Data *smartData)
+{
+ Browser_Window *window = window_find_with_ewk_view(smartData->self);
+ window_close(window);
+}
+
+static void
+_context_menu_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
+{
+ if (!data) {
+ ERROR("Context menu callback data is NULL.");
+ return;
+ }
+
+ Ewk_Context_Menu_Item *ewk_item = (Ewk_Context_Menu_Item *)data;
+ INFO("Selected context menu item: %s.", ewk_context_menu_item_title_get(ewk_item));
+ ewk_context_menu_item_select(ewk_context_menu_item_parent_menu_get(ewk_item), ewk_item);
+ ewk_context_menu_hide(ewk_context_menu_item_parent_menu_get(ewk_item));
+}
+
+static void
+context_menu_populate(Evas_Object* context_menu, Ewk_Context_Menu *ewk_menu, Elm_Object_Item *parent_item)
+{
+ if (!context_menu || !ewk_menu) {
+ ERROR("Necessary objects are NULL.");
+ return;
+ }
+
+ const Eina_List *list = ewk_context_menu_items_get(ewk_menu);
+ const Eina_List *l;
+ void *data;
+
+ Ewk_Context_Menu_Item *ewk_item;
+ Elm_Object_Item *elm_menu_item;
+ Evas_Object *elm_check_item;
+
+ EINA_LIST_FOREACH(list, l, data) {
+ ewk_item = (Ewk_Context_Menu_Item *)data;
+ switch (ewk_context_menu_item_type_get(ewk_item)) {
+ case EWK_ACTION_TYPE:
+ elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), _context_menu_item_selected_cb, ewk_item);
+ break;
+ case EWK_CHECKABLE_ACTION_TYPE:
+ elm_check_item = elm_check_add(context_menu);
+ elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), _context_menu_item_selected_cb, ewk_item);
+ elm_object_item_content_set(elm_menu_item, elm_check_item);
+ elm_check_state_set(elm_check_item, ewk_context_menu_item_checked_get(ewk_item));
+ break;
+ case EWK_SUBMENU_TYPE:
+ elm_menu_item = elm_menu_item_add(context_menu, parent_item, NULL, ewk_context_menu_item_title_get(ewk_item), NULL, ewk_item);
+ if (elm_menu_item)
+ context_menu_populate(context_menu, ewk_context_menu_item_submenu_get(ewk_item), elm_menu_item);
+ break;
+ default:
+ continue;
+ }
+ elm_object_item_disabled_set(elm_menu_item, !ewk_context_menu_item_enabled_get(ewk_item));
+ }
+}
+
+static Eina_Bool
+_context_menu_show(Ewk_View_Smart_Data *sd, Evas_Coord x, Evas_Coord y, Ewk_Context_Menu *menu)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ if (!window || !menu) {
+ ERROR("Necessary objects are NULL.");
+ return EINA_FALSE;
+ }
+
+ window->context_menu.elm_menu = elm_menu_add(window->elm_window);
+
+ if (!window->context_menu.elm_menu) {
+ ERROR("Could not create menu widget.");
+ return EINA_FALSE;
+ }
+
+ window->context_menu.ewk_menu = menu;
+
+ context_menu_populate(window->context_menu.elm_menu, menu, NULL);
+
+ INFO("Showing context menu at (%d, %d).", x, y);
+ elm_menu_move(window->context_menu.elm_menu, x, y);
+ evas_object_show(window->context_menu.elm_menu);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_context_menu_hide(Ewk_View_Smart_Data *sd)
+{
+ Browser_Window *window = window_find_with_ewk_view(sd->self);
+
+ if (!window || !window->context_menu.elm_menu) {
+ ERROR("Necessary objects are NULL.");
+ return EINA_FALSE;
+ }
+
+ elm_menu_close(window->context_menu.elm_menu);
+ evas_object_del(window->context_menu.elm_menu);
+ window->context_menu.elm_menu = NULL;
+ window->context_menu.ewk_menu = NULL;
+
+ return EINA_TRUE;
+}
+
+static void
+auth_popup_close(Auth_Data *auth_data)
+{
+ ewk_object_unref(auth_data->request);
+ evas_object_del(auth_data->popup);
+ free(auth_data);
+}
+
+static void
+_auth_cancel_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Auth_Data *auth_data = (Auth_Data *)user_data;
+
+ ewk_auth_request_cancel(auth_data->request);
+
+ auth_popup_close(auth_data);
+}
+
+static void
+_auth_ok_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Auth_Data *auth_data = (Auth_Data *)user_data;
+
+ const char *username = elm_entry_entry_get(auth_data->username_entry);
+ const char *password = elm_entry_entry_get(auth_data->password_entry);
+ ewk_auth_request_authenticate(auth_data->request, username, password);
+
+ auth_popup_close(auth_data);
+}
+
+static void
+_authentication_request_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ Ewk_Auth_Request *request = ewk_object_ref((Ewk_Auth_Request *)event_info);
+
+ Auth_Data *auth_data = (Auth_Data *)malloc(sizeof(Auth_Data));
+ auth_data->request = request;
+
+ Evas_Object *auth_popup = elm_popup_add(window->elm_window);
+ auth_data->popup = auth_popup;
+ evas_object_size_hint_weight_set(auth_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_object_part_text_set(auth_popup, "title,text", "Authentication Required");
+
+ /* Popup Content */
+ Evas_Object *vbox = elm_box_add(auth_popup);
+ elm_box_padding_set(vbox, 0, 4);
+ evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(vbox, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_content_set(auth_popup, vbox);
+ evas_object_show(vbox);
+
+ /* Authentication message */
+ Evas_Object *label = elm_label_add(auth_popup);
+ elm_label_line_wrap_set(label, ELM_WRAP_WORD);
+ Eina_Strbuf *auth_text = eina_strbuf_new();
+ const char *host = ewk_auth_request_host_get(request);
+ const char *realm = ewk_auth_request_realm_get(request);
+ eina_strbuf_append_printf(auth_text, "A username and password are being requested by %s. The site says: \"%s\"", host, realm ? realm : "");
+ elm_object_text_set(label, eina_strbuf_string_get(auth_text));
+ eina_strbuf_free(auth_text);
+ evas_object_size_hint_weight_set(label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(label, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(vbox, label);
+ evas_object_show(label);
+
+ /* Credential table */
+ Evas_Object *table = elm_table_add(auth_popup);
+ elm_table_padding_set(table, 2, 2);
+ elm_table_homogeneous_set(table, EINA_TRUE);
+ evas_object_size_hint_weight_set(table, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(table, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(vbox, table);
+ evas_object_show(table);
+
+ /* Username row */
+ Evas_Object *username_label = elm_label_add(auth_popup);
+ elm_object_text_set(username_label, "Username:");
+ evas_object_size_hint_weight_set(username_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(username_label, 1, EVAS_HINT_FILL);
+ elm_table_pack(table, username_label, 0, 0, 1, 1);
+ evas_object_show(username_label);
+
+ Evas_Object *username_entry = elm_entry_add(auth_popup);
+ auth_data->username_entry = username_entry;
+ elm_entry_scrollable_set(username_entry, EINA_TRUE);
+ elm_entry_single_line_set(username_entry, EINA_TRUE);
+ elm_entry_text_style_user_push(username_entry, "DEFAULT='font_size=18'");
+ const char *suggested_username = ewk_auth_request_suggested_username_get(request);
+ elm_entry_entry_set(username_entry, suggested_username ? suggested_username : "");
+ evas_object_size_hint_weight_set(username_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(username_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_table_pack(table, username_entry, 1, 0, 2, 1);
+ elm_object_focus_set(username_entry, EINA_TRUE);
+ evas_object_show(username_entry);
+
+ /* Password row */
+ Evas_Object *password_label = elm_label_add(auth_popup);
+ elm_object_text_set(password_label, "Password:");
+ evas_object_size_hint_weight_set(password_label, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(password_label, 1, EVAS_HINT_FILL);
+ elm_table_pack(table, password_label, 0, 1, 1, 1);
+ evas_object_show(password_label);
+
+ Evas_Object *password_entry = elm_entry_add(auth_popup);
+ auth_data->password_entry = password_entry;
+ elm_entry_scrollable_set(password_entry, EINA_TRUE);
+ elm_entry_single_line_set(password_entry, EINA_TRUE);
+ elm_entry_password_set(password_entry, EINA_TRUE);
+ elm_entry_text_style_user_push(password_entry, "DEFAULT='font_size=18'");
+ evas_object_size_hint_weight_set(password_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(password_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_table_pack(table, password_entry, 1, 1, 2, 1);
+ evas_object_show(password_entry);
+
+ /* Popup buttons */
+ Evas_Object *cancel_button = elm_button_add(auth_popup);
+ elm_object_text_set(cancel_button, "Cancel");
+ elm_object_part_content_set(auth_popup, "button1", cancel_button);
+ evas_object_smart_callback_add(cancel_button, "clicked", _auth_cancel_cb, auth_data);
+ Evas_Object *ok_button = elm_button_add(auth_popup);
+ elm_object_text_set(ok_button, "OK");
+ elm_object_part_content_set(auth_popup, "button2", ok_button);
+ evas_object_smart_callback_add(ok_button, "clicked", _auth_ok_cb, auth_data);
+ evas_object_show(auth_popup);
+}
+
+static void
+_search_text_found_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ const int *match_count = (const int *)(event_info);
+
+ if (*match_count) {
+ Eina_Strbuf *search_text = eina_strbuf_new();
+ eina_strbuf_append_printf(search_text, " %d Matches Found " , *match_count);
+ elm_object_text_set(window->search.search_field_count, eina_strbuf_string_get(search_text));
+ eina_strbuf_free(search_text);
+ } else
+ elm_object_text_set(window->search.search_field_count, " No Matches Found");
+
+ evas_object_focus_set(window->ewk_view, EINA_FALSE);
+ elm_object_focus_set(window->search.search_field_count, EINA_FALSE);
+ elm_object_focus_set(window->search.search_field, EINA_TRUE);
+}
+
+static void
+_tooltip_text_set(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ const char *message = (const char*)event_info;
+
+ elm_object_tooltip_text_set(window->elm_window, message);
+ window->tooltip.text_set = EINA_TRUE;
+ window_tooltip_update(window);
+}
+
+static void
+_tooltip_text_unset(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ window_tooltip_hide(window);
+ elm_object_tooltip_unset(window->elm_window);
+ window->tooltip.text_set = EINA_FALSE;
+}
+
+static void
+_navigation_policy_decision_cb(void *user_data, Evas_Object *obj, void *event_info)
+{
+ Ewk_Navigation_Policy_Decision *decision = (Ewk_Navigation_Policy_Decision *)event_info;
+
+ if (ewk_navigation_policy_mouse_button_get(decision) == EWK_EVENT_MOUSE_BUTTON_MIDDLE) {
+ Browser_Window *window = window_create(NULL, 0, 0);
+ ewk_view_url_set(window->ewk_view, ewk_url_request_url_get(ewk_navigation_policy_request_get(decision)));
+ windows = eina_list_append(windows, window);
+ INFO("Mouse middle button pressed, open link in new window");
+
+ ewk_navigation_policy_decision_reject(decision);
+ }
+}
+
+static void
+_search_button_clicked_cb(void *user_data, Evas_Object *home_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ search_box_show(window);
+}
+
+static void
+_home_button_clicked_cb(void *user_data, Evas_Object *home_button, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+
+ ewk_view_url_set(window->ewk_view, DEFAULT_URL);
+}
+
+static void
+_window_deletion_cb(void *user_data, Evas_Object *elm_window, void *event_info)
+{
+ Browser_Window *window = (Browser_Window *)user_data;
+ ewk_view_try_close(window->ewk_view);
+}
+
+static Evas_Object *
+_create_toolbar_button(Evas_Object *elm_window, const char *icon_name)
+{
+ Evas_Object *button = elm_button_add(elm_window);
+
+ Evas_Object *icon = elm_icon_add(elm_window);
+ elm_icon_standard_set(icon, icon_name);
+ evas_object_size_hint_max_set(icon, TOOL_BAR_ICON_SIZE, TOOL_BAR_ICON_SIZE);
+ evas_object_color_set(icon, 0, 255, 255, 255);
+ evas_object_show(icon);
+ elm_object_part_content_set(button, "icon", icon);
+ evas_object_size_hint_min_set(button, TOOL_BAR_BUTTON_SIZE, TOOL_BAR_BUTTON_SIZE);
+
+ return button;
+}
+
+static Browser_Window *window_create(Ewk_View_Configuration* configuration, int width, int height)
+{
+ Browser_Window *window = calloc(1, sizeof(Browser_Window));
+ if (!window) {
+ ERROR("Could not create browser window.");
+ return NULL;
+ }
+
+ /* Initialize tooltip information */
+ window->tooltip.show_timer = NULL;
+ window->tooltip.activated = EINA_FALSE;
+ window->tooltip.text_set = EINA_FALSE;
+ window->tooltip.shown = EINA_FALSE;
+
+ /* Create window */
+ window->elm_window = elm_win_add(NULL, "minibrowser-window", ELM_WIN_BASIC);
+ elm_win_title_set(window->elm_window, APP_NAME);
+ evas_object_smart_callback_add(window->elm_window, "delete,request", _window_deletion_cb, window);
+
+ /* Create window background */
+ Evas_Object *bg = elm_bg_add(window->elm_window);
+ elm_bg_color_set(bg, 193, 192, 191);
+ evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(window->elm_window, bg);
+ evas_object_show(bg);
+
+ /* Create conformant widget. */
+ Evas_Object *conformant = elm_conformant_add(window->elm_window);
+ evas_object_size_hint_weight_set(conformant, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(window->elm_window, conformant);
+ evas_object_show(conformant);
+
+ /* Create vertical layout */
+ window->vertical_layout = elm_box_add(window->elm_window);
+ elm_object_content_set(conformant, window->vertical_layout);
+ elm_box_padding_set(window->vertical_layout, 0, 2);
+ evas_object_size_hint_weight_set(window->vertical_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_show(window->vertical_layout);
+
+ /* Create horizontal layout for top bar */
+ window->horizontal_layout = elm_box_add(window->elm_window);
+ elm_box_horizontal_set(window->horizontal_layout, EINA_TRUE);
+ evas_object_size_hint_weight_set(window->horizontal_layout, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(window->horizontal_layout, EVAS_HINT_FILL, 0.0);
+ elm_box_pack_end(window->vertical_layout, window->horizontal_layout);
+ evas_object_show(window->horizontal_layout);
+
+ /* Create Back button */
+ window->back_button = _create_toolbar_button(window->elm_window, "arrow_left");
+ evas_object_smart_callback_add(window->back_button, "clicked", _back_button_clicked_cb, window);
+ evas_object_smart_callback_add(window->back_button, "repeated", _back_button_longpress_cb, window);
+ elm_object_tooltip_text_set(window->back_button, "Click to go back, longpress to see session history");
+ elm_object_tooltip_window_mode_set(window->back_button, EINA_TRUE);
+ elm_object_disabled_set(window->back_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(window->back_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->back_button, 0.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, window->back_button);
+ evas_object_show(window->back_button);
+
+ /* Create Forward button */
+ window->forward_button = _create_toolbar_button(window->elm_window, "arrow_right");
+ evas_object_smart_callback_add(window->forward_button, "clicked", _forward_button_clicked_cb, window);
+ evas_object_smart_callback_add(window->forward_button, "repeated", _forward_button_longpress_cb, window);
+ elm_object_tooltip_text_set(window->forward_button, "Click to go forward, longpress to see session history");
+ elm_object_tooltip_window_mode_set(window->forward_button, EINA_TRUE);
+ elm_object_disabled_set(window->forward_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(window->forward_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->forward_button, 0.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, window->forward_button);
+ evas_object_show(window->forward_button);
+
+ /* Create Search button */
+ Evas_Object *search_button = _create_toolbar_button(window->elm_window, "toolbar/search");
+ evas_object_smart_callback_add(search_button, "clicked", _search_button_clicked_cb, window);
+ elm_object_tooltip_text_set(search_button, "Find text");
+ elm_object_tooltip_window_mode_set(search_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(search_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(search_button, 1.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, search_button);
+ evas_object_show(search_button);
+
+ /* Create URL bar */
+ window->url_bar = elm_entry_add(window->elm_window);
+ elm_entry_scrollable_set(window->url_bar, EINA_TRUE);
+ elm_scroller_policy_set(window->url_bar, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+ elm_entry_single_line_set(window->url_bar, EINA_TRUE);
+ elm_entry_cnp_mode_set(window->url_bar, ELM_CNP_MODE_PLAINTEXT);
+ elm_entry_text_style_user_push(window->url_bar, "DEFAULT='font_size=18'");
+ evas_object_smart_callback_add(window->url_bar, "activated", _url_bar_activated_cb, window);
+ evas_object_smart_callback_add(window->url_bar, "clicked", _url_bar_clicked_cb, window);
+ evas_object_size_hint_weight_set(window->url_bar, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->url_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(window->horizontal_layout, window->url_bar);
+ evas_object_show(window->url_bar);
+
+ /* Create Refresh button */
+ Evas_Object *refresh_button = _create_toolbar_button(window->elm_window, "refresh");
+ evas_object_smart_callback_add(refresh_button, "clicked", _refresh_button_clicked_cb, window);
+ elm_object_tooltip_text_set(refresh_button, "Reload page");
+ elm_object_tooltip_window_mode_set(refresh_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(refresh_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(refresh_button, 1.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, refresh_button);
+ evas_object_show(refresh_button);
+
+ /* Create Stop button */
+ Evas_Object *stop_button = _create_toolbar_button(window->elm_window, "close");
+ evas_object_smart_callback_add(stop_button, "clicked", _stop_button_clicked_cb, window);
+ elm_object_tooltip_text_set(stop_button, "Stop page load");
+ elm_object_tooltip_window_mode_set(stop_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(stop_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(stop_button, 1.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, stop_button);
+ evas_object_show(stop_button);
+
+ /* Create Home button */
+ Evas_Object *home_button = _create_toolbar_button(window->elm_window, "home");
+ evas_object_smart_callback_add(home_button, "clicked", _home_button_clicked_cb, window);
+ elm_object_tooltip_text_set(home_button, "Home page");
+ elm_object_tooltip_window_mode_set(home_button, EINA_TRUE);
+ evas_object_size_hint_weight_set(home_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(home_button, 1.0, 0.5);
+ elm_box_pack_end(window->horizontal_layout, home_button);
+ evas_object_show(home_button);
+
+ /* Create Search bar */
+ window->search.search_bar = elm_box_add(window->elm_window);
+ elm_box_horizontal_set(window->search.search_bar, EINA_TRUE);
+ evas_object_size_hint_min_set(window->search.search_bar, SEARCH_FIELD_SIZE + 2 * SEARCH_BUTTON_SIZE, 0);
+ evas_object_size_hint_align_set(window->search.search_bar, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(window->vertical_layout, window->search.search_bar);
+
+ /* Create Search field */
+ window->search.search_field = elm_entry_add(window->elm_window);
+ elm_entry_scrollable_set(window->search.search_field, EINA_TRUE);
+ elm_scroller_policy_set(window->search.search_field, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
+ elm_entry_single_line_set(window->search.search_field, EINA_TRUE);
+ elm_entry_cnp_mode_set(window->search.search_field, ELM_CNP_MODE_PLAINTEXT);
+ elm_entry_text_style_user_push(window->search.search_field, "DEFAULT='font_size=14'");
+ evas_object_smart_callback_add(window->search.search_field, "activated", _search_field_activated_cb, window);
+ evas_object_smart_callback_add(window->search.search_field, "changed", _search_field_activated_cb, window);
+ evas_object_smart_callback_add(window->search.search_field, "aborted", _search_field_aborted_cb, window);
+ evas_object_smart_callback_add(window->search.search_field, "clicked", _search_field_clicked_cb, window);
+ evas_object_size_hint_weight_set(window->search.search_field, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->search.search_field, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(window->search.search_bar, window->search.search_field);
+
+ /* Create Search backward button */
+ window->search.backward_button = _create_toolbar_button(window->elm_window, "arrow_up");
+ evas_object_smart_callback_add(window->search.backward_button, "clicked", _search_backward_button_clicked_cb, window);
+ elm_object_disabled_set(window->search.backward_button, EINA_FALSE);
+ evas_object_size_hint_weight_set(window->search.backward_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->search.backward_button, 1.0, 0.5);
+ evas_object_size_hint_min_set(window->search.backward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
+ elm_box_pack_end(window->search.search_bar, window->search.backward_button);
+
+ /* Create Search forwardward button */
+ window->search.forward_button = _create_toolbar_button(window->elm_window, "arrow_down");
+ evas_object_smart_callback_add(window->search.forward_button, "clicked", _search_forward_button_clicked_cb, window);
+ elm_object_disabled_set(window->search.forward_button, EINA_FALSE);
+ evas_object_size_hint_weight_set(window->search.forward_button, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->search.forward_button, 1.0, 0.5);
+ evas_object_size_hint_min_set(window->search.forward_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
+ elm_box_pack_end(window->search.search_bar, window->search.forward_button);
+
+ /* Create Search count field */
+ window->search.search_field_count = elm_label_add(window->elm_window);
+ evas_object_size_hint_weight_set(window->search.search_field_count, 0.0, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->search.search_field_count, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_object_text_set(window->search.search_field_count, "");
+ elm_box_pack_end(window->search.search_bar, window->search.search_field_count);
+
+ /* Create Search Case Sensitive Option check box */
+ window->search.search_case_check_box = elm_check_add(window->elm_window);
+ elm_object_text_set(window->search.search_case_check_box, "Case Sensitive");
+ evas_object_smart_callback_add(window->search.search_case_check_box, "changed", _search_case_option_changed, window);
+ elm_box_pack_end(window->search.search_bar, window->search.search_case_check_box);
+
+ /* Create Search Word Start Option check box */
+ window->search.search_word_start_check_box = elm_check_add(window->elm_window);
+ elm_object_text_set(window->search.search_word_start_check_box, "Only Word Start");
+ evas_object_smart_callback_add(window->search.search_word_start_check_box, "changed", _search_word_start_option_changed_cb, window);
+ elm_box_pack_end(window->search.search_bar, window->search.search_word_start_check_box);
+
+ /* Create Search close button */
+ window->search.close_button = _create_toolbar_button(window->elm_window, "close");
+ evas_object_smart_callback_add(window->search.close_button, "clicked", _search_close_button_clicked_cb, window);
+ elm_object_disabled_set(window->search.close_button, EINA_FALSE);
+ evas_object_size_hint_weight_set(window->search.close_button, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->search.close_button, 1.0, 0.5);
+ evas_object_size_hint_min_set(window->search.close_button, SEARCH_BUTTON_SIZE, SEARCH_BUTTON_SIZE);
+ elm_box_pack_end(window->search.search_bar, window->search.close_button);
+
+ /* Create history box */
+ window->history.history_box = elm_box_add(window->elm_window);
+ evas_object_size_hint_aspect_set(window->history.history_box, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+ evas_object_size_hint_weight_set(window->history.history_box, EVAS_HINT_EXPAND , EVAS_HINT_EXPAND);
+
+ /* Create history list */
+ window->history.history_list = elm_genlist_add(window->elm_window);
+ evas_object_size_hint_weight_set(window->history.history_list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->history.history_list, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_win_resize_object_add(window->elm_window, window->history.history_box);
+ elm_box_pack_end(window->history.history_box, window->history.history_list);
+
+ /* Create ewk_view */
+ Ewk_View_Smart_Class *ewkViewClass = miniBrowserViewSmartClass();
+ ewkViewClass->run_javascript_alert = _javascript_alert_cb;
+ ewkViewClass->run_javascript_confirm = _javascript_confirm_cb;
+ ewkViewClass->run_javascript_prompt = _javascript_prompt_cb;
+ ewkViewClass->run_javascript_before_unload_confirm = _javascript_before_unload_confirm_cb;
+ ewkViewClass->window_geometry_get = _window_geometry_get;
+ ewkViewClass->window_geometry_set = _window_geometry_set;
+ ewkViewClass->fullscreen_enter = _fullscreen_enter_cb;
+ ewkViewClass->fullscreen_exit = _fullscreen_exit_cb;
+ ewkViewClass->window_create = _window_create_cb;
+ ewkViewClass->window_close = _window_close_cb;
+ ewkViewClass->popup_menu_show = _popup_menu_show;
+ ewkViewClass->popup_menu_hide = _popup_menu_hide;
+ ewkViewClass->context_menu_show = _context_menu_show;
+ ewkViewClass->context_menu_hide = _context_menu_hide;
+ ewkViewClass->input_picker_color_request = _color_picker_request_cb;
+ ewkViewClass->input_picker_color_dismiss = _color_picker_dismiss_cb;
+
+ Evas *evas = evas_object_evas_get(window->elm_window);
+ Evas_Smart *smart = evas_smart_class_new(&ewkViewClass->sc);
+ window->ewk_view = ewk_view_add_with_configuration(evas, smart, configuration);
+
+ Ewk_Context *context = ewk_view_context_get(window->ewk_view);
+ ewk_favicon_database_icon_change_callback_add(ewk_context_favicon_database_get(context), _icon_changed_cb, window);
+
+ ewk_view_theme_set(window->ewk_view, DEFAULT_THEME_DIR "/default.edj");
+ if (device_pixel_ratio)
+ ewk_view_device_pixel_ratio_set(window->ewk_view, (float)device_pixel_ratio);
+ ewk_view_user_agent_set(window->ewk_view, user_agent_string);
+ ewk_view_layout_fixed_set(window->ewk_view, fixed_layout_enabled);
+
+ if (touch_events_enabled) {
+ ewk_view_touch_events_enabled_set(window->ewk_view, EINA_TRUE);
+ ewk_view_mouse_events_enabled_set(window->ewk_view, EINA_FALSE);
+ }
+
+ if (background_color_string) {
+ int red, green, blue, alpha;
+
+ if (sscanf(background_color_string, "%d:%d:%d:%d", &red, &green, &blue, &alpha))
+ ewk_view_bg_color_set(window->ewk_view, red, green, blue, alpha);
+ }
+
+ /* Set the zoom level to default */
+ window->current_zoom_level = DEFAULT_ZOOM_LEVEL;
+
+ elm_win_fullscreen_set(window->elm_window, fullscreen_enabled);
+
+ evas_object_smart_callback_add(window->ewk_view, "authentication,request", _authentication_request_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "file,chooser,request", _file_chooser_request_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "load,error", _error_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "load,provisional,failed", _error_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "load,progress", _progress_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "title,changed", _title_changed_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "url,changed", _url_changed_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "back,forward,list,changed", _back_forward_list_changed_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "text,found", _search_text_found_cb, window);
+ evas_object_smart_callback_add(window->ewk_view, "tooltip,text,set", _tooltip_text_set, window);
+ evas_object_smart_callback_add(window->ewk_view, "tooltip,text,unset", _tooltip_text_unset, window);
+ evas_object_smart_callback_add(window->ewk_view, "policy,decision,navigation", _navigation_policy_decision_cb, window);
+
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, window);
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, window);
+
+ evas_object_size_hint_weight_set(window->ewk_view, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(window->ewk_view, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_before(window->vertical_layout, window->ewk_view, window->search.search_bar);
+ evas_object_show(window->ewk_view);
+
+ evas_object_resize(window->elm_window, width ? width : window_width, height ? height : window_height);
+ evas_object_show(window->elm_window);
+ search_box_hide(window);
+
+ view_focus_set(window, EINA_TRUE);
+ // Prevent window from stealing web view's focus on start up.
+ elm_object_focus_allow_set(window->elm_window, EINA_FALSE);
+
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_IN, _mouse_in_cb, window);
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_OUT, _mouse_out_cb, window);
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, window);
+ evas_object_event_callback_add(window->ewk_view, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, window);
+ evas_object_event_callback_add(window->elm_window, EVAS_CALLBACK_RESIZE, _window_resize_cb, window);
+
+ elm_button_autorepeat_set(window->back_button, EINA_TRUE);
+ elm_button_autorepeat_set(window->forward_button, EINA_TRUE);
+ elm_button_autorepeat_initial_timeout_set(window->back_button, LONGPRESS_INTERVAL_SECONDS);
+ elm_button_autorepeat_initial_timeout_set(window->forward_button, LONGPRESS_INTERVAL_SECONDS);
+
+ return window;
+}
+
+static Ewk_View_Configuration* configuration()
+{
+ static Ewk_View_Configuration* default_configuration = 0;
+
+ if (default_configuration)
+ return default_configuration;
+
+ default_configuration = ewk_view_configuration_new();
+
+ Ewk_Settings* settings = ewk_view_configuration_settings_get(default_configuration);
+ ewk_settings_file_access_from_file_urls_allowed_set(settings, EINA_TRUE);
+ ewk_settings_encoding_detector_enabled_set(settings, encoding_detector_enabled);
+ ewk_settings_frame_flattening_enabled_set(settings, frame_flattening_enabled);
+ ewk_settings_local_storage_enabled_set(settings, local_storage_enabled);
+ ewk_settings_offline_web_application_cache_enabled_set(settings, offline_web_application_cache_enabled);
+ INFO("HTML5 local storage is %s for this view.", local_storage_enabled ? "enabled" : "disabled");
+ ewk_settings_developer_extras_enabled_set(settings, EINA_TRUE);
+ ewk_settings_preferred_minimum_contents_width_set(settings, 0);
+ ewk_text_checker_continuous_spell_checking_enabled_set(spell_checking_enabled);
+ ewk_settings_web_security_enabled_set(settings, web_security_enabled);
+
+ return default_configuration;
+}
+
+static Ewk_Cookie_Accept_Policy
+parse_cookies_policy(const char *input_string)
+{
+ if (!strcmp(input_string, "always"))
+ return EWK_COOKIE_ACCEPT_POLICY_ALWAYS;
+ if (!strcmp(input_string, "never"))
+ return EWK_COOKIE_ACCEPT_POLICY_NEVER;
+ if (strcmp(input_string, "no-third-party"))
+ INFO("Unrecognized type for cookies policy: %s.", input_string);
+ return EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY;
+}
+
+static void
+parse_window_size(const char *input_string, int *width, int *height)
+{
+ static const unsigned max_length = 4;
+ int parsed_width;
+ int parsed_height;
+ char **arr;
+ unsigned elements;
+
+ arr = eina_str_split_full(input_string, "x", 0, &elements);
+
+ if (elements == 2 && (strlen(arr[0]) <= max_length) && (strlen(arr[1]) <= max_length)) {
+ parsed_width = atoi(arr[0]);
+ if (width && parsed_width)
+ *width = parsed_width;
+
+ parsed_height = atoi(arr[1]);
+ if (height && parsed_height)
+ *height = parsed_height;
+ }
+
+ free(arr[0]);
+ free(arr);
+}
+
+EAPI_MAIN int
+elm_main(int argc, char *argv[])
+{
+ int args = 1;
+ unsigned char quitOption = 0;
+ Browser_Window *window;
+ char *window_size_string = NULL;
+ char *cookies_policy_string = NULL;
+
+ Ecore_Getopt_Value values[] = {
+ ECORE_GETOPT_VALUE_STR(evas_engine_name),
+ ECORE_GETOPT_VALUE_STR(window_size_string),
+ ECORE_GETOPT_VALUE_STR(user_agent_string),
+ ECORE_GETOPT_VALUE_STR(extensions_path),
+ ECORE_GETOPT_VALUE_DOUBLE(device_pixel_ratio),
+ ECORE_GETOPT_VALUE_BOOL(quitOption),
+ ECORE_GETOPT_VALUE_BOOL(encoding_detector_enabled),
+ ECORE_GETOPT_VALUE_STR(background_color_string),
+ ECORE_GETOPT_VALUE_BOOL(frame_flattening_enabled),
+ ECORE_GETOPT_VALUE_BOOL(local_storage_enabled),
+ ECORE_GETOPT_VALUE_BOOL(offline_web_application_cache_enabled),
+ ECORE_GETOPT_VALUE_BOOL(fullscreen_enabled),
+ ECORE_GETOPT_VALUE_BOOL(spell_checking_enabled),
+ ECORE_GETOPT_VALUE_BOOL(touch_events_enabled),
+ ECORE_GETOPT_VALUE_BOOL(fixed_layout_enabled),
+ ECORE_GETOPT_VALUE_STR(cookies_policy_string),
+ ECORE_GETOPT_VALUE_BOOL(web_security_enabled),
+ ECORE_GETOPT_VALUE_BOOL(separated_process_enabled),
+ ECORE_GETOPT_VALUE_BOOL(quitOption),
+ ECORE_GETOPT_VALUE_BOOL(quitOption),
+ ECORE_GETOPT_VALUE_BOOL(quitOption),
+ ECORE_GETOPT_VALUE_NONE
+ };
+
+ efreet_cache_update = 0;
+
+ if (!ewk_init())
+ return EXIT_FAILURE;
+
+ _log_domain_id = eina_log_domain_register("minibrowser", EINA_COLOR_YELLOW);
+
+ ewk_view_smart_class_set(miniBrowserViewSmartClass());
+
+ ecore_app_args_set(argc, (const char **) argv);
+ args = ecore_getopt_parse(&options, values, argc, argv);
+
+ if (args < 0)
+ return quit(EINA_FALSE, "Could not parse options.");
+
+ if (quitOption)
+ return quit(EINA_TRUE, NULL);
+
+ if (evas_engine_name)
+ elm_config_accel_preference_set(evas_engine_name);
+ else {
+ evas_engine_name = "opengl:depth24:stencil8";
+ elm_config_accel_preference_set(evas_engine_name);
+ }
+
+ Ewk_Context *context = ewk_context_default_get();
+
+ if (separated_process_enabled)
+ ewk_context_web_process_count_limit_set(context, 0);
+
+ // Enable favicon database.
+ ewk_context_favicon_database_directory_set(context, NULL);
+
+ // Use a proper cache model.
+ ewk_context_cache_model_set(context, EWK_CACHE_MODEL_PRIMARY_WEBBROWSER);
+
+ if (cookies_policy_string) {
+ Ewk_Cookie_Accept_Policy cookie_policy = parse_cookies_policy(cookies_policy_string);
+ ewk_cookie_manager_accept_policy_set(ewk_context_cookie_manager_get(context), cookie_policy);
+
+ if (cookie_policy == EWK_COOKIE_ACCEPT_POLICY_ALWAYS) {
+ const char cookie_storage_directory[] = "/tmp/ewebkit2_minibrowser_cookie/";
+ mkdir(cookie_storage_directory, S_IRWXU);
+ char storage_name[64];
+ snprintf(storage_name, sizeof(storage_name), "%stxt-cookie", cookie_storage_directory);
+ ewk_cookie_manager_persistent_storage_set(ewk_context_cookie_manager_get(context), storage_name, EWK_COOKIE_PERSISTENT_STORAGE_TEXT);
+ }
+ }
+
+ if (window_size_string)
+ parse_window_size(window_size_string, &window_width, &window_height);
+
+ window = window_create(configuration(), 0, 0);
+ if (!window)
+ return quit(EINA_FALSE, "Could not create browser window.");
+
+ // Set callbacks for download events.
+ ewk_context_download_callbacks_set(context, _download_request_cb, _download_failed_cb, 0, _download_finished_cb, window);
+
+ if (args < argc) {
+ char *url = url_from_user_input(argv[args]);
+ url_load_from_user_input(window->ewk_view, url);
+ free(url);
+ } else
+ ewk_view_url_set(window->ewk_view, DEFAULT_URL);
+
+ windows = eina_list_append(windows, window);
+
+ elm_run();
+
+ return quit(EINA_TRUE, NULL);
+}
+ELM_MAIN()
+
</ins></span></pre></div>
<a id="trunkToolsScriptsrunefltests"></a>
<div class="addfile"><h4>Added: trunk/Tools/Scripts/run-efl-tests (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-efl-tests         (rev 0)
+++ trunk/Tools/Scripts/run-efl-tests        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+#!/usr/bin/perl -w
+# Copyright (C) 2012 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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.
+# * Neither the name of Intel Corporation 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 THE COPYRIGHT HOLDERS AND 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
+# OWNER OR 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.
+
+use strict;
+use FindBin;
+use lib $FindBin::Bin;
+use webkitdirs;
+
+my $xvfb_display = ":55";
+
+my $xvfb_pid = fork();
+exit(1) if not defined $xvfb_pid;
+
+# Tell CTest to dump gtest output in case of failure.
+$ENV{CTEST_OUTPUT_ON_FAILURE} = "1";
+$ENV{DISPLAY} = $xvfb_display;
+
+if ($xvfb_pid == 0) {
+ # Start Xvfb
+ my @xvfb_args = ( "Xvfb $xvfb_display -screen 0 800x600x24 -nolisten tcp > /dev/null 2>&1" );
+ exec(@xvfb_args);
+} else {
+ setConfiguration();
+
+ # Manually add this for jhbuildWrapperPrefixIfNeeded().
+ push(@ARGV, "--efl");
+
+ my $returnCode = exitStatus(generateBuildSystemFromCMakeProject(undef, cmakeBasedPortArguments()));
+ exit($returnCode) if $returnCode;
+
+ $returnCode = exitStatus(buildCMakeGeneratedProject("test"));
+
+ # Kill Xvfb
+ kill(15, $xvfb_pid);
+
+ exit($returnCode);
+}
+
</ins><span class="cx">Property changes on: trunk/Tools/Scripts/run-efl-tests
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<ins>+*
</ins><span class="cx">\ No newline at end of property
</span><a id="trunkToolsScriptsupdatewebkitefllibs"></a>
<div class="addfile"><h4>Added: trunk/Tools/Scripts/update-webkitefl-libs (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/update-webkitefl-libs         (rev 0)
+++ trunk/Tools/Scripts/update-webkitefl-libs        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+#!/usr/bin/perl -w
+# Copyright (C) 2012 Intel Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+use FindBin;
+use lib $FindBin::Bin;
+use webkitdirs;
+
+my $scriptsDir = relativeScriptsDir();
+system("perl", "$scriptsDir/update-webkit-libs-jhbuild", "--efl", @ARGV) == 0 or die $!;
</ins><span class="cx">Property changes on: trunk/Tools/Scripts/update-webkitefl-libs
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<ins>+*
</ins><span class="cx">\ No newline at end of property
</span><a id="trunkToolsScriptswebkitpyporteflpy"></a>
<div class="addfile"><h4>Added: trunk/Tools/Scripts/webkitpy/port/efl.py (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/port/efl.py         (rev 0)
+++ trunk/Tools/Scripts/webkitpy/port/efl.py        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,146 @@
</span><ins>+# Copyright (C) 2011 ProFUSION Embedded Systems. All rights reserved.
+# Copyright (C) 2011 Samsung Electronics. All rights reserved.
+# Copyright (C) 2012 Intel Corporation
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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 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
+# OWNER OR 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.
+
+"""WebKit Efl implementation of the Port interface."""
+
+import os
+
+from webkitpy.common.system import path
+from webkitpy.layout_tests.models.test_configuration import TestConfiguration
+from webkitpy.port.base import Port
+from webkitpy.port.pulseaudio_sanitizer import PulseAudioSanitizer
+from webkitpy.port.xorgdriver import XorgDriver
+from webkitpy.port.xvfbdriver import XvfbDriver
+from webkitpy.port.linux_get_crash_log import GDBCrashLogGenerator
+
+
+class EflPort(Port):
+ port_name = 'efl'
+
+ def __init__(self, *args, **kwargs):
+ super(EflPort, self).__init__(*args, **kwargs)
+
+ self._jhbuild_wrapper = [self.path_from_webkit_base('Tools', 'jhbuild', 'jhbuild-wrapper'), '--efl', 'run']
+
+ self.set_option_default('wrapper', ' '.join(self._jhbuild_wrapper))
+ self.webprocess_cmd_prefix = self.get_option('webprocess_cmd_prefix')
+
+ self._pulseaudio_sanitizer = PulseAudioSanitizer()
+
+ def _port_flag_for_scripts(self):
+ return "--efl"
+
+ def setup_test_run(self, device_class=None):
+ super(EflPort, self).setup_test_run(device_class)
+ self._pulseaudio_sanitizer.unload_pulseaudio_module()
+
+ def setup_environ_for_server(self, server_name=None):
+ env = super(EflPort, self).setup_environ_for_server(server_name)
+
+ # If DISPLAY environment variable is unset in the system
+ # e.g. on build bot, remove DISPLAY variable from the dictionary
+ if not 'DISPLAY' in os.environ:
+ del env['DISPLAY']
+
+ if 'ACCESSIBILITY_EAIL_LIBRARY_PATH' in os.environ:
+ env['ACCESSIBILITY_EAIL_LIBRARY_PATH'] = os.environ['ACCESSIBILITY_EAIL_LIBRARY_PATH']
+
+ env['TEST_RUNNER_INJECTED_BUNDLE_FILENAME'] = self._build_path('lib', 'libTestRunnerInjectedBundle.so')
+ env['TEST_RUNNER_PLUGIN_PATH'] = self._build_path('lib', 'plugins')
+
+ # Silence GIO warnings about using the "memory" GSettings backend.
+ env['GSETTINGS_BACKEND'] = 'memory'
+
+ if self.webprocess_cmd_prefix:
+ env['WEB_PROCESS_CMD_PREFIX'] = self.webprocess_cmd_prefix
+
+ return env
+
+ def default_timeout_ms(self):
+ # Tests run considerably slower under gdb
+ # or valgrind.
+ if self.get_option('webprocess_cmd_prefix'):
+ return 350 * 1000
+ return super(EflPort, self).default_timeout_ms()
+
+ def clean_up_test_run(self):
+ super(EflPort, self).clean_up_test_run()
+ self._pulseaudio_sanitizer.restore_pulseaudio_module()
+
+ def _generate_all_test_configurations(self):
+ return [TestConfiguration(version=self._version, architecture='x86', build_type=build_type) for build_type in self.ALL_BUILD_TYPES]
+
+ def _driver_class(self):
+ if os.environ.get("USE_NATIVE_XDISPLAY"):
+ return XorgDriver
+ return XvfbDriver
+
+ def _path_to_driver(self):
+ return self._build_path('bin', self.driver_name())
+
+ def _path_to_image_diff(self):
+ return self._build_path('bin', 'ImageDiff')
+
+ def _image_diff_command(self, *args, **kwargs):
+ return self._jhbuild_wrapper + super(EflPort, self)._image_diff_command(*args, **kwargs)
+
+ def _path_to_webcore_library(self):
+ static_path = self._build_path('lib', 'libwebcore_efl.a')
+ dyn_path = self._build_path('lib', 'libwebcore_efl.so')
+ return static_path if self._filesystem.exists(static_path) else dyn_path
+
+ def _search_paths(self):
+ search_paths = []
+ search_paths.append(self.port_name)
+ search_paths.append('wk2')
+ return search_paths
+
+ def default_baseline_search_path(self):
+ return map(self._webkit_baseline_path, self._search_paths())
+
+ def _port_specific_expectations_files(self):
+ # FIXME: We should be able to use the default algorithm here.
+ return list(reversed([self._filesystem.join(self._webkit_baseline_path(p), 'TestExpectations') for p in self._search_paths()]))
+
+ def show_results_html_file(self, results_filename):
+ self._run_script("run-minibrowser", [path.abspath_to_uri(self.host.platform, results_filename)])
+
+ def check_sys_deps(self, needs_http):
+ return super(EflPort, self).check_sys_deps(needs_http) and self._driver_class().check_driver(self)
+
+ def build_webkit_command(self, build_style=None):
+ command = super(EflPort, self).build_webkit_command(build_style)
+ command.extend(["--efl", "--update-efl"])
+ command.append(super(EflPort, self).make_args())
+ return command
+
+ def _get_crash_log(self, name, pid, stdout, stderr, newer_than):
+ return GDBCrashLogGenerator(name, pid, newer_than, self._filesystem, self._path_to_driver).generate_crash_log(stdout, stderr)
+
+ def test_expectations_file_position(self):
+ # EFL port baseline search path is efl -> wk2 -> generic (as efl-wk2 and efl baselines are merged), so port test expectations file is at third to last position.
+ return 2
</ins></span></pre></div>
<a id="trunkToolsScriptswebkitpyportefl_unittestpy"></a>
<div class="addfile"><h4>Added: trunk/Tools/Scripts/webkitpy/port/efl_unittest.py (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/webkitpy/port/efl_unittest.py         (rev 0)
+++ trunk/Tools/Scripts/webkitpy/port/efl_unittest.py        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+# Copyright (C) 2011 ProFUSION Embedded Systems. All rights reserved.
+# Copyright (C) 2011 Samsung Electronics. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * 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 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
+# OWNER OR 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.
+
+import unittest
+
+from webkitpy.common.system.executive_mock import MockExecutive
+from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.port.efl import EflPort
+from webkitpy.port.pulseaudio_sanitizer_mock import PulseAudioSanitizerMock
+from webkitpy.port import port_testcase
+
+
+class EflPortTest(port_testcase.PortTestCase):
+ port_name = 'efl'
+ port_maker = EflPort
+
+ # Additionally mocks out the PulseAudioSanitizer methods.
+ def make_port(self, host=None, port_name=None, options=None, os_name=None, os_version=None, **kwargs):
+ port = super(EflPortTest, self).make_port(host, port_name, options, os_name, os_version, **kwargs)
+ port._pulseaudio_sanitizer = PulseAudioSanitizerMock()
+ return port
+
+ def test_show_results_html_file(self):
+ port = self.make_port()
+ port._executive = MockExecutive(should_log=True)
+ expected_logs = "MOCK run_command: ['Tools/Scripts/run-minibrowser', '--release', '--efl', 'file://test.html'], cwd=/mock-checkout\n"
+ OutputCapture().assert_outputs(self, port.show_results_html_file, ["test.html"], expected_logs=expected_logs)
+
+ def test_get_crash_log(self):
+ # This function tested in linux_get_crash_log_unittest.py
+ pass
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2eflWKViewClientWebProcessCallbackscpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+/*
+ * Copyright (C) 2013 Intel Corporation. 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. 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 ``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
+ * 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 "ewk_view_private.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include "WKView.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+struct TestStatesData {
+ TestStatesData(WKViewRef view, WKURLRef url)
+ : view(view)
+ , url(url)
+ , didFinishLoad(false)
+ , didCrash(false)
+ , didRelaunch(false)
+ {
+ }
+
+ WKViewRef view;
+ WKURLRef url;
+ bool didFinishLoad;
+ bool didCrash;
+ bool didRelaunch;
+};
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void* clientInfo)
+{
+ TestStatesData* states = const_cast<TestStatesData*>(static_cast<const TestStatesData*>(clientInfo));
+ states->didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page, const void* clientInfo)
+{
+ WKPageLoaderClientV3 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 3;
+ loaderClient.base.clientInfo = clientInfo;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+void webProcessCrashed(WKViewRef view, WKURLRef url, const void* clientInfo)
+{
+ TestStatesData* states = const_cast<TestStatesData*>(static_cast<const TestStatesData*>(clientInfo));
+
+ EXPECT_EQ(states->view, view);
+ EXPECT_TRUE(WKURLIsEqual(url, states->url));
+
+ states->didCrash = true;
+}
+
+void webProcessDidRelaunch(WKViewRef view, const void* clientInfo)
+{
+ TestStatesData* states = const_cast<TestStatesData*>(static_cast<const TestStatesData*>(clientInfo));
+
+ EXPECT_EQ(states->view, view);
+
+ states->didRelaunch = true;
+}
+
+static void setViewClient(WKViewRef view, const void* clientInfo)
+{
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(WKViewClientV0));
+
+ viewClient.base.version = 0;
+ viewClient.base.clientInfo = clientInfo;
+ viewClient.webProcessCrashed = webProcessCrashed;
+ viewClient.webProcessDidRelaunch = webProcessDidRelaunch;
+
+ WKViewSetViewClient(view, &viewClient.base);
+}
+
+TEST(WebKit2, WKViewClientWebProcessCallbacks)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WKViewClientWebProcessCallbacksTest"));
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+
+ PlatformWebView view(context.get());
+ WKViewRef wkView = EWKViewGetWKView(view.platformView());
+
+ TestStatesData states = TestStatesData(wkView, url.get());
+
+ setPageLoaderClient(view.page(), &states);
+ setViewClient(wkView, &states);
+
+ WKPageLoadURL(view.page(), url.get());
+ Util::run(&states.didFinishLoad);
+
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("Crash").get(), 0);
+ Util::run(&states.didCrash);
+
+ WKPageReload(view.page());
+ Util::run(&states.didRelaunch);
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2eflWKViewClientWebProcessCallbacks_Bundlecpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks_Bundle.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks_Bundle.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewClientWebProcessCallbacks_Bundle.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 ``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
+ * 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 "InjectedBundleTest.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+class WKViewClientWebProcessCallbacksTest : public InjectedBundleTest {
+public:
+ WKViewClientWebProcessCallbacksTest(const std::string& identifier);
+
+private:
+ virtual void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody);
+};
+
+static InjectedBundleTest::Register<WKViewClientWebProcessCallbacksTest> registrar("WKViewClientWebProcessCallbacksTest");
+
+WKViewClientWebProcessCallbacksTest::WKViewClientWebProcessCallbacksTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void WKViewClientWebProcessCallbacksTest::didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef)
+{
+ if (!WKStringIsEqualToUTF8CString(messageName, "Crash"))
+ return;
+
+ // Simulating a crash
+ abort();
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2eflWKViewScrollTocpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewScrollTo.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewScrollTo.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/WKViewScrollTo.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+/*
+ * Copyright (C) 2014 Samsung Electronics. 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. 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 ``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
+ * 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 "ewk_view_private.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKRetainPtr.h>
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool finishedLoad = false;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ finishedLoad = true;
+}
+
+TEST(WebKit2, WKViewScrollTo)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+ WKRetainPtr<WKViewRef> view = EWKViewGetWKView(webView.platformView());
+
+ WKPageSetUseFixedLayout(webView.page(), true);
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(viewClient));
+ viewClient.base.version = 0;
+ viewClient.didChangeContentsPosition = 0;
+ WKViewSetViewClient(view.get(), &viewClient.base);
+
+ // Load page.
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("efl/scrollTo", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&finishedLoad);
+
+ WKPoint currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(100, currentPagePosition.x);
+ EXPECT_EQ(300, currentPagePosition.y);
+}
+
+} // TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2eflscrollTohtml"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/scrollTo.html (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/scrollTo.html         (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2/efl/scrollTo.html        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+<html>
+<body style="width:2000px;height:2000px;">
+scrollTo Test
+<script>
+window.scrollTo(100, 300);
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPIeflInjectedBundleControllercpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/efl/InjectedBundleController.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/efl/InjectedBundleController.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/efl/InjectedBundleController.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * 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 "InjectedBundleController.h"
+
+#include <wtf/Assertions.h>
+
+namespace TestWebKitAPI {
+
+void InjectedBundleController::platformInitialize()
+{
+ WTFInstallReportBacktraceOnCrashHook();
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPIeflPlatformUtilitiescpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/efl/PlatformUtilities.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/efl/PlatformUtilities.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/efl/PlatformUtilities.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+/*
+ * Copyright (C) 2012 Intel Corporation. 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. 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 "PlatformUtilities.h"
+
+#include <Ecore.h>
+#include <stdio.h>
+#include <unistd.h>
+
+namespace TestWebKitAPI {
+
+namespace Util {
+
+void run(bool* done)
+{
+ while (!*done)
+ ecore_main_loop_iterate();
+}
+
+void sleep(double seconds)
+{
+ usleep(seconds * 1000000);
+}
+
+WKURLRef createURLForResource(const char* resource, const char* extension)
+{
+ char url[PATH_MAX];
+
+ snprintf(url, sizeof(url), "file://%s/%s.%s", TEST_WEBKIT2_RESOURCES_DIR, resource, extension);
+
+ return WKURLCreateWithUTF8CString(url);
+}
+
+WKStringRef createInjectedBundlePath()
+{
+ return WKStringCreateWithUTF8CString(TEST_INJECTED_BUNDLE_PATH);
+}
+
+WKURLRef URLForNonExistentResource()
+{
+ return WKURLCreateWithUTF8CString("file:///does-not-exist.html");
+}
+
+WKRetainPtr<WKStringRef> MIMETypeForWKURLResponse(WKURLResponseRef wkResponse)
+{
+ return adoptWK(WKURLResponseCopyMIMEType(wkResponse));
+}
+
+} // namespace Util
+
+} // namespace TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPIeflPlatformWebViewcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/efl/PlatformWebView.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/efl/PlatformWebView.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/efl/PlatformWebView.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+/*
+ * Copyright (C) 2012, 2014 Samsung Electronics
+ * Copyright (C) 2012 Intel Corporation. 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. 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 "ewk_main.h"
+#include "ewk_view_private.h"
+#include "PlatformWebView.h"
+#include "EWebKit2.h"
+#include <WebKit/WKAPICast.h>
+#include <WebKit/WKPageConfigurationRef.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKViewEfl.h>
+#include <Ecore_Evas.h>
+
+extern bool useX11Window;
+
+using namespace WebKit;
+
+namespace TestWebKitAPI {
+
+static Ecore_Evas* createEcoreEvas()
+{
+ Ecore_Evas* ecoreEvas;
+#if defined(HAVE_ECORE_X)
+ ecoreEvas = ecore_evas_new("opengl_x11", 0, 0, 800, 600, 0);
+ // Graceful fallback to software rendering if evas_gl engine is not available.
+ if (!ecoreEvas)
+#endif
+ ecoreEvas = ecore_evas_new(0, 0, 0, 800, 600, 0);
+
+ ASSERT(ecoreEvas);
+
+ ecore_evas_show(ecoreEvas);
+
+ return ecoreEvas;
+}
+
+static void onWebProcessCrashed(void*, Evas_Object*, void* eventInfo)
+{
+ bool* handled = static_cast<bool*>(eventInfo);
+ *handled = true;
+}
+
+PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
+{
+ m_window = createEcoreEvas();
+
+ WKRetainPtr<WKPageConfigurationRef> pageConfiguration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(pageConfiguration.get(), contextRef);
+ WKPageConfigurationSetPageGroup(pageConfiguration.get(), pageGroupRef);
+
+ m_view = EWKViewCreate(pageConfiguration.get(), ecore_evas_get(m_window), /* smart */ 0);
+
+ WKRetainPtr<WKStringRef> wkTheme = adoptWK(WKStringCreateWithUTF8CString(DEFAULT_THEME_DIR "/default.edj"));
+ WKViewSetThemePath(EWKViewGetWKView(m_view), wkTheme.get());
+
+ evas_object_smart_callback_add(m_view, "webprocess,crashed", onWebProcessCrashed, 0);
+ resizeTo(600, 800);
+}
+
+PlatformWebView::~PlatformWebView()
+{
+ evas_object_del(m_view);
+
+ ecore_evas_free(m_window);
+}
+
+void PlatformWebView::resizeTo(unsigned width, unsigned height)
+{
+ evas_object_resize(m_view, width, height);
+}
+
+WKPageRef PlatformWebView::page() const
+{
+ return WKViewGetPage(EWKViewGetWKView(m_view));
+}
+
+void PlatformWebView::simulateSpacebarKeyPress()
+{
+ Evas* evas = evas_object_evas_get(m_view);
+ evas_object_focus_set(m_view, true);
+ evas_event_feed_key_down(evas, "space", "space", " ", 0, 0, 0);
+ evas_event_feed_key_up(evas, "space", "space", " ", 0, 1, 0);
+}
+
+void PlatformWebView::simulateMouseMove(unsigned x, unsigned y)
+{
+ Evas* evas = evas_object_evas_get(m_view);
+ evas_object_show(m_view);
+ evas_event_feed_mouse_move(evas, x, y, 0, 0);
+}
+
+void PlatformWebView::simulateRightClick(unsigned x, unsigned y)
+{
+ Evas* evas = evas_object_evas_get(m_view);
+ evas_object_show(m_view);
+ evas_event_feed_mouse_move(evas, x, y, 0, 0);
+ evas_event_feed_mouse_down(evas, 3, EVAS_BUTTON_NONE, 0, 0);
+ evas_event_feed_mouse_up(evas, 3, EVAS_BUTTON_NONE, 0, 0);
+}
+
+} // namespace TestWebKitAPI
</ins></span></pre></div>
<a id="trunkToolsTestWebKitAPIeflmaincpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/efl/main.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/efl/main.cpp         (rev 0)
+++ trunk/Tools/TestWebKitAPI/efl/main.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Copyright (C) 2012 Intel Corporation. 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. 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 "TestsController.h"
+#include <getopt.h>
+#include <EWebKit2.h>
+#include <wtf/Assertions.h>
+
+bool useX11Window = false;
+
+static bool checkForUseX11WindowArgument(int argc, char** argv)
+{
+ int hasUseX11Window = 0;
+
+ static const option options[] = {
+ {"useX11Window", no_argument, &hasUseX11Window, 1},
+ {0, 0, 0, 0}
+ };
+
+ while (getopt_long(argc, argv, "", options, 0) != -1) { }
+
+ return hasUseX11Window;
+}
+
+int main(int argc, char** argv)
+{
+ WTFInstallReportBacktraceOnCrashHook();
+ setenv("WEBKIT_EXEC_PATH", WEBKIT_EXEC_PATH, false);
+
+ if (!ewk_init())
+ return EXIT_FAILURE;
+
+ useX11Window = checkForUseX11WindowArgument(argc, argv);
+
+ int returnCode = TestWebKitAPI::TestsController::singleton().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+ ewk_shutdown();
+
+ return returnCode;
+}
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleeflActivateFontsEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/ActivateFontsEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/ActivateFontsEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/ActivateFontsEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+/*
+ * Copyright (C) 2012 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 program 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 program; 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 "ActivateFonts.h"
+
+#include "FontManagement.h"
+
+namespace WTR {
+
+void activateFonts()
+{
+ addFontsToEnvironment();
+}
+
+} // namespace WTR
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleeflFontManagementcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,140 @@
</span><ins>+/*
+ * Copyright (C) 2011 ProFUSION Embedded Systems
+ * Copyright (C) 2011 Samsung Electronics
+ * Copyright (C) 2012 Intel Corporation. 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. 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/StringBuilder.h>
+
+static CString buildPath(const char* base, const char* first, ...)
+{
+ va_list ap;
+ StringBuilder result;
+ result.append(base);
+
+ if (const char* current = first) {
+ va_start(ap, first);
+ do {
+ result.append('/');
+ result.append(current);
+ } while ((current = va_arg(ap, const char*)));
+ va_end(ap);
+ }
+
+ return result.toString().utf8();
+}
+
+static Vector<CString> getCoreFontFiles()
+{
+ Vector<CString> fontFilePaths;
+
+ // Ahem is used by many layout tests.
+ fontFilePaths.append(CString(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(CString(FONTS_CONF_DIR "/FontWithNoValidEncoding.fon"));
+
+ for (int i = 1; i <= 9; i++) {
+ char fontPath[EINA_PATH_MAX];
+ snprintf(fontPath, EINA_PATH_MAX - 1, FONTS_CONF_DIR "/../../fonts/WebKitWeightWatcher%i00.ttf", i);
+ fontFilePaths.append(CString(fontPath));
+ }
+
+ return fontFilePaths;
+}
+
+static void addFontDirectory(const CString& fontDirectory, FcConfig* config)
+{
+ const char* fontPath = fontDirectory.data();
+ if (!fontPath || !FcConfigAppFontAddDir(config, reinterpret_cast<const FcChar8*>(fontPath)))
+ fprintf(stderr, "Could not add font directory %s!\n", fontPath);
+}
+
+static void addFontFiles(const Vector<CString>& fontFiles, FcConfig* config)
+{
+ Vector<CString>::const_iterator it, end = fontFiles.end();
+ for (it = fontFiles.begin(); it != end; ++it) {
+ const char* filePath = (*it).data();
+ if (!FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(filePath)))
+ fprintf(stderr, "Could not load font at %s!\n", filePath);
+ }
+}
+
+static CString getCustomBuildDir()
+{
+ if (const char* userChosenBuildDir = getenv("WEBKIT_OUTPUTDIR")) {
+ if (ecore_file_is_dir(userChosenBuildDir))
+ return userChosenBuildDir;
+ fprintf(stderr, "WEBKIT_OUTPUTDIR set to '%s', but path doesn't exist.\n", userChosenBuildDir);
+ }
+
+ return CString();
+}
+
+static CString getPlatformFontsPath()
+{
+ CString customBuildDir = getCustomBuildDir();
+ if (!customBuildDir.isNull()) {
+ CString fontsPath = buildPath(customBuildDir.data(), "DependenciesEFL", "Root", "webkitgtk-test-fonts", 0);
+ if (!ecore_file_exists(fontsPath.data()))
+ fprintf(stderr, "WEBKIT_OUTPUTDIR set to '%s', but could not local test fonts.\n", customBuildDir.data());
+ return fontsPath;
+ }
+
+ CString fontsPath = CString(DOWNLOADED_FONTS_DIR);
+ if (ecore_file_exists(fontsPath.data()))
+ return fontsPath;
+
+ fprintf(stderr, "Could not locate tests fonts, try setting WEBKIT_OUTPUTDIR.\n");
+ return CString();
+}
+
+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);
+ }
+
+ addFontFiles(getCoreFontFiles(), config);
+ addFontDirectory(getPlatformFontsPath(), config);
+
+ if (!FcConfigSetCurrent(config)) {
+ fprintf(stderr, "Could not set the current font configuration!\n");
+ exit(1);
+ }
+}
+
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleeflFontManagementh"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.h (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.h         (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/FontManagement.h        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+/*
+ * 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
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleeflInjectedBundleEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/InjectedBundleEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/InjectedBundleEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/InjectedBundleEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+/*
+ * Copyright (C) 2012 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 program 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 program; 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 "InjectedBundle.h"
+
+#include <wtf/Assertions.h>
+
+namespace WTR {
+
+void InjectedBundle::platformInitialize(WKTypeRef)
+{
+ WTFInstallReportBacktraceOnCrashHook();
+}
+
+} // namespace WTR
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnerInjectedBundleeflTestRunnerEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+/*
+ * Copyright (C) 2012 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 program 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 program; 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 "TestRunner.h"
+
+#include "InjectedBundle.h"
+#include <Ecore.h>
+#include <JavaScriptCore/OpaqueJSString.h>
+#include <WebCore/EflInspectorUtilities.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTR {
+
+static Eina_Bool waitToDumpWatchdogTimerCallback(void*)
+{
+ InjectedBundle::singleton().testRunner()->waitToDumpWatchdogTimerFired();
+ return false;
+}
+
+void TestRunner::platformInitialize()
+{
+ m_waitToDumpWatchdogTimer = 0;
+}
+
+void TestRunner::invalidateWaitToDumpWatchdogTimer()
+{
+ if (!m_waitToDumpWatchdogTimer)
+ return;
+
+ ecore_timer_del(m_waitToDumpWatchdogTimer);
+ m_waitToDumpWatchdogTimer = 0;
+}
+
+void TestRunner::initializeWaitToDumpWatchdogTimerIfNeeded()
+{
+ if (m_waitToDumpWatchdogTimer)
+ return;
+
+ m_waitToDumpWatchdogTimer = ecore_timer_loop_add(m_timeout / 1000.0, waitToDumpWatchdogTimerCallback, 0);
+}
+
+JSRetainPtr<JSStringRef> TestRunner::pathToLocalResource(JSStringRef url)
+{
+ String requestedUrl(url->characters(), url->length());
+ String resourceRoot;
+ String requestedRoot;
+
+ if (requestedUrl.find("LayoutTests") != notFound) {
+ // If the URL contains LayoutTests we need to remap that to
+ // LOCAL_RESOURCE_ROOT which is the path of the LayoutTests directory
+ // within the WebKit source tree.
+ requestedRoot = "/tmp/LayoutTests";
+ resourceRoot = getenv("LOCAL_RESOURCE_ROOT");
+ } else if (requestedUrl.find("tmp") != notFound) {
+ // If the URL is a child of /tmp we need to convert it to be a child
+ // DUMPRENDERTREE_TEMP replace tmp with DUMPRENDERTREE_TEMP
+ requestedRoot = "/tmp";
+ resourceRoot = getenv("DUMPRENDERTREE_TEMP");
+ }
+
+ size_t indexOfRootStart = requestedUrl.reverseFind(requestedRoot);
+ size_t indexOfSeparatorAfterRoot = indexOfRootStart + requestedRoot.length();
+ String fullPathToUrl = "file://" + resourceRoot + requestedUrl.substring(indexOfSeparatorAfterRoot);
+
+ return JSStringCreateWithUTF8CString(fullPathToUrl.utf8().data());
+}
+
+JSRetainPtr<JSStringRef> TestRunner::inspectorTestStubURL()
+{
+ StringBuilder builder;
+ builder.append("file://");
+ builder.append(WebCore::inspectorResourcePath());
+ builder.appendLiteral("/TestStub.html");
+
+ return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
+}
+
+} // namespace WTR
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnereflEventSenderProxyEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/efl/EventSenderProxyEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/efl/EventSenderProxyEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/efl/EventSenderProxyEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,572 @@
</span><ins>+/*
+ * 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) 2012 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 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
+ * OWNER OR 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 "EventSenderProxy.h"
+
+#include "NotImplemented.h"
+#include "PlatformWebView.h"
+#include "TestController.h"
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <unistd.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTR {
+
+static const char* modifierNames[] = { "Shift", "Control", "Alt", "Meta" };
+
+enum WTREventType {
+ WTREventTypeNone = 0,
+ WTREventTypeMouseDown,
+ WTREventTypeMouseUp,
+ WTREventTypeMouseMove,
+ WTREventTypeMouseScrollBy,
+ WTREventTypeLeapForward
+};
+
+enum EvasMouseButton {
+ EvasMouseButtonNone = 0,
+ EvasMouseButtonLeft,
+ EvasMouseButtonMiddle,
+ EvasMouseButtonRight
+};
+
+// Key event location code defined in DOM Level 3.
+enum KeyLocationCode {
+ DOMKeyLocationStandard = 0x00,
+ DOMKeyLocationLeft = 0x01,
+ DOMKeyLocationRight = 0x02,
+ DOMKeyLocationNumpad = 0x03
+};
+
+struct WTREvent {
+ WTREventType eventType;
+ unsigned delay;
+ WKEventModifiers modifiers;
+ int button;
+ int horizontal;
+ int vertical;
+
+ WTREvent()
+ : eventType(WTREventTypeNone)
+ , delay(0)
+ , modifiers(0)
+ , button(-1)
+ , horizontal(-1)
+ , vertical(-1)
+ {
+ }
+
+ WTREvent(WTREventType eventType, unsigned delay, WKEventModifiers modifiers, int button)
+ : eventType(eventType)
+ , delay(delay)
+ , modifiers(modifiers)
+ , button(button)
+ , horizontal(-1)
+ , vertical(-1)
+ {
+ }
+};
+
+struct KeyEventInfo : public RefCounted<KeyEventInfo> {
+ KeyEventInfo(const CString& keyName, const CString& keyString)
+ : keyName(keyName)
+ , keyString(keyString)
+ {
+ }
+
+ const CString keyName;
+ const CString keyString;
+};
+
+static unsigned evasMouseButton(unsigned button)
+{
+ // The common case involves converting from a WKEventMouseButton (which
+ // starts at -1) to an EvasMouseButton (which a starts at 0). The special
+ // case for button 3 exists because of fast/events/mouse-click-events.html,
+ // which tests whether a 4th mouse button behaves as the middle one.
+ if (button <= kWKEventMouseButtonRightButton)
+ return button + 1;
+ if (button == kWKEventMouseButtonRightButton + 1)
+ return EvasMouseButtonMiddle;
+ return EvasMouseButtonNone;
+}
+
+static void setEvasModifiers(Evas* evas, WKEventModifiers wkModifiers)
+{
+ for (unsigned modifier = 0; modifier < (sizeof(modifierNames) / sizeof(char*)); ++modifier) {
+ if (wkModifiers & (1 << modifier))
+ evas_key_modifier_on(evas, modifierNames[modifier]);
+ else
+ evas_key_modifier_off(evas, modifierNames[modifier]);
+ }
+}
+
+static void dispatchMouseDownEvent(Evas* evas, unsigned button, WKEventModifiers wkModifiers, int clickCount)
+{
+ Evas_Button_Flags buttonFlags = EVAS_BUTTON_NONE;
+ if (clickCount == 3)
+ buttonFlags = EVAS_BUTTON_TRIPLE_CLICK;
+ else if (clickCount == 2)
+ buttonFlags = EVAS_BUTTON_DOUBLE_CLICK;
+
+ setEvasModifiers(evas, wkModifiers);
+ evas_event_feed_mouse_down(evas, button, buttonFlags, 0, 0);
+ setEvasModifiers(evas, 0);
+}
+
+static void dispatchMouseUpEvent(Evas* evas, unsigned button, WKEventModifiers wkModifiers)
+{
+ setEvasModifiers(evas, wkModifiers);
+ evas_event_feed_mouse_up(evas, button, EVAS_BUTTON_NONE, 0, 0);
+ setEvasModifiers(evas, 0);
+}
+
+static void dispatchMouseMoveEvent(Evas* evas, int x, int y)
+{
+ evas_event_feed_mouse_move(evas, x, y, 0, 0);
+}
+
+static void dispatchMouseScrollByEvent(Evas* evas, int horizontal, int vertical)
+{
+ if (horizontal)
+ evas_event_feed_mouse_wheel(evas, 1, horizontal, 0, 0);
+
+ if (vertical)
+ evas_event_feed_mouse_wheel(evas, 0, vertical, 0, 0);
+}
+
+static const RefPtr<KeyEventInfo> keyPadName(WKStringRef keyRef)
+{
+ if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
+ return adoptRef(new KeyEventInfo("KP_Left", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "rightArrow"))
+ return adoptRef(new KeyEventInfo("KP_Right", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
+ return adoptRef(new KeyEventInfo("KP_Up", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
+ return adoptRef(new KeyEventInfo("KP_Down", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
+ return adoptRef(new KeyEventInfo("KP_Prior", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
+ return adoptRef(new KeyEventInfo("KP_Next", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "home"))
+ return adoptRef(new KeyEventInfo("KP_Home", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "end"))
+ return adoptRef(new KeyEventInfo("KP_End", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
+ return adoptRef(new KeyEventInfo("KP_Insert", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
+ return adoptRef(new KeyEventInfo("KP_Delete", ""));
+
+ size_t bufferSize = WKStringGetMaximumUTF8CStringSize(keyRef);
+ auto buffer = std::make_unique<char[]>(bufferSize);
+ WKStringGetUTF8CString(keyRef, buffer.get(), bufferSize);
+ return adoptRef(new KeyEventInfo(buffer.get(), buffer.get()));
+}
+
+static const RefPtr<KeyEventInfo> keyName(WKStringRef keyRef)
+{
+ if (WKStringIsEqualToUTF8CString(keyRef, "leftArrow"))
+ return adoptRef(new KeyEventInfo("Left", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "rightArrow"))
+ return adoptRef(new KeyEventInfo("Right", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "upArrow"))
+ return adoptRef(new KeyEventInfo("Up", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "downArrow"))
+ return adoptRef(new KeyEventInfo("Down", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "pageUp"))
+ return adoptRef(new KeyEventInfo("Prior", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "pageDown"))
+ return adoptRef(new KeyEventInfo("Next", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "home"))
+ return adoptRef(new KeyEventInfo("Home", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "end"))
+ return adoptRef(new KeyEventInfo("End", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "insert"))
+ return adoptRef(new KeyEventInfo("Insert", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "delete"))
+ return adoptRef(new KeyEventInfo("Delete", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "printScreen"))
+ return adoptRef(new KeyEventInfo("Print", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "menu"))
+ return adoptRef(new KeyEventInfo("Menu", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "leftControl"))
+ return adoptRef(new KeyEventInfo("Control_L", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "rightControl"))
+ return adoptRef(new KeyEventInfo("Control_R", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "leftShift"))
+ return adoptRef(new KeyEventInfo("Shift_L", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "rightShift"))
+ return adoptRef(new KeyEventInfo("Shift_R", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "leftAlt"))
+ return adoptRef(new KeyEventInfo("Alt_L", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "rightAlt"))
+ return adoptRef(new KeyEventInfo("Alt_R", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F1"))
+ return adoptRef(new KeyEventInfo("F1", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F2"))
+ return adoptRef(new KeyEventInfo("F2", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F3"))
+ return adoptRef(new KeyEventInfo("F3", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F4"))
+ return adoptRef(new KeyEventInfo("F4", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F5"))
+ return adoptRef(new KeyEventInfo("F5", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F6"))
+ return adoptRef(new KeyEventInfo("F6", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F7"))
+ return adoptRef(new KeyEventInfo("F7", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F8"))
+ return adoptRef(new KeyEventInfo("F8", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F9"))
+ return adoptRef(new KeyEventInfo("F9", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F10"))
+ return adoptRef(new KeyEventInfo("F10", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F11"))
+ return adoptRef(new KeyEventInfo("F11", ""));
+ if (WKStringIsEqualToUTF8CString(keyRef, "F12"))
+ return adoptRef(new KeyEventInfo("F12", ""));
+
+ size_t bufferSize = WKStringGetMaximumUTF8CStringSize(keyRef);
+ auto buffer = std::make_unique<char[]>(bufferSize);
+ WKStringGetUTF8CString(keyRef, buffer.get(), bufferSize);
+ char charCode = buffer.get()[0];
+
+ if (charCode == '\n' || charCode == '\r')
+ return adoptRef(new KeyEventInfo("Return", "\r"));
+ if (charCode == '\t')
+ return adoptRef(new KeyEventInfo("Tab", "\t"));
+ if (charCode == '\x8')
+ return adoptRef(new KeyEventInfo("BackSpace", "\x8"));
+ if (charCode == ' ')
+ return adoptRef(new KeyEventInfo("space", " "));
+
+ return adoptRef(new KeyEventInfo(buffer.get(), buffer.get()));
+}
+
+EventSenderProxy::EventSenderProxy(TestController* testController)
+ : m_testController(testController)
+ , m_time(0)
+ , m_leftMouseButtonDown(false)
+ , m_clickCount(0)
+ , m_clickTime(0)
+ , m_clickButton(kWKEventMouseButtonNoButton)
+ , m_mouseButton(kWKEventMouseButtonNoButton)
+#if ENABLE(TOUCH_EVENTS)
+ , m_touchPoints(0)
+#endif
+{
+}
+
+EventSenderProxy::~EventSenderProxy()
+{
+#if ENABLE(TOUCH_EVENTS)
+ clearTouchPoints();
+#endif
+}
+
+void EventSenderProxy::updateClickCountForButton(int button)
+{
+ if (m_time - m_clickTime < 1 && m_position == m_clickPosition && button == m_clickButton) {
+ ++m_clickCount;
+ m_clickTime = m_time;
+ return;
+ }
+
+ m_clickCount = 1;
+ m_clickTime = m_time;
+ m_clickPosition = m_position;
+ m_clickButton = button;
+}
+
+void EventSenderProxy::dispatchEvent(const WTREvent& event)
+{
+ Evas* evas = evas_object_evas_get(m_testController->mainWebView()->platformView());
+
+ if (event.eventType == WTREventTypeMouseDown)
+ dispatchMouseDownEvent(evas, event.button, event.modifiers, m_clickCount);
+ else if (event.eventType == WTREventTypeMouseUp)
+ dispatchMouseUpEvent(evas, event.button, event.modifiers);
+ else if (event.eventType == WTREventTypeMouseMove)
+ dispatchMouseMoveEvent(evas, static_cast<int>(m_position.x), static_cast<int>(m_position.y));
+ else if (event.eventType == WTREventTypeMouseScrollBy)
+ dispatchMouseScrollByEvent(evas, event.horizontal, event.vertical);
+}
+
+void EventSenderProxy::replaySavedEvents()
+{
+ while (!m_eventQueue.isEmpty()) {
+ WTREvent event = m_eventQueue.takeFirst();
+ if (event.delay)
+ usleep(event.delay * 1000);
+
+ dispatchEvent(event);
+ }
+}
+
+void EventSenderProxy::sendOrQueueEvent(const WTREvent& event)
+{
+ if (m_eventQueue.isEmpty() || !m_eventQueue.last().delay) {
+ dispatchEvent(event);
+ return;
+ }
+
+ m_eventQueue.append(event);
+ replaySavedEvents();
+}
+
+void EventSenderProxy::mouseDown(unsigned button, WKEventModifiers wkModifiers)
+{
+ if (m_mouseButton == button)
+ return;
+
+ m_mouseButton = button;
+ updateClickCountForButton(button);
+
+ sendOrQueueEvent(WTREvent(WTREventTypeMouseDown, 0, wkModifiers, evasMouseButton(button)));
+}
+
+void EventSenderProxy::mouseUp(unsigned button, WKEventModifiers wkModifiers)
+{
+ sendOrQueueEvent(WTREvent(WTREventTypeMouseUp, 0, wkModifiers, evasMouseButton(button)));
+
+ if (m_mouseButton == button)
+ m_mouseButton = kWKEventMouseButtonNoButton;
+
+ m_clickPosition = m_position;
+ m_clickTime = currentEventTime();
+}
+
+void EventSenderProxy::mouseMoveTo(double x, double y)
+{
+ m_position.x = x;
+ m_position.y = y;
+
+ sendOrQueueEvent(WTREvent(WTREventTypeMouseMove, 0, 0, kWKEventMouseButtonNoButton));
+}
+
+void EventSenderProxy::mouseScrollBy(int horizontal, int vertical)
+{
+ WTREvent event(WTREventTypeMouseScrollBy, 0, 0, kWKEventMouseButtonNoButton);
+ // We need to invert scrolling values since in EFL negative z value means that
+ // canvas is scrolling down
+ event.horizontal = -horizontal;
+ event.vertical = -vertical;
+ sendOrQueueEvent(event);
+}
+
+void EventSenderProxy::continuousMouseScrollBy(int horizontal, int vertical, bool paged)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int /*phase*/, int /*momentum*/)
+{
+ // EFL does not have the concept of wheel gesture phases or momentum. Just relay to
+ // the mouse wheel handler.
+ mouseScrollBy(x, y);
+}
+
+void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int, int, int, int)
+{
+ notImplemented();
+}
+
+void EventSenderProxy::leapForward(int milliseconds)
+{
+ if (m_eventQueue.isEmpty())
+ m_eventQueue.append(WTREvent(WTREventTypeLeapForward, milliseconds, 0, kWKEventMouseButtonNoButton));
+
+ m_time += milliseconds / 1000.0;
+}
+
+void EventSenderProxy::keyDown(WKStringRef keyRef, WKEventModifiers wkModifiers, unsigned location)
+{
+ const RefPtr<KeyEventInfo> keyEventInfo = (location == DOMKeyLocationNumpad) ? keyPadName(keyRef) : keyName(keyRef);
+ if (!keyEventInfo)
+ return;
+
+ const char* keyName = keyEventInfo->keyName.data();
+ const char* keyString = keyEventInfo->keyString.data();
+
+ // Enforce 'Shift' modifier for caps.
+ if ((strlen(keyName) == 1) && (keyName[0] >= 'A' && keyName[0] <= 'Z'))
+ wkModifiers |= kWKEventModifiersShiftKey;
+
+ Evas* evas = evas_object_evas_get(m_testController->mainWebView()->platformView());
+
+ int eventIndex = 0;
+ // Mimic the emacs ctrl-o binding by inserting a paragraph
+ // separator and then putting the cursor back to its original
+ // position. Allows us to pass emacs-ctrl-o.html
+ if ((wkModifiers & kWKEventModifiersControlKey) && !strcmp(keyName, "o")) {
+ setEvasModifiers(evas, 0);
+ evas_event_feed_key_down(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
+ evas_event_feed_key_up(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
+ wkModifiers = 0;
+ keyName = "Left";
+ keyString = 0;
+ }
+
+ setEvasModifiers(evas, wkModifiers);
+ evas_event_feed_key_down(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
+ evas_event_feed_key_up(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
+ setEvasModifiers(evas, 0);
+}
+
+#if ENABLE(TOUCH_EVENTS)
+void EventSenderProxy::sendTouchEvent(Ewk_Touch_Event_Type eventType)
+{
+ ASSERT(m_touchPoints);
+
+ Evas_Object* ewkView = m_testController->mainWebView()->platformView();
+ ewk_view_feed_touch_event(ewkView, eventType, m_touchPoints, evas_key_modifier_get(evas_object_evas_get(ewkView)));
+
+ Eina_List* list;
+ Eina_List* listNext;
+ void* data;
+ EINA_LIST_FOREACH_SAFE(m_touchPoints, list, listNext, data) {
+ Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(data);
+ ASSERT(touchPoint);
+
+ if ((touchPoint->state == EVAS_TOUCH_POINT_UP) || (touchPoint->state == EVAS_TOUCH_POINT_CANCEL)) {
+ delete touchPoint;
+ m_touchPoints = eina_list_remove_list(m_touchPoints, list);
+ } else
+ touchPoint->state = EVAS_TOUCH_POINT_STILL;
+ }
+}
+
+void EventSenderProxy::addTouchPoint(int x, int y)
+{
+ int id = 0;
+ if (m_touchPoints) {
+ Eina_List* last = eina_list_last(m_touchPoints);
+ Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_data_get(last));
+ ASSERT(touchPoint);
+
+ id = touchPoint->id + 1;
+ }
+
+ Ewk_Touch_Point* touchPoint = new Ewk_Touch_Point;
+ touchPoint->id = id;
+ touchPoint->x = x;
+ touchPoint->y = y;
+ touchPoint->state = EVAS_TOUCH_POINT_DOWN;
+
+ m_touchPoints = eina_list_append(m_touchPoints, touchPoint);
+}
+
+void EventSenderProxy::updateTouchPoint(int index, int x, int y)
+{
+ ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
+
+ Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
+ ASSERT(touchPoint);
+
+ touchPoint->x = x;
+ touchPoint->y = y;
+ touchPoint->state = EVAS_TOUCH_POINT_MOVE;
+}
+
+void EventSenderProxy::setTouchModifier(WKEventModifiers modifier, bool enable)
+{
+ Evas_Object* ewkView = m_testController->mainWebView()->platformView();
+
+ for (unsigned index = 0; index < (sizeof(modifierNames) / sizeof(char*)); ++index) {
+ if (modifier & (1 << index)) {
+ if (enable)
+ evas_key_modifier_on(evas_object_evas_get(ewkView), modifierNames[index]);
+ else
+ evas_key_modifier_off(evas_object_evas_get(ewkView), modifierNames[index]);
+ }
+ }
+}
+
+void EventSenderProxy::touchStart()
+{
+ sendTouchEvent(EWK_TOUCH_START);
+}
+
+void EventSenderProxy::touchMove()
+{
+ sendTouchEvent(EWK_TOUCH_MOVE);
+}
+
+void EventSenderProxy::touchEnd()
+{
+ sendTouchEvent(EWK_TOUCH_END);
+}
+
+void EventSenderProxy::touchCancel()
+{
+ sendTouchEvent(EWK_TOUCH_CANCEL);
+}
+
+void EventSenderProxy::clearTouchPoints()
+{
+ void* data = 0;
+ EINA_LIST_FREE(m_touchPoints, data)
+ delete static_cast<Ewk_Touch_Point*>(data);
+}
+
+void EventSenderProxy::releaseTouchPoint(int index)
+{
+ ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
+
+ Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
+ ASSERT(touchPoint);
+
+ touchPoint->state = EVAS_TOUCH_POINT_UP;
+}
+
+void EventSenderProxy::cancelTouchPoint(int index)
+{
+ ASSERT(index >= 0 && index < eina_list_count(m_touchPoints));
+
+ Ewk_Touch_Point* touchPoint = static_cast<Ewk_Touch_Point*>(eina_list_nth(m_touchPoints, index));
+ ASSERT(touchPoint);
+
+ touchPoint->state = EVAS_TOUCH_POINT_CANCEL;
+}
+
+void EventSenderProxy::setTouchPointRadius(int radiusX, int radiusY)
+{
+ notImplemented();
+}
+
+#endif
+
+}
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnereflPlatformWebViewEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/efl/PlatformWebViewEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/efl/PlatformWebViewEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/efl/PlatformWebViewEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,175 @@
</span><ins>+/*
+ * Copyright (C) 2012 Samsung Electronics
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * 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 program 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 program; 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 "ewk_view_private.h"
+#include "PlatformWebView.h"
+
+#include "EWebKit2.h"
+#include <Ecore_Evas.h>
+#include <WebCore/RefPtrCairo.h>
+#include <WebKit/WKImageCairo.h>
+#include <WebKit/WKViewEfl.h>
+#include <cairo.h>
+
+using namespace WebKit;
+
+namespace WTR {
+
+static Ecore_Evas* initEcoreEvas()
+{
+ Ecore_Evas* ecoreEvas = 0;
+#if defined(HAVE_ECORE_X)
+ const char* engine = "opengl_x11";
+ ecoreEvas = ecore_evas_new(engine, 0, 0, 800, 600, 0);
+ // Graceful fallback to software rendering if evas_gl engine is not available.
+ if (!ecoreEvas)
+#endif
+ ecoreEvas = ecore_evas_new(0, 0, 0, 800, 600, 0);
+
+ if (!ecoreEvas)
+ return 0;
+
+ ecore_evas_title_set(ecoreEvas, "EFL WebKitTestRunner");
+ ecore_evas_show(ecoreEvas);
+
+ return ecoreEvas;
+}
+
+PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration, const TestOptions& options)
+ : m_options(options)
+{
+ WKRetainPtr<WKStringRef> useFixedLayoutKey(AdoptWK, WKStringCreateWithUTF8CString("UseFixedLayout"));
+ m_usingFixedLayout = options.useFixedLayout;
+
+ m_window = initEcoreEvas();
+
+ m_view = EWKViewCreate(configuration, ecore_evas_get(m_window), /* smart */ 0);
+
+ WKPageSetUseFixedLayout(WKViewGetPage(EWKViewGetWKView(m_view)), m_usingFixedLayout);
+
+ if (m_usingFixedLayout)
+ resizeTo(800, 600);
+
+ ewk_view_theme_set(m_view, DEFAULT_THEME_DIR "/default.edj");
+ m_windowIsKey = false;
+ evas_object_show(m_view);
+}
+
+PlatformWebView::~PlatformWebView()
+{
+ evas_object_del(m_view);
+
+ ecore_evas_free(m_window);
+}
+
+void PlatformWebView::setWindowIsKey(bool isKey)
+{
+ m_windowIsKey = isKey;
+}
+
+void PlatformWebView::resizeTo(unsigned width, unsigned height, WebViewSizingMode)
+{
+ // FIXME: Don't we need to resize the window too?
+ evas_object_resize(m_view, width, height);
+}
+
+WKPageRef PlatformWebView::page()
+{
+ return WKViewGetPage(EWKViewGetWKView(m_view));
+}
+
+void PlatformWebView::focus()
+{
+ // In a few cases, an iframe might receive focus from JavaScript and Evas is not aware of it at all
+ // (WebCoreSupport::focusedFrameChanged() does not emit any notification). We then manually remove the
+ // focus from the view to make the call give focus to evas_object_focus_set(..., true) to be effectful.
+ if (WKPageGetFocusedFrame(page()) != WKPageGetMainFrame(page()))
+ evas_object_focus_set(m_view, false);
+ evas_object_focus_set(m_view, true);
+}
+
+WKRect PlatformWebView::windowFrame()
+{
+ int x, y, width, height;
+
+ ecore_evas_request_geometry_get(m_window, &x, &y, &width, &height);
+
+ return WKRectMake(x, y, width, height);
+}
+
+void PlatformWebView::setWindowFrame(WKRect frame, WebViewSizingMode)
+{
+ ecore_evas_move_resize(m_window, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+ evas_object_resize(m_view, frame.size.width, frame.size.height);
+}
+
+void PlatformWebView::addChromeInputField()
+{
+}
+
+void PlatformWebView::removeChromeInputField()
+{
+}
+
+void PlatformWebView::addToWindow()
+{
+}
+
+void PlatformWebView::removeFromWindow()
+{
+}
+
+void PlatformWebView::makeWebViewFirstResponder()
+{
+}
+
+void PlatformWebView::changeWindowScaleIfNeeded(float)
+{
+}
+
+WKRetainPtr<WKImageRef> PlatformWebView::windowSnapshotImage()
+{
+ int width;
+ int height;
+ ecore_evas_geometry_get(m_window, 0, 0, &width, &height);
+ ASSERT(width > 0 && height > 0);
+
+ return adoptWK(WKViewCreateSnapshot(EWKViewGetWKView(m_view)));
+}
+
+bool PlatformWebView::viewSupportsOptions(const TestOptions& options) const
+{
+ if (m_options.useFixedLayout != options.useFixedLayout)
+ return false;
+
+ return true;
+}
+
+void PlatformWebView::didInitializeClients()
+{
+}
+
+void PlatformWebView::setNavigationGesturesEnabled(bool)
+{
+}
+
+} // namespace WTR
+
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnereflTestControllerEflcpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/efl/TestControllerEfl.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/efl/TestControllerEfl.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/efl/TestControllerEfl.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+/*
+ * Copyright (C) 2012 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 program 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 program; 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 "TestController.h"
+
+#include "PlatformWebView.h"
+#include "TestInvocation.h"
+#include <Ecore.h>
+#include <Evas.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wtf/Platform.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTR {
+
+static Ecore_Timer* timer = 0;
+
+static Eina_Bool timerFired(void*)
+{
+ timer = 0;
+ ecore_main_loop_quit();
+ return ECORE_CALLBACK_CANCEL;
+}
+
+void TestController::notifyDone()
+{
+ if (!timer)
+ return;
+
+ ecore_timer_del(timer);
+ timer = 0;
+ ecore_main_loop_quit();
+}
+
+void TestController::platformInitialize()
+{
+ const char* isDebugging = getenv("WEB_PROCESS_CMD_PREFIX");
+ if (isDebugging && *isDebugging) {
+ m_useWaitToDumpWatchdogTimer = false;
+ m_forceNoTimeout = true;
+ }
+}
+
+WKPreferencesRef TestController::platformPreferences()
+{
+ return WKPageGroupGetPreferences(m_pageGroup.get());
+}
+
+void TestController::platformDestroy()
+{
+}
+
+void TestController::platformRunUntil(bool& condition, double timeout)
+{
+ if (timeout <= 0) {
+ // Never timeout if we are debugging or not meant to timeout.
+ while (!condition)
+ ecore_main_loop_iterate();
+
+ return;
+ }
+ timer = ecore_timer_loop_add(timeout, timerFired, 0);
+ ecore_main_loop_begin();
+}
+
+static const char* getEnvironmentVariableOrExit(const char* variableName)
+{
+ const char* value = getenv(variableName);
+ if (!value) {
+ fprintf(stderr, "%s environment variable not found\n", variableName);
+ exit(0);
+ }
+
+ return value;
+}
+
+void TestController::initializeInjectedBundlePath()
+{
+ const char* bundlePath = getEnvironmentVariableOrExit("TEST_RUNNER_INJECTED_BUNDLE_FILENAME");
+ m_injectedBundlePath.adopt(WKStringCreateWithUTF8CString(bundlePath));
+}
+
+void TestController::initializeTestPluginDirectory()
+{
+ const char* pluginPath = getEnvironmentVariableOrExit("TEST_RUNNER_PLUGIN_PATH");
+ m_testPluginDirectory.adopt(WKStringCreateWithUTF8CString(pluginPath));
+}
+
+void TestController::platformInitializeContext()
+{
+}
+
+void TestController::setHidden(bool hidden)
+{
+ PlatformWKView view = mainWebView()->platformView();
+
+ if (!view) {
+ fprintf(stderr, "ERROR: view is null.\n");
+ return;
+ }
+
+ if (hidden)
+ evas_object_hide(view);
+ else
+ evas_object_show(view);
+}
+
+void TestController::runModal(PlatformWebView*)
+{
+ // FIXME: Need to implement this to test showModalDialog.
+}
+
+const char* TestController::platformLibraryPathForTesting()
+{
+ return 0;
+}
+
+static bool pathContains(const std::string& pathOrURL, const char* substring)
+{
+ String path(pathOrURL.c_str());
+ return path.contains(substring); // Case-insensitive.
+}
+
+static bool shouldUseFixedLayout(const std::string& pathOrURL)
+{
+#if USE(COORDINATED_GRAPHICS)
+ if (pathContains(pathOrURL, "sticky/") || pathContains(pathOrURL, "sticky\\"))
+ return true;
+#endif
+ return false;
+}
+
+void TestController::updatePlatformSpecificTestOptionsForTest(TestOptions& testOptions, const std::string& pathOrURL) const
+{
+ testOptions.useFixedLayout |= shouldUseFixedLayout(pathOrURL);
+}
+
+void TestController::platformConfigureViewForTest(const TestInvocation&)
+{
+ WKPageSetApplicationNameForUserAgent(mainWebView()->page(), WKStringCreateWithUTF8CString("WebKitTestRunnerEFL"));
+}
+
+void TestController::platformResetPreferencesToConsistentValues()
+{
+}
+
+} // namespace WTR
</ins></span></pre></div>
<a id="trunkToolsWebKitTestRunnereflmaincpp"></a>
<div class="addfile"><h4>Added: trunk/Tools/WebKitTestRunner/efl/main.cpp (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/WebKitTestRunner/efl/main.cpp         (rev 0)
+++ trunk/Tools/WebKitTestRunner/efl/main.cpp        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,59 @@
</span><ins>+/*
+ * Copyright (C) 2012 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 program 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 program; 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 "EWebKit2.h"
+#include "TestController.h"
+#include <wtf/Assertions.h>
+#include <stdlib.h>
+
+#ifdef HAVE_ECORE_X
+#include <X11/Xlib.h>
+#include <X11/extensions/Xext.h>
+
+static int dummyExtensionErrorHandler(Display*, _Xconst char*, _Xconst char*)
+{
+ return 0;
+}
+#endif
+
+int main(int argc, char** argv)
+{
+ WTFInstallReportBacktraceOnCrashHook();
+
+#ifdef HAVE_ECORE_X
+ XSetExtensionErrorHandler(dummyExtensionErrorHandler);
+#endif
+
+ if (!ewk_init())
+ return 1;
+
+ {
+ // Test controller has own ptr containing WebView and WebView must be deleted
+ // before its evas object is deleted. Call of ewk_shutdown() leads to evas objects deletion.
+
+ WTR::TestController controller(argc, const_cast<const char**>(argv));
+ }
+
+ ewk_shutdown();
+
+ return 0;
+}
+
</ins></span></pre></div>
<a id="trunkToolseflinstalldependencies"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/install-dependencies (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/install-dependencies         (rev 0)
+++ trunk/Tools/efl/install-dependencies        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,135 @@
</span><ins>+#!/bin/bash
+
+# This script needs to be run with root rights.
+if [ $UID -ne 0 ]; then
+ sudo $0
+ exit 0
+fi
+
+function printNotSupportedMessageAndExit() {
+ echo
+ echo "Currently this script only works for distributions supporting apt-get."
+ echo "Please add support for your distribution."
+ echo
+ exit 1
+}
+
+function checkCmakeVersion() {
+ CMAKE_VERSION=`cmake --version`
+
+ VERSION=`echo "$CMAKE_VERSION" | awk '{split($3,num,".");
+ if (!(num[1]>2 || num[2]>8 || num[3]>=10))
+ printf $3}'`
+
+ if [ -n "${VERSION}" ]; then
+ echo "Warning: CMake version detected (${VERSION}) is lower then 2.8.10."
+ echo " This will probably cause errors, as older version didn't support CMAKE_NINJA_FORCE_RESPONSE_FILE,"
+ echo " which is needed now for building. (look at: https://lists.webkit.org/pipermail/webkit-gtk/2014-March/001809.html )"
+ echo ""
+
+ if [ -f "/etc/issue" ]; then
+ ubuntu_version=`cat /etc/issue`
+ if [[ $ubuntu_version == *Ubuntu\ 12.04* ]]; then
+ echo " For Ubuntu 12.04 or 12.10 You might consider adding ppa from https://launchpad.net/~kalakris/+archive/ubuntu/cmake"
+ fi
+ fi
+ fi
+}
+
+function checkInstaller {
+ # apt-get - Debian based distributions
+ apt-get --version &> /dev/null
+ if [ $? -eq 0 ]; then
+ installDependenciesWithApt
+ checkCmakeVersion;
+ exit 0
+ fi
+
+ printNotSupportedMessageAndExit
+}
+
+# If the package $1 is available, prints it. Otherwise prints $2.
+# Useful for handling when a package is renamed on new versions of Debian/Ubuntu.
+function aptIfElse {
+ if apt-cache show $1 &>/dev/null; then
+ echo $1
+ else
+ echo $2
+ fi
+}
+
+function installDependenciesWithApt {
+ # These are dependencies necessary for building WebKitEFL.
+ apt-get install \
+ bison \
+ cmake \
+ doxygen \
+ flex \
+ g++ \
+ geoclue-2.0 \
+ gperf \
+ gtk-doc-tools \
+ libatk1.0-dev \
+ libdbus-1-dev \
+ libedit-dev \
+ libenchant-dev \
+ libespeak-dev \
+ libfaad-dev \
+ libffi-dev \
+ libfreetype6-dev \
+ $(aptIfElse libgcrypt20-dev libgcrypt11-dev) \
+ $(aptIfElse libgeoclue-2-dev libgeoclue-dev) \
+ libgif-dev \
+ libgl1-mesa-dev \
+ libgpg-error-dev \
+ libhyphen-dev \
+ libicu-dev \
+ libjpeg-dev \
+ libjson-glib-dev \
+ liblua5.1-0-dev \
+ libluajit-5.1-dev \
+ libmpg123-dev \
+ liborc-0.4-dev \
+ libosmesa6-dev \
+ libp11-kit-dev \
+ $(aptIfElse libpng-dev libpng12-dev) \
+ libpoppler-cpp-dev \
+ libpulse-dev \
+ libraw-dev \
+ librsvg2-dev \
+ libspectre-dev \
+ libsqlite3-dev \
+ libssl-dev \
+ libtheora-dev \
+ libtiff5-dev \
+ libudev-dev \
+ libvorbis-dev \
+ libwebp-dev \
+ libxcomposite-dev \
+ libxcursor-dev \
+ libxinerama-dev \
+ libxrandr-dev \
+ libxrender-dev \
+ libxss-dev \
+ libxt-dev \
+ libxtst-dev \
+ ninja-build \
+ ragel \
+ ruby \
+ subversion \
+ x11proto-print-dev
+
+ # These are dependencies necessary for building WebKitEFL and not available on ARM64.
+ apt-get install \
+ luajit
+
+ # These are dependencies necessary for running tests.
+ apt-get install \
+ apache2 \
+ $(aptIfElse libapache2-mod-php7.0 libapache2-mod-php5) \
+ libruby \
+ xvfb
+}
+
+checkInstaller
+
</ins><span class="cx">Property changes on: trunk/Tools/efl/install-dependencies
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnexecutable"></a>
<div class="addfile"><h4>Added: svn:executable</h4></div>
<ins>+*
</ins><span class="cx">\ No newline at end of property
</span><a id="trunkToolsefljhbuildoptionalmodules"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/jhbuild-optional.modules (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/jhbuild-optional.modules         (rev 0)
+++ trunk/Tools/efl/jhbuild-optional.modules        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <repository type="tarball" name="ftp.gnome.org"
+ href="http://ftp.gnome.org"/>
+
+ <autotools id="at-spi2-core"
+ autogenargs="--disable-introspection">
+ <branch module="pub/GNOME/sources/at-spi2-core/2.10/at-spi2-core-2.10.0.tar.xz" version="2.10.0"
+ repo="ftp.gnome.org"
+ hash="sha256:964155c7574220a00e11e1c0d91f2d3017ed603920eb1333ff9cbdb6a22744db">
+ </branch>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="at-spi2-atk">
+ <branch module="pub/GNOME/sources/at-spi2-atk/2.10/at-spi2-atk-2.10.0.tar.xz" version="2.10.0"
+ repo="ftp.gnome.org"
+ hash="sha256:dea7ff2f9bc9bbdb0351112616d738de718b55739cd2511afecac51604c31a94">
+ </branch>
+ <dependencies>
+ <dep package="glib"/>
+ <dep package="atk"/>
+ <dep package="at-spi2-core"/>
+ </dependencies>
+ </autotools>
+
+</moduleset>
</ins></span></pre></div>
<a id="trunkToolsefljhbuildmodules"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/jhbuild.modules (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/jhbuild.modules         (rev 0)
+++ trunk/Tools/efl/jhbuild.modules        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,317 @@
</span><ins>+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <metamodule id="webkitefl-testing-dependencies">
+ <dependencies>
+ <dep package="cairo"/>
+ <dep package="fonts"/>
+ <dep package="dicts"/>
+ <dep package="fontconfig"/>
+ <dep package="freetype6"/>
+ <dep package="harfbuzz"/>
+ <dep package="glib"/>
+ <dep package="glib-networking"/>
+ <dep package="libsoup"/>
+ <dep package="efl"/>
+ <dep package="libxml2"/>
+ <dep package="libxslt"/>
+ <dep package="gstreamer"/>
+ <dep package="gst-plugins-base"/>
+ <dep package="gst-plugins-good"/>
+ <dep package="gst-plugins-bad"/>
+ <dep package="gst-libav"/>
+ <dep package="atk"/>
+ <dep package="openwebrtc"/>
+ </dependencies>
+ </metamodule>
+
+ <include href="jhbuild-optional.modules"/>
+
+ <repository type="tarball" name="github.com"
+ href="https://github.com"/>
+ <repository type="tarball" name="sourceware.org"
+ href="ftp://sourceware.org"/>
+ <repository type="tarball" name="ftp.gnome.org"
+ href="http://ftp.gnome.org"/>
+ <repository type="git" name="git.gnome.org"
+ href="git://git.gnome.org/"/>
+ <repository type="tarball" name="cairographics.org"
+ href="http://cairographics.org"/>
+ <repository type="tarball" name="freedesktop.org"
+ href="http://www.freedesktop.org"/>
+ <repository type="tarball" name="nice.freedesktop.org"
+ href="http://nice.freedesktop.org/"/>
+ <repository type="tarball" name="enlightenment.fr"
+ href="http://git.enlightenment.fr/cgit.cgi/svn/"/>
+ <repository type="tarball" name="xmlsoft.org"
+ href="ftp://xmlsoft.org"/>
+ <repository type="tarball" name="download.enlightenment.org"
+ href="http://download.enlightenment.org"/>
+ <repository type="tarball" name="gstreamer"
+ href="http://gstreamer.freedesktop.org/src/"/>
+
+ <autotools id="cairo" autogen-sh="configure"
+ makeargs="CFLAGS='-fno-lto' CXXFLAGS='-fno-lto' LDFLAGS='-fno-lto'">
+ <dependencies>
+ <dep package="fontconfig"/>
+ <dep package="pixman"/>
+ </dependencies>
+ <branch module="releases/cairo-1.14.2.tar.xz" version="1.14.2"
+ repo="cairographics.org"
+ hash="sha256:c919d999ddb1bbbecd4bbe65299ca2abd2079c7e13d224577895afa7005ecceb"
+ md5sum="e1cdfaf1c6c995c4d4c54e07215b0118">
+ </branch>
+ </autotools>
+
+ <!-- FIXME: Pixman 0.32.6 isn't buildable with Clang, but disable-mmx option fixes
+ the build. This workaround can be removed once the original bug is fixed.
+ Details can be found here: https://bugs.webkit.org/show_bug.cgi?id=151441 -->
+ <autotools id="pixman" autogen-sh="configure"
+ autogenargs="--enable-gtk=no --disable-arm-iwmmxt --disable-mmx">
+ <branch module="releases/pixman-0.32.6.tar.gz" version="0.32.6"
+ repo="cairographics.org"
+ hash="sha256:3dfed13b8060eadabf0a4945c7045b7793cc7e3e910e748a8bb0f0dc3e794904"
+ md5sum="3a30859719a41bd0f5cccffbfefdd4c2">
+ </branch>
+ </autotools>
+
+ <autotools id="fonts" supports-non-srcdir-builds="no"
+ skip-autogen="true">
+ <branch module="mrobinson/webkitgtk-test-fonts/archive/0.0.5.tar.gz" version="0.0.5"
+ checkoutdir="webkitgtk-test-fonts"
+ repo="github.com"
+ hash="sha256:369aea9e18aa1a234400976c0a8135b9709805ce4b65a3b474a8d0ee0e298f34"
+ md5sum="39802b485f513842724e6cfd265335bb" size="22592847">
+ </branch>
+ </autotools>
+
+ <autotools id="dicts" supports-non-srcdir-builds="no"
+ skip-autogen="true">
+ <branch module="mrobinson/webkitgtk-test-dicts/archive/0.0.1.zip" version="0.0.1"
+ checkoutdir="webkitgtk-test-dicts"
+ repo="github.com"
+ hash="sha256:6cfc94a7846a0d8f76a7a733f729e8109c6e1d0fbc9e0e8587eb5c3ef9888c24"
+ md5sum="6bd8d32c157305fc69932ea8d1348723" size="99299">
+ </branch>
+ </autotools>
+
+ <autotools id="libffi" autogen-sh="configure">
+ <branch module="/pub/libffi/libffi-3.1.tar.gz" version="3.1"
+ repo="sourceware.org"
+ hash="sha256:97feeeadca5e21870fa4433bc953d1b3af3f698d5df8a428f68b73cd60aef6eb"
+ md5sum="f5898b29bbfd70502831a212d9249d10"/>
+ </autotools>
+
+ <!-- FIXME: Original download url doesn't work in Korea. So, Bug 133303 changes the url for now.
+ Original download url: http://download.savannah.gnu.org/releases/freetype/freetype-2.4.11.tar.bz2 -->
+ <tarball id="freetype6">
+ <source href="github.com/shivamidow/freetype/raw/master/freetype-2.4.11.tar.bz2" version="2.4.11"
+ hash="sha256:ef9d0bcb64647d9e5125dc7534d7ca371c98310fec87677c410f397f71ffbe3f"
+ md5sum="b93435488942486c8d0ca22e8f768034" />
+ </tarball>
+
+ <autotools id="glib"
+ autogen-sh="configure"
+ autogenargs="--disable-dtrace">
+ <dependencies>
+ <dep package="libffi"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/glib/2.41/glib-2.41.2.tar.xz" version="2.41.2"
+ repo="ftp.gnome.org"
+ hash="sha256:da1f7258655f0e196b9304cb9515784634f3797437923e236bb3466348811c96"
+ md5sum="9636f60e99b98fd0fdb5239f905ac008"/>
+ </autotools>
+
+ <autotools id="glib-networking">
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ <branch module="/pub/GNOME/sources/glib-networking/2.41/glib-networking-2.41.4.tar.xz" version="2.41.4"
+ repo="ftp.gnome.org"
+ hash="sha256:930ad618865dcf81765d0f48cb6f13e22d76203efa59d30604aed0384ce80fd7"
+ md5sum="f88e163322c0834f9781d6224771ab2e"/>
+ </autotools>
+
+ <autotools id="libsoup"
+ autogenargs="--without-gnome --disable-introspection">
+ <dependencies>
+ <dep package="glib-networking"/>
+ <dep package="libxml2"/>
+ </dependencies>
+ <branch module="/pub/gnome/sources/libsoup/2.50/libsoup-2.50.0.tar.xz" version="2.50.0"
+ repo="ftp.gnome.org"
+ hash="sha256:1e01365ac4af3817187ea847f9d3588c27eee01fc519a5a7cb212bb78b0f667b">
+ </branch>
+ </autotools>
+
+ <autotools id="fontconfig"
+ autogen-sh="configure"
+ autogenargs="--enable-libxml2">
+ <dependencies>
+ <dep package="freetype6"/>
+ <dep package="libxml2"/>
+ </dependencies>
+ <branch module="software/fontconfig/release/fontconfig-2.11.1.tar.gz" version="2.11.1"
+ repo="freedesktop.org"
+ hash="sha256:b6b066c7dce3f436fdc0dfbae9d36122b38094f4f53bd8dffd45e195b0540d8d"
+ md5sum="e75e303b4f7756c2b16203a57ac87eba"/>
+ </autotools>
+
+ <autotools id="harfbuzz" autogen-sh="configure">
+ <branch module="software/harfbuzz/release/harfbuzz-0.9.35.tar.bz2" version="0.9.35"
+ checkoutdir="harfbuzz-0.9.35"
+ repo="freedesktop.org"
+ hash="sha256:0aa1a8aba6f502321cf6fef3c9d2c73dde48389c5ed1d3615a7691944c2a06ed">
+ </branch>
+ </autotools>
+
+ <autotools id="efl" autogen-sh="configure"
+ autogenargs="--disable-fribidi --disable-audio --disable-libmount --disable-physics --enable-i-really-know-what-i-am-doing-and-that-this-will-probably-break-things-and-i-will-fix-them-myself-and-send-patches-abb">
+ <dependencies>
+ <dep package="fontconfig"/>
+ <dep package="gstreamer"/>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="rel/libs/efl/efl-1.18.4.tar.gz" version="1.18.4"
+ repo="download.enlightenment.org"
+ hash="sha256:d19669eece770cc09733568c7dfef9870daa0f8b9f613ab76ad14b2f5de20040">
+ </branch>
+ </autotools>
+
+ <autotools id="libxml2"
+ autogen-sh="configure"
+ autogenargs="--without-python">
+ <branch module="/libxml2/libxml2-2.9.1.tar.gz" version="2.9.1"
+ repo="xmlsoft.org"
+ hash="sha256:fd3c64cb66f2c4ea27e934d275904d92cec494a8e8405613780cbc8a71680fdb"
+ md5sum="9c0cfef285d5c4a5c80d00904ddab380"/>
+ </autotools>
+
+ <autotools id="libxslt">
+ <branch module="/libxslt/libxslt-1.1.29.tar.gz" version="1.1.29"
+ repo="xmlsoft.org"
+ hash="sha256:b5976e3857837e7617b29f2249ebb5eeac34e249208d31f1fbf7a6ba7a4090ce"/>
+ <dependencies>
+ <dep package="libxml2"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="orc" autogenargs="--disable-gtk-doc" autogen-sh="configure">
+ <branch module="orc/orc-0.4.17.tar.gz" version="0.4.17"
+ repo="gstreamer"
+ hash="sha256:4fc7cca48c59fff23afee78fb642cdbde001f56401c8f47b95a16578d1d5d7e8"
+ md5sum="af1bf3dab9e69f3c36f389285e2a12a1"/>
+ </autotools>
+
+ <autotools id="gstreamer" autogenargs="--disable-gtk-doc" autogen-sh="configure">
+ <dependencies>
+ <dep package="orc"/>
+ </dependencies>
+ <branch module="gstreamer/gstreamer-1.8.0.tar.xz" version="1.8.0"
+ repo="gstreamer"
+ hash="sha256:947a314a212b5d94985d89b43440dbe66b696e12bbdf9a2f78967b98d74abedc"
+ md5sum="6846d7289ec323c38c49b818171e955a"/>
+ </autotools>
+
+ <autotools id="gst-plugins-base"
+ autogen-sh="configure"
+ autogenargs="--disable-examples --disable-gtk-doc">
+ <dependencies>
+ <dep package="gstreamer"/>
+ </dependencies>
+ <branch module="gst-plugins-base/gst-plugins-base-1.8.0.tar.xz" version="1.8.0"
+ repo="gstreamer"
+ hash="sha256:abc0acc1d15b4b9c97c65cd9689bd6400081853b9980ea428d3c8572dd791522"
+ md5sum="20cc8231609318310f2a55f64c86cbb4">
+ </branch>
+ </autotools>
+
+ <autotools id="gst-plugins-good" autogenargs="--disable-examples --disable-soup --disable-gtk-doc" autogen-sh="configure">
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="gst-plugins-good/gst-plugins-good-1.8.0.tar.xz" version="1.8.0"
+ repo="gstreamer"
+ hash="sha256:c20c134d47dbc238d921707a3b66da709c2b4dd89f9d267cec13d1ddf16e9f4d"
+ md5sum="91ed4649c7c2e43a61f731d144f6f6d0">
+ <patch file="gst-plugins-good-use-the-tfdt-decode-time.patch" strip="1"/>
+ <patch file="gst-plugins-good-Revert-qtdemux-expose-streams-with-first-moof-for-fr.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="gst-plugins-bad" autogenargs="--disable-examples --disable-gtk-doc">
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="gst-plugins-bad/gst-plugins-bad-1.8.0.tar.xz" version="1.8.0"
+ repo="gstreamer"
+ hash="sha256:116376dd1085082422e0b21b0ecd3d1cb345c469c58e32463167d4675f4ca90e"
+ md5sum="1c2d797bb96a81e9ef570c7a0a37203e">
+ </branch>
+ </autotools>
+
+ <autotools id="gst-libav" autogenargs="--with-libav-extra-configure='--disable-yasm' --disable-gtk-doc" autogen-sh="configure">
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ </dependencies>
+ <branch module="gst-libav/gst-libav-1.8.0.tar.xz" version="1.8.0"
+ repo="gstreamer"
+ hash="sha256:5a1ce28876aee93cb4f3d090f0e807915a5d9bc1325e3480dd302b85aeb4291c"
+ md5sum="361638fa45466c5050bcde6bfe10fa46">
+ <patch file="gst-libav.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="atk"
+ autogen-sh="configure"
+ autogenargs="--disable-introspection">
+ <branch module="pub/GNOME/sources/atk/2.15/atk-2.15.2.tar.xz" version="2.15.2"
+ repo="ftp.gnome.org"
+ hash="sha256:179d15424b8aa3a5726903f0da458de68e0585dfd9d451c6dcfcdb6b7b509cbe"/>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="libusrsctp" supports-non-srcdir-builds="no" autogen-sh="./bootstrap; ./configure --disable-warnings-as-errors">
+ <branch repo="github.com" module="sctplab/usrsctp/archive/078ff3252f73327e0ac11d6fd5eff62011f6646e.tar.gz" version="078ff3252f73327e0ac11d6fd5eff62011f6646e" checkoutdir="libusrsctp"
+ hash="sha256:175938887dc7554e000152055c818bdd15dd0e4ccc94ef93e38e9f952ea82edc" size="648925">
+ </branch>
+ </autotools>
+
+ <autotools id="gst-plugins-openwebrtc" supports-parallel-builds="no" supports-non-srcdir-builds="no" autogen-sh="./autogen.sh; ./configure">
+ <dependencies>
+ <dep package="gst-plugins-base"/>
+ <dep package="libusrsctp"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc-gst-plugins/archive/e359b67484af90f416ea35e301205d2b53c77a14.tar.gz" checkoutdir="gst-plugins-openwebrtc" version="gst-plugins-openwebrtc-20150317"
+ hash="sha256:a456425efb88de39c16a4f8ac4214aaf53157f9df1323f08de375c77f227b6b7"
+ md5sum="827f13634ffa83cccf1a6312effbceaa" size="92883">
+ <patch file="openwebrtc-gst-plugins-clang-warning-fix.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="libnice" supports-non-srcdir-builds="no">
+ <dependencies>
+ <dep package="gstreamer"/>
+ </dependencies>
+ <branch repo="nice.freedesktop.org" module="releases/libnice-0.1.13.tar.gz" checkoutdir="libnice" version="0.1.13"
+ hash="sha256:61112d9f3be933a827c8365f20551563953af6718057928f51f487bfe88419e1"
+ md5sum="3226faeaf48a9150ada00da2e2865959" size="912374">
+ </branch>
+ </autotools>
+
+ <autotools id="openwebrtc" autogenargs="--enable-bridge=no --enable-owr-gst=yes">
+ <dependencies>
+ <dep package="gst-plugins-openwebrtc"/>
+ <dep package="libnice"/>
+ </dependencies>
+ <branch repo="github.com" module="EricssonResearch/openwebrtc/archive/f511ea1fa79a33fa3d52bfd1c0969c28084aeb35.tar.gz" checkoutdir="openwebrtc" version="f511ea1fa79a33fa3d52bfd1c0969c28084aeb35"
+ hash="sha256:af80b80512b5f5a6b82b4cf43afa28da9c94c86800f6fadd10762361079fb5e3"
+ md5sum="4555d20821af8f5334f74b4f0327f178" size="296143">
+ </branch>
+ </autotools>
+
+</moduleset>
</ins></span></pre></div>
<a id="trunkToolsefljhbuildrc"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/jhbuildrc (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/jhbuildrc         (rev 0)
+++ trunk/Tools/efl/jhbuildrc        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+#!/usr/bin/env python
+# Copyright (C) 2011 Igalia S.L.
+# Copyright (C) 2012 Intel Corporation
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import platform
+
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../jhbuild") )
+import jhbuildrc_common
+
+jhbuildrc_common.init(globals(), "efl")
+
+addpath('XDG_DATA_DIRS', '/usr/share')
+addpath('XDG_CONFIG_DIRS', '/etc/xdg')
+
+partial_build = False
</ins></span></pre></div>
<a id="trunkToolseflpatchesevasfixbuildwithgiflib5patch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/evas-fix-build-with-giflib5.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/evas-fix-build-with-giflib5.patch         (rev 0)
+++ trunk/Tools/efl/patches/evas-fix-build-with-giflib5.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+Patch from Doug Newgard, available at https://phab.enlightenment.org/D200
+
+diff --git a/src/modules/loaders/gif/evas_image_load_gif.c b/src/modules/loaders/gif/evas_image_load_gif.c
+index 18a6e23..6b6ef3d 100644
+--- a/src/modules/loaders/gif/evas_image_load_gif.c
++++ b/src/modules/loaders/gif/evas_image_load_gif.c
+@@ -700,7 +700,11 @@ evas_image_load_file_head_gif(Image_Entry *ie, const char *file, const char *key
+ return EINA_FALSE;
+ }
+
++#if GIFLIB_MAJOR >= 5
++ gif = DGifOpenFileHandle(fd, NULL);
++#else
+ gif = DGifOpenFileHandle(fd);
++#endif
+ if (!gif)
+ {
+ if (fd) close(fd);
+@@ -838,7 +842,11 @@ evas_image_load_specific_frame(Image_Entry *ie, const char *file, int frame_inde
+ return EINA_FALSE;
+ }
+
++#if GIFLIB_MAJOR >= 5
++ gif = DGifOpenFileHandle(fd, NULL);
++#else
+ gif = DGifOpenFileHandle(fd);
++#endif
+ if (!gif)
+ {
+ if (fd) close(fd);
+@@ -927,7 +935,11 @@ evas_image_load_file_data_gif(Image_Entry *ie, const char *file, const char *key
+ return EINA_FALSE;
+ }
+
++#if GIFLIB_MAJOR >= 5
++ gif = DGifOpenFileHandle(fd, NULL);
++#else
+ gif = DGifOpenFileHandle(fd);
++#endif
+ if (!gif)
+ {
+ if (fd) close(fd);
+@@ -1000,7 +1012,11 @@ evas_image_load_frame_duration_gif(Image_Entry *ie, const char *file, const int
+ #endif
+ if (fd < 0) return -1;
+
++#if GIFLIB_MAJOR >=5
++ gif = DGifOpenFileHandle(fd, NULL);
++#else
+ gif = DGifOpenFileHandle(fd);
++#endif
+ if (!gif)
+ {
+ if (fd) close(fd);
</ins></span></pre></div>
<a id="trunkToolseflpatchesfontconfigC11requiresaspacebetweenliteralandidentifierpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch         (rev 0)
+++ trunk/Tools/efl/patches/fontconfig-C-11-requires-a-space-between-literal-and-identifier.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+From 7069d717e982adcf8e1d300cbd10eec6322a65c9 Mon Sep 17 00:00:00 2001
+From: Akira TAGOH <akira@tagoh.org>
+Date: Sun, 22 Apr 2012 21:40:44 +0900
+Subject: [PATCH] C++11 requires a space between literal and identifier
+
+Reported by Buganini
+---
+ fontconfig/fontconfig.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
+index 0e2ca50..b27ccb5 100644
+--- a/fontconfig/fontconfig.h
++++ b/fontconfig/fontconfig.h
+@@ -112,9 +112,9 @@ typedef int                FcBool;
+ #define FC_DECORATIVE         "decorative"        /* Bool - true if style is a decorative variant */
+ #define FC_LCD_FILTER         "lcdfilter"                /* Int */
+
+-#define FC_CACHE_SUFFIX                 ".cache-"FC_CACHE_VERSION
+-#define FC_DIR_CACHE_FILE         "fonts.cache-"FC_CACHE_VERSION
+-#define FC_USER_CACHE_FILE         ".fonts.cache-"FC_CACHE_VERSION
++#define FC_CACHE_SUFFIX                 ".cache-" FC_CACHE_VERSION
++#define FC_DIR_CACHE_FILE         "fonts.cache-" FC_CACHE_VERSION
++#define FC_USER_CACHE_FILE         ".fonts.cache-" FC_CACHE_VERSION
+
+ /* Adjust outline rasterizer */
+ #define FC_CHAR_WIDTH         "charwidth"        /* Int */
+--
+1.8.3.2
+
</ins></span></pre></div>
<a id="trunkToolseflpatchesgstlibavpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/gst-libav.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/gst-libav.patch         (rev 0)
+++ trunk/Tools/efl/patches/gst-libav.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+--- a/gst-libs/ext/libav/libavcodec/arm/videodsp_armv5te.S
++++ b/gst-libs/ext/libav/libavcodec/arm/videodsp_armv5te.S
+@@ -27,6 +27,7 @@
+ subs r2, r2, #1
+ pld [r0]
+ add r0, r0, r1
++ it ne
+ bne 1b
+ bx lr
+
+--- a/gst-libs/ext/libav/libswresample/arm/audio_convert_neon.S
++++ b/gst-libs/ext/libav/libswresample/arm/audio_convert_neon.S
+@@ -134,6 +134,7 @@ function swri_oldapi_conv_fltp_to_s16_nch_neon, export=1
+ itt lt
+ ldrlt r1, [r1]
+ blt X(swri_oldapi_conv_flt_to_s16_neon)
++ it eq
+ beq X(swri_oldapi_conv_fltp_to_s16_2ch_neon)
+
+ push {r4-r8, lr}
</ins></span></pre></div>
<a id="trunkToolseflpatchesgstpluginsbasertprtcpbufferfixtypoinenumpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/gst-plugins-base-rtp-rtcpbuffer-fix-typo-in-enum.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/gst-plugins-base-rtp-rtcpbuffer-fix-typo-in-enum.patch         (rev 0)
+++ trunk/Tools/efl/patches/gst-plugins-base-rtp-rtcpbuffer-fix-typo-in-enum.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+From dfc34c58411f50b37b2e1300560ae8a0b6a9a7d4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= <tim@centricular.com>
+Date: Tue, 7 Apr 2015 16:43:59 +0100
+Subject: [PATCH] rtp: rtcpbuffer: fix typo in enum
+
+and in docs. Spotted by Rob Swain.
+---
+ gst-libs/gst/rtp/gstrtcpbuffer.h | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/gst-libs/gst/rtp/gstrtcpbuffer.h b/gst-libs/gst/rtp/gstrtcpbuffer.h
+index b5ff4a1..47378cf 100644
+--- a/gst-libs/gst/rtp/gstrtcpbuffer.h
++++ b/gst-libs/gst/rtp/gstrtcpbuffer.h
+@@ -59,6 +59,9 @@ typedef enum
+ GST_RTCP_TYPE_PSFB = 206
+ } GstRTCPType;
+
++/* FIXME 2.0: backwards compatibility define for enum typo */
++#define GST_RTCP_RTPFB_TYPE_RCTP_SR_REQ GST_RTCP_RTPFB_TYPE_RTCP_SR_REQ
++
+ /**
+ * GstRTCPFBType:
+ * @GST_RTCP_FB_TYPE_INVALID: Invalid type
+@@ -66,7 +69,7 @@ typedef enum
+ * @GST_RTCP_RTPFB_TYPE_TMMBR: Temporary Maximum Media Stream Bit Rate Request
+ * @GST_RTCP_RTPFB_TYPE_TMMBN: Temporary Maximum Media Stream Bit Rate
+ * Notification
+- * @GST_RTCP_RTPFB_TYPE_RTCP_SR_SEQ: Request an SR packet for early
++ * @GST_RTCP_RTPFB_TYPE_RTCP_SR_REQ: Request an SR packet for early
+ * synchronization
+ * @GST_RTCP_PSFB_TYPE_PLI: Picture Loss Indication
+ * @GST_RTCP_PSFB_TYPE_SLI: Slice Loss Indication
+@@ -89,7 +92,7 @@ typedef enum
+ GST_RTCP_RTPFB_TYPE_TMMBR = 3,
+ GST_RTCP_RTPFB_TYPE_TMMBN = 4,
+ /* RTPFB types assigned in RFC 6051 */
+- GST_RTCP_RTPFB_TYPE_RCTP_SR_REQ = 5,
++ GST_RTCP_RTPFB_TYPE_RTCP_SR_REQ = 5,
+ /* PSFB types */
+ GST_RTCP_PSFB_TYPE_PLI = 1,
+ GST_RTCP_PSFB_TYPE_SLI = 2,
+--
+2.1.4
+
</ins></span></pre></div>
<a id="trunkToolseflpatchesgstpluginsgoodRevertqtdemuxexposestreamswithfirstmoofforfrpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/gst-plugins-good-Revert-qtdemux-expose-streams-with-first-moof-for-fr.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/gst-plugins-good-Revert-qtdemux-expose-streams-with-first-moof-for-fr.patch         (rev 0)
+++ trunk/Tools/efl/patches/gst-plugins-good-Revert-qtdemux-expose-streams-with-first-moof-for-fr.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,133 @@
</span><ins>+From 1a81bd90d4a3e59d6669a0bbfa456f1ed4e5db48 Mon Sep 17 00:00:00 2001
+From: Xabier Rodriguez Calvar <calvaris@igalia.com>
+Date: Thu, 7 Apr 2016 13:57:16 +0200
+Subject: [PATCH] Revert "qtdemux: expose streams with first moof for
+ fragmented format"
+
+This reverts commit d8bb6687ea251570c331038279a43d448167d6ad.
+---
+ gst/isomp4/qtdemux.c | 54 ++++++++++++++++------------------------------------
+ gst/isomp4/qtdemux.h | 1 -
+ 2 files changed, 16 insertions(+), 39 deletions(-)
+
+diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
+index 39be163..9636b4b 100644
+--- a/gst/isomp4/qtdemux.c
++++ b/gst/isomp4/qtdemux.c
+@@ -609,7 +609,6 @@ gst_qtdemux_init (GstQTDemux * qtdemux)
+ qtdemux->state = QTDEMUX_STATE_INITIAL;
+ qtdemux->pullbased = FALSE;
+ qtdemux->posted_redirect = FALSE;
+- qtdemux->pending_configure = FALSE;
+ qtdemux->neededbytes = 16;
+ qtdemux->todrop = 0;
+ qtdemux->adapter = gst_adapter_new ();
+@@ -2049,7 +2048,6 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
+ gst_caps_replace (&qtdemux->media_caps, NULL);
+ qtdemux->timescale = 0;
+ qtdemux->got_moov = FALSE;
+- qtdemux->pending_configure = FALSE;
+ } else if (qtdemux->mss_mode) {
+ gst_flow_combiner_reset (qtdemux->flowcombiner);
+ for (n = 0; n < qtdemux->n_streams; n++)
+@@ -6104,7 +6102,6 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
+ &fourcc);
+ if (fourcc == FOURCC_moov) {
+ gint n;
+- gboolean got_samples = FALSE;
+
+ /* in usual fragmented setup we could try to scan for more
+ * and end up at the the moov (after mdat) again */
+@@ -6136,27 +6133,19 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
+ qtdemux_node_dump (demux, demux->moov_node);
+ qtdemux_parse_tree (demux);
+ qtdemux_prepare_streams (demux);
++ if (!demux->got_moov)
++ qtdemux_expose_streams (demux);
++ else {
+
+- for (n = 0; n < demux->n_streams; n++) {
+- QtDemuxStream *stream = demux->streams[n];
+- got_samples |= stream->stbl_index >= 0;
+- }
+- if (!demux->fragmented || got_samples) {
+- if (!demux->got_moov) {
+- qtdemux_expose_streams (demux);
+- } else {
+- for (n = 0; n < demux->n_streams; n++) {
+- QtDemuxStream *stream = demux->streams[n];
+- gst_qtdemux_configure_stream (demux, stream);
+- }
++ for (n = 0; n < demux->n_streams; n++) {
++ QtDemuxStream *stream = demux->streams[n];
++
++ gst_qtdemux_configure_stream (demux, stream);
+ }
+- gst_qtdemux_check_send_pending_segment (demux);
+- demux->pending_configure = FALSE;
+- } else {
+- demux->pending_configure = TRUE;
+ }
+
+ demux->got_moov = TRUE;
++ gst_qtdemux_check_send_pending_segment (demux);
+
+ /* fragmented streams headers shouldn't contain edts atoms */
+ if (!demux->fragmented) {
+@@ -6175,7 +6164,6 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
+ guint64 dist = 0;
+ GstClockTime prev_pts;
+ guint64 prev_offset;
+- gint n;
+
+ GST_DEBUG_OBJECT (demux, "Parsing [moof]");
+
+@@ -6209,25 +6197,15 @@ gst_qtdemux_process_adapter (GstQTDemux * demux, gboolean force)
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
+- /* in MSS we need to expose the pads after the first moof as we won't get a moov
+- * Also, fragmented format need to be exposed if a moov have no valid sample data */
+- if (demux->mss_mode || demux->pending_configure) {
+- if (!demux->exposed) {
+- if (!demux->pending_newsegment) {
+- GstSegment segment;
+- gst_segment_init (&segment, GST_FORMAT_TIME);
+- GST_DEBUG_OBJECT (demux, "new pending_newsegment");
+- demux->pending_newsegment = gst_event_new_segment (&segment);
+- }
+- qtdemux_expose_streams (demux);
+- } else {
+- for (n = 0; n < demux->n_streams; n++) {
+- QtDemuxStream *stream = demux->streams[n];
+- gst_qtdemux_configure_stream (demux, stream);
+- }
++ /* in MSS we need to expose the pads after the first moof as we won't get a moov */
++ if (demux->mss_mode && !demux->exposed) {
++ if (!demux->pending_newsegment) {
++ GstSegment segment;
++ gst_segment_init (&segment, GST_FORMAT_TIME);
++ GST_DEBUG_OBJECT (demux, "new pending_newsegment");
++ demux->pending_newsegment = gst_event_new_segment (&segment);
+ }
+- gst_qtdemux_check_send_pending_segment (demux);
+- demux->pending_configure = FALSE;
++ qtdemux_expose_streams (demux);
+ }
+ } else {
+ GST_DEBUG_OBJECT (demux, "Discarding [moof]");
+diff --git a/gst/isomp4/qtdemux.h b/gst/isomp4/qtdemux.h
+index 6061215..ecf0c63 100644
+--- a/gst/isomp4/qtdemux.h
++++ b/gst/isomp4/qtdemux.h
+@@ -89,7 +89,6 @@ struct _GstQTDemux {
+ gboolean posted_redirect;
+
+ /* push based variables */
+- gboolean pending_configure;
+ guint neededbytes;
+ guint todrop;
+ GstAdapter *adapter;
+--
+2.8.0.rc3
+
</ins></span></pre></div>
<a id="trunkToolseflpatchesgstpluginsgoodusethetfdtdecodetimepatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/gst-plugins-good-use-the-tfdt-decode-time.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/gst-plugins-good-use-the-tfdt-decode-time.patch         (rev 0)
+++ trunk/Tools/efl/patches/gst-plugins-good-use-the-tfdt-decode-time.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,146 @@
</span><ins>+From 46d3e0faa922643094a5e46a32e4f82f774ae772 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Enrique=20Oca=C3=B1a=20Gonz=C3=A1lez?= <eocanha@igalia.com>
+Date: Tue, 10 Nov 2015 13:09:00 +0100
+Subject: [PATCH] Use the tfdt decode time when it's significantly different
+ than the time in the last sample if always-honor-tfdt is enabled
+
+https://bugzilla.gnome.org/show_bug.cgi?id=754230
+---
+ gst/isomp4/qtdemux.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ gst/isomp4/qtdemux.h | 1 +
+ 2 files changed, 73 insertions(+)
+
+diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
+index 880595e..d8b54f0 100644
+--- a/gst/isomp4/qtdemux.c
++++ b/gst/isomp4/qtdemux.c
+@@ -535,6 +535,11 @@ static void gst_qtdemux_append_protection_system_id (GstQTDemux * qtdemux,
+ const gchar * id);
+ static void qtdemux_gst_structure_free (GstStructure * gststructure);
+
++static void gst_qtdemux_set_property (GObject * object, guint prop_id,
++ const GValue * value, GParamSpec * spec);
++static void gst_qtdemux_get_property (GObject * object, guint prop_id,
++ GValue * value, GParamSpec * spec);
++
+ static void
+ gst_qtdemux_class_init (GstQTDemuxClass * klass)
+ {
+@@ -546,8 +551,21 @@ gst_qtdemux_class_init (GstQTDemuxClass * klass)
+
+ parent_class = g_type_class_peek_parent (klass);
+
++ gobject_class->set_property = gst_qtdemux_set_property;
++ gobject_class->get_property = gst_qtdemux_get_property;
++
+ gobject_class->dispose = gst_qtdemux_dispose;
+
++ /**
++ * GstQtDemux::always-honor-tfdt:
++ *
++ * Requests the demuxer to respect what the TFDT atom says in order to produce presentation timestamps. Defaults to FALSE.
++ */
++ g_object_class_install_property (gobject_class, PROP_ALWAYS_HONOR_TFDT,
++ g_param_spec_boolean ("always-honor-tfdt", "Always honor TFDT",
++ "When enabled, TFDT atom will always be respected in order to produce presentation timestamps",
++ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
++
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qtdemux_change_state);
+ #if 0
+ gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_qtdemux_set_index);
+@@ -611,6 +629,7 @@ gst_qtdemux_init (GstQTDemux * qtdemux)
+ qtdemux->cenc_aux_info_sizes = NULL;
+ qtdemux->cenc_aux_sample_count = 0;
+ qtdemux->protection_system_ids = NULL;
++ qtdemux->always_honor_tfdt = FALSE;
+ g_queue_init (&qtdemux->protection_event_queue);
+ gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
+ qtdemux->flowcombiner = gst_flow_combiner_new ();
+@@ -639,6 +658,42 @@ gst_qtdemux_dispose (GObject * object)
+ }
+
+ static void
++gst_qtdemux_set_property (GObject * object, guint prop_id,
++ const GValue * value, GParamSpec * pspec)
++{
++ GstQTDemux *qtdemux = GST_QTDEMUX (object);
++
++ switch (prop_id) {
++ case PROP_ALWAYS_HONOR_TFDT:
++ GST_OBJECT_LOCK (qtdemux);
++ qtdemux->always_honor_tfdt = g_value_get_boolean (value);
++ GST_OBJECT_UNLOCK (qtdemux);
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static void
++gst_qtdemux_get_property (GObject * object, guint prop_id, GValue * value,
++ GParamSpec * pspec)
++{
++ GstQTDemux *qtdemux = GST_QTDEMUX (object);
++
++ switch (prop_id) {
++ case PROP_ALWAYS_HONOR_TFDT:
++ GST_OBJECT_LOCK (qtdemux);
++ g_value_set_boolean (value, qtdemux->always_honor_tfdt);
++ GST_OBJECT_UNLOCK (qtdemux);
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++ break;
++ }
++}
++
++static void
+ gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
+ {
+ if (qtdemux->posted_redirect) {
+@@ -2995,6 +3050,16 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
+ stream->samples[stream->n_samples - 1].timestamp +
+ stream->samples[stream->n_samples - 1].duration;
+
++ /* If we're always honoring TFDT and there's a significative difference
++ * between the decode_ts and the timestamp, prefer decode_ts */
++ if (qtdemux->always_honor_tfdt == TRUE
++ && abs (decode_ts - timestamp) >
++ stream->samples[stream->n_samples - 1].duration) {
++ GST_INFO_OBJECT (qtdemux,
++ "decode_ts is significantly different from timestamp, using decode_ts");
++ timestamp = decode_ts;
++ }
++
+ gst_ts = QTSTREAMTIME_TO_GSTTIME (stream, timestamp);
+ GST_INFO_OBJECT (qtdemux, "first sample ts %" GST_TIME_FORMAT
+ " (extends previous samples)", GST_TIME_ARGS (gst_ts));
+diff --git a/gst/isomp4/qtdemux.h b/gst/isomp4/qtdemux.h
+index 53bd071..ecf0c63 100644
+--- a/gst/isomp4/qtdemux.h
++++ b/gst/isomp4/qtdemux.h
+@@ -154,12 +154,20 @@ struct _GstQTDemux {
+ guint8 *cenc_aux_info_sizes;
+ guint32 cenc_aux_sample_count;
+
++ gboolean always_honor_tfdt;
+ };
+
+ struct _GstQTDemuxClass {
+ GstElementClass parent_class;
+ };
+
++/* props */
++enum
++{
++ PROP_0,
++ PROP_ALWAYS_HONOR_TFDT
++};
++
+ GType gst_qtdemux_get_type (void);
+
+ G_END_DECLS
+--
+2.6.1
+
</ins></span></pre></div>
<a id="trunkToolseflpatchesopenwebrtcgstpluginsclangwarningfixpatch"></a>
<div class="addfile"><h4>Added: trunk/Tools/efl/patches/openwebrtc-gst-plugins-clang-warning-fix.patch (0 => 212517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/efl/patches/openwebrtc-gst-plugins-clang-warning-fix.patch         (rev 0)
+++ trunk/Tools/efl/patches/openwebrtc-gst-plugins-clang-warning-fix.patch        2017-02-17 02:15:35 UTC (rev 212517)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+diff --git a/gst/videorepair/Makefile.am b/gst/videorepair/Makefile.am
+index 34487b5..34c3887 100644
+--- a/gst/videorepair/Makefile.am
++++ b/gst/videorepair/Makefile.am
+@@ -17,7 +17,7 @@ plugin_LTLIBRARIES = libgstvideorepair.la
+ libgstvideorepair_la_SOURCES = gstvideorepair.c
+
+ # compiler and linker flags used to compile this plugin, set in configure.ac
+-libgstvideorepair_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -Wall -Wextra -Werror
++libgstvideorepair_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -Wall -Wextra
+ libgstvideorepair_la_LIBADD = $(GST_LIBS) -lgstvideo-1.0
+ libgstvideorepair_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+ if !GST_PLUGIN_BUILD_STATIC
</ins></span></pre>
</div>
</div>
</body>
</html>