[EFL][WK2] Add API to execute js script

https://bugs.webkit.org/show_bug.cgi?id=101904

Reviewed by Gyuyoung Kim.

Add ewk_view_script_execute() which provides a way to execute user
script.

* UIProcess/API/efl/ewk_context.cpp:
Added JS Global Contexta which is required to deserialize to the script
value from the callback.
(EwkContext::EwkContext):
(EwkContext::~EwkContext):
(EwkContext::jsGlobalContext):
* UIProcess/API/efl/ewk_context_private.h:
* UIProcess/API/efl/ewk_view.cpp:
(Ewk_View_Script_Execute_Callback_Context::Ewk_View_Script_Execute_Callback_Context):
(runJavaScriptCallback):
(ewk_view_script_execute):
* UIProcess/API/efl/ewk_view.h:
* UIProcess/API/efl/tests/test_ewk2_view.cpp:
Added unit test for ewk_view_script_execute.
(scriptExecuteCallback):
(TEST_F):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@161527 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 3beac403
2014-01-08 Ryuan Choi <ryuan.choi@samsung.com>
[EFL][WK2] Add API to execute js script
https://bugs.webkit.org/show_bug.cgi?id=101904
Reviewed by Gyuyoung Kim.
Add ewk_view_script_execute() which provides a way to execute user
script.
* UIProcess/API/efl/ewk_context.cpp:
Added JS Global Contexta which is required to deserialize to the script
value from the callback.
(EwkContext::EwkContext):
(EwkContext::~EwkContext):
(EwkContext::jsGlobalContext):
* UIProcess/API/efl/ewk_context_private.h:
* UIProcess/API/efl/ewk_view.cpp:
(Ewk_View_Script_Execute_Callback_Context::Ewk_View_Script_Execute_Callback_Context):
(runJavaScriptCallback):
(ewk_view_script_execute):
* UIProcess/API/efl/ewk_view.h:
* UIProcess/API/efl/tests/test_ewk2_view.cpp:
Added unit test for ewk_view_script_execute.
(scriptExecuteCallback):
(TEST_F):
2014-01-08 Gyuyoung Kim <gyuyoung.kim@samsung.com>
[EFL] Move efl API test binaries to TestWebKitAPI/EWebKit|EWebKit2
......
......@@ -39,6 +39,7 @@
#include "ewk_private.h"
#include "ewk_storage_manager_private.h"
#include "ewk_url_scheme_request_private.h"
#include <JavaScriptCore/JSContextRef.h>
#include <WebCore/FileSystem.h>
#include <WebCore/IconDatabase.h>
#include <wtf/HashMap.h>
......@@ -72,6 +73,7 @@ EwkContext::EwkContext(WKContextRef context)
, m_downloadManager(std::make_unique<DownloadManagerEfl>(context))
, m_requestManagerClient(std::make_unique<RequestManagerClientEfl>(context))
, m_historyClient(std::make_unique<ContextHistoryClientEfl>(context))
, m_jsGlobalContext(nullptr)
{
ContextMap::AddResult result = contextMap().add(context, this);
ASSERT_UNUSED(result, result.isNewEntry);
......@@ -96,6 +98,10 @@ EwkContext::EwkContext(WKContextRef context)
EwkContext::~EwkContext()
{
ASSERT(contextMap().get(m_context.get()) == this);
if (m_jsGlobalContext)
JSGlobalContextRelease(m_jsGlobalContext);
contextMap().remove(m_context.get());
}
......@@ -214,6 +220,15 @@ void EwkContext::clearResourceCache()
WKResourceCacheManagerClearCacheForAllOrigins(WKContextGetResourceCacheManager(m_context.get()), WKResourceCachesToClearAll);
}
JSGlobalContextRef EwkContext::jsGlobalContext()
{
if (!m_jsGlobalContext)
m_jsGlobalContext = JSGlobalContextCreate(0);
return m_jsGlobalContext;
}
Ewk_Cookie_Manager* ewk_context_cookie_manager_get(const Ewk_Context* ewkContext)
{
EWK_OBJ_GET_IMPL_OR_RETURN(const EwkContext, ewkContext, impl, 0);
......
......@@ -22,6 +22,7 @@
#include "ewk_context.h"
#include "ewk_object_private.h"
#include <JavaScriptCore/JSContextRef.h>
#include <WebKit2/WKBase.h>
#include <WebKit2/WKRetainPtr.h>
#include <wtf/RefPtr.h>
......@@ -85,6 +86,8 @@ public:
void clearResourceCache();
JSGlobalContextRef jsGlobalContext();
private:
explicit EwkContext(WKContextRef);
......@@ -106,6 +109,8 @@ private:
std::unique_ptr<WebKit::RequestManagerClientEfl> m_requestManagerClient;
std::unique_ptr<WebKit::ContextHistoryClientEfl> m_historyClient;
JSGlobalContextRef m_jsGlobalContext;
};
#endif // ewk_context_private_h
......@@ -40,6 +40,7 @@
#include "ewk_private.h"
#include "ewk_settings_private.h"
#include <Ecore_Evas.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <WebKit2/WKAPICast.h>
#include <WebKit2/WKData.h>
#include <WebKit2/WKEinaSharedString.h>
......@@ -47,6 +48,7 @@
#include <WebKit2/WKInspector.h>
#include <WebKit2/WKPageGroup.h>
#include <WebKit2/WKRetainPtr.h>
#include <WebKit2/WKSerializedScriptValue.h>
#include <WebKit2/WKString.h>
#include <WebKit2/WKURL.h>
#include <WebKit2/WKView.h>
......@@ -625,3 +627,51 @@ Eina_Bool ewk_view_source_mode_get(const Evas_Object* ewkView)
return WKViewGetShowsAsSource(impl->wkView());
}
struct Ewk_View_Script_Execute_Callback_Context {
Ewk_View_Script_Execute_Callback_Context(Ewk_View_Script_Execute_Cb callback, Evas_Object* ewkView, void* userData)
: m_callback(callback)
, m_view(ewkView)
, m_userData(userData)
{
}
Ewk_View_Script_Execute_Cb m_callback;
Evas_Object* m_view;
void* m_userData;
};
static void runJavaScriptCallback(WKSerializedScriptValueRef scriptValue, WKErrorRef, void* context)
{
ASSERT(context);
auto callbackContext = std::unique_ptr<Ewk_View_Script_Execute_Callback_Context>(static_cast<Ewk_View_Script_Execute_Callback_Context*>(context));
ASSERT(callbackContext->m_view);
if (!callbackContext->m_callback)
return;
if (scriptValue) {
EWK_VIEW_IMPL_GET_OR_RETURN(callbackContext->m_view, impl);
JSGlobalContextRef jsGlobalContext = impl->ewkContext()->jsGlobalContext();
JSValueRef value = WKSerializedScriptValueDeserialize(scriptValue, jsGlobalContext, 0);
JSRetainPtr<JSStringRef> jsStringValue(Adopt, JSValueToStringCopy(jsGlobalContext, value, 0));
size_t length = JSStringGetMaximumUTF8CStringSize(jsStringValue.get());
auto buffer = std::make_unique<char[]>(length);
JSStringGetUTF8CString(jsStringValue.get(), buffer.get(), length);
callbackContext->m_callback(callbackContext->m_view, buffer.get(), callbackContext->m_userData);
} else
callbackContext->m_callback(callbackContext->m_view, 0, callbackContext->m_userData);
}
Eina_Bool ewk_view_script_execute(Evas_Object* ewkView, const char* script, Ewk_View_Script_Execute_Cb callback, void* userData)
{
EWK_VIEW_IMPL_GET_OR_RETURN(ewkView, impl, false);
EINA_SAFETY_ON_NULL_RETURN_VAL(script, false);
Ewk_View_Script_Execute_Callback_Context* context = new Ewk_View_Script_Execute_Callback_Context(callback, ewkView, userData);
WKRetainPtr<WKStringRef> scriptString(AdoptWK, WKStringCreateWithUTF8CString(script));
WKPageRunJavaScriptInMainFrame(impl->wkPage(), scriptString.get(), context, runJavaScriptCallback);
return true;
}
......@@ -278,6 +278,12 @@ typedef enum {
EWK_PAGINATION_MODE_BOTTOM_TO_TOP /**< go to the next page with scrolling bottom to top vertically. */
} Ewk_Pagination_Mode;
/**
* @typedef Ewk_View_Script_Execute_Cb Ewk_View_Script_Execute_Cb
* @brief Callback type for use with ewk_view_script_execute()
*/
typedef void (*Ewk_View_Script_Execute_Cb)(Evas_Object *o, const char *return_value, void *user_data);
/**
* Creates a type name for the callback function used to get the page contents.
*
......@@ -884,6 +890,20 @@ EAPI Eina_Bool ewk_view_source_mode_set(Evas_Object *o, Eina_Bool enabled);
*/
EAPI Eina_Bool ewk_view_source_mode_get(const Evas_Object *o);
/**
* Requests execution of the given script.
*
* The result value for the execution can be retrieved from the asynchronous callback.
*
* @param o The view to execute script
* @param script JavaScript to execute
* @param callback The function to call when the execution is completed, may be @c NULL
* @param user_data User data, may be @c NULL
*
* @return @c EINA_TRUE on success or @c EINA_FALSE on failure
*/
EAPI Eina_Bool ewk_view_script_execute(Evas_Object *o, const char *script, Ewk_View_Script_Execute_Cb callback, void *user_data);
#ifdef __cplusplus
}
#endif
......
......@@ -30,6 +30,7 @@ extern EWK2UnitTestEnvironment* environment;
static bool fullScreenCallbackCalled;
static bool obtainedPageContents = false;
static bool scriptExecuteCallbackCalled;
static struct {
const char* expectedMessage;
......@@ -1033,3 +1034,52 @@ TEST_F(EWK2ViewTest, ewk_view_user_agent)
ASSERT_STREQ(defaultUserAgent, ewk_view_user_agent_get(webView()));
eina_stringshare_del(defaultUserAgent);
}
static void scriptExecuteCallback(Evas_Object*, const char* returnValue, void* userData)
{
Eina_Strbuf* buffer = static_cast<Eina_Strbuf*>(userData);
eina_strbuf_reset(buffer);
if (returnValue)
eina_strbuf_append(buffer, returnValue);
scriptExecuteCallbackCalled = true;
}
TEST_F(EWK2UnitTestBase, ewk_view_script_execute)
{
const char scriptExecuteHTML[] =
"<!DOCTYPE html>"
"<body>"
"<p id=\"TestContent\">test content</p>"
"</body>";
ewk_view_html_string_load(webView(), scriptExecuteHTML, 0, 0);
ASSERT_TRUE(waitUntilLoadFinished());
Eina_Strbuf* result = eina_strbuf_new();
// 1. Get the innerHTML for "TestContent"
const char getDataScript[] = "document.getElementById('TestContent').innerHTML";
scriptExecuteCallbackCalled = false;
ASSERT_TRUE(ewk_view_script_execute(webView(), getDataScript, scriptExecuteCallback, static_cast<void*>(result)));
waitUntilTrue(scriptExecuteCallbackCalled);
ASSERT_STREQ("test content", eina_strbuf_string_get(result));
// 2. Change the innerHTML for "TestContent"
const char changeDataScript[] =
"document.getElementById('TestContent').innerHTML = \"test\";";
ASSERT_TRUE(ewk_view_script_execute(webView(), changeDataScript, 0, 0));
// 3. Check the change of the innerHTML.
eina_strbuf_reset(result);
scriptExecuteCallbackCalled = false;
ASSERT_TRUE(ewk_view_script_execute(webView(), getDataScript, scriptExecuteCallback, static_cast<void*>(result)));
waitUntilTrue(scriptExecuteCallbackCalled);
ASSERT_STREQ("test", eina_strbuf_string_get(result));
eina_strbuf_free(result);
ASSERT_FALSE(ewk_view_script_execute(webView(), 0, 0, 0));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment