QtBuiltinBundlePage.cpp [plain text]
#include "config.h"
#include "QtBuiltinBundlePage.h"
#include "QtBuiltinBundle.h"
#include "WKArray.h"
#include "WKBundleFrame.h"
#include "WKRetainPtr.h"
#include "WKString.h"
#include "WKStringPrivate.h"
#include "WKStringQt.h"
#include <JavaScript.h>
#include <JavaScriptCore/JSRetainPtr.h>
namespace WebKit {
QtBuiltinBundlePage::QtBuiltinBundlePage(QtBuiltinBundle* bundle, WKBundlePageRef page)
: m_bundle(bundle)
, m_page(page)
, m_navigatorQtObject(0)
, m_navigatorQtObjectEnabled(false)
{
WKBundlePageLoaderClient loaderClient = {
kWKBundlePageLoaderClientCurrentVersion,
this,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, didClearWindowForFrame,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
WKBundlePageSetPageLoaderClient(m_page, &loaderClient);
}
QtBuiltinBundlePage::~QtBuiltinBundlePage()
{
if (!m_navigatorQtObject)
return;
WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
JSValueUnprotect(context, m_navigatorQtObject);
}
void QtBuiltinBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
{
static_cast<QtBuiltinBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
}
static JSValueRef qt_postMessageCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
{
if (argumentCount < 1 || !JSValueIsString(context, arguments[0]))
return JSValueMakeUndefined(context);
QtBuiltinBundlePage* bundlePage = reinterpret_cast<QtBuiltinBundlePage*>(JSObjectGetPrivate(thisObject));
ASSERT(bundlePage);
if (!bundlePage->navigatorQtObjectEnabled())
return JSValueMakeUndefined(context);
JSRetainPtr<JSStringRef> jsContents = JSValueToStringCopy(context, arguments[0], 0);
WKRetainPtr<WKStringRef> contents(AdoptWK, WKStringCreateWithJSString(jsContents.get()));
bundlePage->postMessageFromNavigatorQtObject(contents.get());
return JSValueMakeUndefined(context);
}
void QtBuiltinBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
{
if (!WKBundleFrameIsMainFrame(frame) || WKBundleScriptWorldNormalWorld() != world)
return;
JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
registerNavigatorQtObject(context);
}
void QtBuiltinBundlePage::postMessageFromNavigatorQtObject(WKStringRef contents)
{
static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageFromNavigatorQtObject");
WKTypeRef body[] = { page(), contents };
WKRetainPtr<WKArrayRef> messageBody(AdoptWK, WKArrayCreate(body, sizeof(body) / sizeof(WKTypeRef)));
WKBundlePostMessage(m_bundle->toRef(), messageName, messageBody.get());
}
static JSObjectRef createWrappedMessage(JSGlobalContextRef context, WKStringRef data)
{
static JSStringRef dataName = JSStringCreateWithUTF8CString("data");
JSRetainPtr<JSStringRef> jsData = WKStringCopyJSString(data);
JSObjectRef wrappedMessage = JSObjectMake(context, 0, 0);
JSObjectSetProperty(context, wrappedMessage, dataName, JSValueMakeString(context, jsData.get()), kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
return wrappedMessage;
}
void QtBuiltinBundlePage::didReceiveMessageToNavigatorQtObject(WKStringRef contents)
{
static JSStringRef onmessageName = JSStringCreateWithUTF8CString("onmessage");
if (!m_navigatorQtObject)
return;
WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
JSValueRef onmessageValue = JSObjectGetProperty(context, m_navigatorQtObject, onmessageName, 0);
if (!JSValueIsObject(context, onmessageValue))
return;
JSObjectRef onmessageFunction = JSValueToObject(context, onmessageValue, 0);
if (!JSObjectIsFunction(context, onmessageFunction))
return;
JSObjectRef wrappedMessage = createWrappedMessage(context, contents);
JSObjectCallAsFunction(context, onmessageFunction, 0, 1, &wrappedMessage, 0);
}
void QtBuiltinBundlePage::setNavigatorQtObjectEnabled(bool enabled)
{
if (enabled == m_navigatorQtObjectEnabled)
return;
m_navigatorQtObjectEnabled = enabled;
}
void QtBuiltinBundlePage::registerNavigatorQtObject(JSGlobalContextRef context)
{
static JSStringRef postMessageName = JSStringCreateWithUTF8CString("postMessage");
static JSStringRef navigatorName = JSStringCreateWithUTF8CString("navigator");
static JSStringRef qtName = JSStringCreateWithUTF8CString("qt");
if (m_navigatorQtObject)
JSValueUnprotect(context, m_navigatorQtObject);
m_navigatorQtObject = JSObjectMake(context, navigatorQtObjectClass(), this);
JSValueProtect(context, m_navigatorQtObject);
JSObjectRef postMessage = JSObjectMakeFunctionWithCallback(context, postMessageName, qt_postMessageCallback);
JSObjectSetProperty(context, m_navigatorQtObject, postMessageName, postMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
JSValueRef navigatorValue = JSObjectGetProperty(context, JSContextGetGlobalObject(context), navigatorName, 0);
if (!JSValueIsObject(context, navigatorValue))
return;
JSObjectRef navigatorObject = JSValueToObject(context, navigatorValue, 0);
JSObjectSetProperty(context, navigatorObject, qtName, m_navigatorQtObject, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
}
JSClassRef QtBuiltinBundlePage::navigatorQtObjectClass()
{
static JSClassRef classRef = 0;
if (!classRef) {
const JSClassDefinition navigatorQtObjectClass = kJSClassDefinitionEmpty;
classRef = JSClassCreate(&navigatorQtObjectClass);
}
return classRef;
}
}