blob: d24bf3606d244692a53ce0ca47ea09da467f8a83 [file] [log] [blame]
/*
* Copyright (C) 2011 ProFUSION Embedded Systems
* Copyright (C) 2011 Samsung Electronics
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Red istributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define __STDC_FORMAT_MACROS
#include "config.h"
#include "DumpRenderTreeView.h"
#include "DumpRenderTree.h"
#include "DumpRenderTreeChrome.h"
#include "DumpRenderTreeEfl.h"
#include "TestRunner.h"
#include <EWebKit.h>
#include <Ecore.h>
#include <Eina.h>
#include <Evas.h>
#include <cstdio>
#include <cstdlib>
#include <inttypes.h>
#include <wtf/NotFound.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>
using namespace std;
static Ewk_View_Smart_Class gParentSmartClass = EWK_VIEW_SMART_CLASS_INIT_NULL;
static WTF::String urlSuitableForTestResult(const WTF::String& uriString)
{
if (uriString.isEmpty() || !uriString.startsWith("file://"))
return uriString;
const size_t index = uriString.reverseFind('/');
return (index == WTF::notFound) ? uriString : uriString.substring(index + 1);
}
static void onConsoleMessage(Ewk_View_Smart_Data* smartData, const char* message, unsigned lineNumber, const char*)
{
Evas_Object* evasObject = smartData->self;
if (evas_object_data_get(evasObject, "ignore-console-messages"))
return;
// Tests expect only the filename part of local URIs
WTF::String newMessage = WTF::String::fromUTF8(message);
if (!newMessage.isEmpty()) {
const size_t fileProtocol = newMessage.find("file://");
if (fileProtocol != WTF::notFound)
newMessage = newMessage.left(fileProtocol) + urlSuitableForTestResult(newMessage.substring(fileProtocol));
}
// Ignore simple translation-related messages and unnecessary messages
if (newMessage.contains("Localized string") || newMessage.contains("Protocol Error: the message is for non-existing domain 'Profiler'"))
return;
printf("CONSOLE MESSAGE: ");
if (lineNumber)
printf("line %u: ", lineNumber);
printf("%s\n", newMessage.utf8().data());
}
static void onJavaScriptAlert(Ewk_View_Smart_Data*, Evas_Object*, const char* message)
{
printf("ALERT: %s\n", message);
fflush(stdout);
}
static Eina_Bool onJavaScriptConfirm(Ewk_View_Smart_Data*, Evas_Object*, const char* message)
{
printf("CONFIRM: %s\n", message);
return EINA_TRUE;
}
static Eina_Bool onJavaScriptPrompt(Ewk_View_Smart_Data*, Evas_Object*, const char* message, const char* defaultValue, const char** value)
{
printf("PROMPT: %s, default text: %s\n", message, defaultValue);
*value = eina_stringshare_add(defaultValue);
return EINA_TRUE;
}
static Evas_Object* onWindowCreate(Ewk_View_Smart_Data*, Eina_Bool, const Ewk_Window_Features*)
{
return gTestRunner->canOpenWindows() ? browser->createNewWindow() : 0;
}
static Eina_Bool onWindowCloseDelayed(void* data)
{
Evas_Object* view = static_cast<Evas_Object*>(data);
browser->removeWindow(view);
return EINA_FALSE;
}
static void onWindowClose(Ewk_View_Smart_Data* smartData)
{
Evas_Object* view = smartData->self;
ecore_idler_add(onWindowCloseDelayed, view);
}
static uint64_t onExceededDatabaseQuota(Ewk_View_Smart_Data* smartData, Evas_Object* frame, const char* databaseName, uint64_t currentSize, uint64_t expectedSize)
{
if (!gTestRunner->dumpDatabaseCallbacks())
return 0;
Ewk_Security_Origin* origin = ewk_frame_security_origin_get(frame);
printf("UI DELEGATE DATABASE CALLBACK: exceededDatabaseQuotaForSecurityOrigin:{%s, %s, %i} database:%s\n",
ewk_security_origin_protocol_get(origin),
ewk_security_origin_host_get(origin),
ewk_security_origin_port_get(origin),
databaseName);
ewk_security_origin_free(origin);
return 5 * 1024 * 1024;
}
static int64_t onExceededApplicationCacheQuota(Ewk_View_Smart_Data*, Ewk_Security_Origin *origin, int64_t defaultOriginQuota, int64_t totalSpaceNeeded)
{
if (gTestRunner->dumpApplicationCacheDelegateCallbacks()) {
// For example, numbers from 30000 - 39999 will output as 30000.
// Rounding up or down does not really matter for these tests. It's
// sufficient to just get a range of 10000 to determine if we were
// above or below a threshold.
int64_t truncatedSpaceNeeded = (totalSpaceNeeded / 10000) * 10000;
printf("UI DELEGATE APPLICATION CACHE CALLBACK: exceededApplicationCacheOriginQuotaForSecurityOrigin:{%s, %s, %i} totalSpaceNeeded:~%" PRId64 "\n",
ewk_security_origin_protocol_get(origin),
ewk_security_origin_host_get(origin),
ewk_security_origin_port_get(origin),
truncatedSpaceNeeded);
}
if (gTestRunner->disallowIncreaseForApplicationCacheQuota())
return 0;
return defaultOriginQuota;
}
static bool shouldUseTiledBackingStore()
{
const char* useTiledBackingStore = getenv("DRT_USE_TILED_BACKING_STORE");
return useTiledBackingStore && *useTiledBackingStore == '1';
}
static bool chooseAndInitializeAppropriateSmartClass(Ewk_View_Smart_Class* api)
{
return !shouldUseTiledBackingStore() ? ewk_view_single_smart_set(api) : ewk_view_tiled_smart_set(api);
}
// Taken from the file "WebKit/Tools/DumpRenderTree/chromium/WebViewHost.cpp".
static inline const char* navigationTypeToString(const Ewk_Navigation_Type type)
{
switch (type) {
case EWK_NAVIGATION_TYPE_LINK_CLICKED:
return "link clicked";
case EWK_NAVIGATION_TYPE_FORM_SUBMITTED:
return "form submitted";
case EWK_NAVIGATION_TYPE_BACK_FORWARD:
return "back/forward";
case EWK_NAVIGATION_TYPE_RELOAD:
return "reload";
case EWK_NAVIGATION_TYPE_FORM_RESUBMITTED:
return "form resubmitted";
case EWK_NAVIGATION_TYPE_OTHER:
return "other";
}
return "illegal value";
}
static Eina_Bool onNavigationPolicyDecision(Ewk_View_Smart_Data*, Ewk_Frame_Resource_Request* request, Ewk_Navigation_Type navigationType)
{
if (!policyDelegateEnabled)
return true;
printf("Policy delegate: attempt to load %s with navigation type '%s'\n", urlSuitableForTestResult(request->url).utf8().data(),
navigationTypeToString(navigationType));
if (gTestRunner)
gTestRunner->notifyDone();
return policyDelegatePermissive;
}
static Eina_Bool onFocusCanCycle(Ewk_View_Smart_Data*, Ewk_Focus_Direction)
{
// This is the behavior of Mac and Chromium ports and is expected by some test cases.
return true;
}
Evas_Object* drtViewAdd(Evas* evas)
{
static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("DRT_View");
if (!chooseAndInitializeAppropriateSmartClass(&api))
return 0;
if (EINA_UNLIKELY(!gParentSmartClass.sc.add))
ewk_view_base_smart_set(&gParentSmartClass);
api.add_console_message = onConsoleMessage;
api.run_javascript_alert = onJavaScriptAlert;
api.run_javascript_confirm = onJavaScriptConfirm;
api.run_javascript_prompt = onJavaScriptPrompt;
api.window_create = onWindowCreate;
api.window_close = onWindowClose;
api.exceeded_application_cache_quota = onExceededApplicationCacheQuota;
api.exceeded_database_quota = onExceededDatabaseQuota;
api.navigation_policy_decision = onNavigationPolicyDecision;
api.focus_can_cycle = onFocusCanCycle;
return evas_object_smart_add(evas, evas_smart_class_new(&api.sc));
}