⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jni_jsobject.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2003, 2008 Apple Inc. 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 COMPUTER, INC. ``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 COMPUTER, INC. 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 "jni_jsobject.h"#if ENABLE(MAC_JAVA_BRIDGE)#include "Frame.h"#include "WebCoreFrameView.h"#include "jni_runtime.h"#include "jni_utility.h"#include "ScriptController.h"#include "runtime_object.h"#include "runtime_root.h"#include <interpreter/CallFrame.h>#include <runtime/JSGlobalObject.h>#include <runtime/JSLock.h>#include <runtime/Completion.h>#include <runtime/Completion.h>#include <wtf/Assertions.h>#include <parser/SourceProvider.h>using WebCore::Frame;using namespace JSC::Bindings;using namespace JSC;#ifdef NDEBUG#define JS_LOG(formatAndArgs...) ((void)0)#else#define JS_LOG(formatAndArgs...) { \    fprintf (stderr, "%s(%p,%p):  ", __PRETTY_FUNCTION__, _performJavaScriptRunLoop, CFRunLoopGetCurrent()); \    fprintf(stderr, formatAndArgs); \}#endif#define UndefinedHandle 1static CFRunLoopSourceRef _performJavaScriptSource;static CFRunLoopRef _performJavaScriptRunLoop;// May only be set by dispatchToJavaScriptThread().static CFRunLoopSourceRef completionSource;static void completedJavaScriptAccess (void *i){    assert (CFRunLoopGetCurrent() != _performJavaScriptRunLoop);        JSObjectCallContext *callContext = (JSObjectCallContext *)i;    CFRunLoopRef runLoop = (CFRunLoopRef)callContext->originatingLoop;        assert (CFRunLoopGetCurrent() == runLoop);        CFRunLoopStop(runLoop);}static pthread_once_t javaScriptAccessLockOnce = PTHREAD_ONCE_INIT;static pthread_mutex_t javaScriptAccessLock;static int javaScriptAccessLockCount = 0;static void initializeJavaScriptAccessLock(){    pthread_mutexattr_t attr;        pthread_mutexattr_init(&attr);    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);        pthread_mutex_init(&javaScriptAccessLock, &attr);}static inline void lockJavaScriptAccess(){    // Perhaps add deadlock detection?    pthread_once(&javaScriptAccessLockOnce, initializeJavaScriptAccessLock);    pthread_mutex_lock(&javaScriptAccessLock);    javaScriptAccessLockCount++;}static inline void unlockJavaScriptAccess(){    javaScriptAccessLockCount--;    pthread_mutex_unlock(&javaScriptAccessLock);}static void dispatchToJavaScriptThread(JSObjectCallContext *context){    // This lock guarantees that only one thread can invoke    // at a time, and also guarantees that completionSource;    // won't get clobbered.    lockJavaScriptAccess();        CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();        assert (currentRunLoop != _performJavaScriptRunLoop);        // Setup a source to signal once the invocation of the JavaScript    // call completes.    //    // FIXME:  This could be a potential performance issue.  Creating and    // adding run loop sources is expensive.  We could create one source     // per thread, as needed, instead.    context->originatingLoop = currentRunLoop;    CFRunLoopSourceContext sourceContext = {0, context, NULL, NULL, NULL, NULL, NULL, NULL, NULL, completedJavaScriptAccess};    completionSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);    CFRunLoopAddSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);        // Wakeup JavaScript access thread and make it do it's work.    CFRunLoopSourceSignal(_performJavaScriptSource);    if (CFRunLoopIsWaiting(_performJavaScriptRunLoop))        CFRunLoopWakeUp(_performJavaScriptRunLoop);        // Wait until the JavaScript access thread is done.    CFRunLoopRun ();        CFRunLoopRemoveSource(currentRunLoop, completionSource, kCFRunLoopDefaultMode);    CFRelease (completionSource);        unlockJavaScriptAccess();}static void performJavaScriptAccess(void*){    assert (CFRunLoopGetCurrent() == _performJavaScriptRunLoop);        // Dispatch JavaScript calls here.    CFRunLoopSourceContext sourceContext;    CFRunLoopSourceGetContext (completionSource, &sourceContext);    JSObjectCallContext *callContext = (JSObjectCallContext *)sourceContext.info;        CFRunLoopRef originatingLoop = callContext->originatingLoop;        JavaJSObject::invoke (callContext);        // Signal the originating thread that we're done.    CFRunLoopSourceSignal (completionSource);    if (CFRunLoopIsWaiting(originatingLoop))        CFRunLoopWakeUp(originatingLoop);}// Must be called from the thread that will be used to access JavaScript.void JavaJSObject::initializeJNIThreading() {    // Should only be called once.    ASSERT(!_performJavaScriptRunLoop);        // Assume that we can retain this run loop forever.  It'll most     // likely (always?) be the main loop.    _performJavaScriptRunLoop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());        // Setup a source the other threads can use to signal the _runLoop    // thread that a JavaScript call needs to be invoked.    CFRunLoopSourceContext sourceContext = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, performJavaScriptAccess};    _performJavaScriptSource = CFRunLoopSourceCreate(NULL, 0, &sourceContext);    CFRunLoopAddSource(_performJavaScriptRunLoop, _performJavaScriptSource, kCFRunLoopDefaultMode);}static bool isJavaScriptThread(){    return (_performJavaScriptRunLoop == CFRunLoopGetCurrent());}jvalue JavaJSObject::invoke(JSObjectCallContext *context){    jvalue result;    bzero ((void *)&result, sizeof(jvalue));        if (!isJavaScriptThread()) {                // Send the call context to the thread that is allowed to        // call JavaScript.        dispatchToJavaScriptThread(context);        result = context->result;    }    else {        jlong nativeHandle = context->nativeHandle;        if (nativeHandle == UndefinedHandle || nativeHandle == 0) {            return result;        }        if (context->type == CreateNative) {            result.j = JavaJSObject::createNative(nativeHandle);        }        else {            JSObject *imp = jlong_to_impptr(nativeHandle);            if (!findProtectingRootObject(imp)) {                fprintf (stderr, "%s:%d:  Attempt to access JavaScript from destroyed applet, type %d.\n", __FILE__, __LINE__, context->type);                return result;            }            switch (context->type){                            case Call: {                    result.l = JavaJSObject(nativeHandle).call(context->string, context->args);                    break;                }                                case Eval: {                    result.l = JavaJSObject(nativeHandle).eval(context->string);                    break;                }                            case GetMember: {                    result.l = JavaJSObject(nativeHandle).getMember(context->string);                    break;                }                                case SetMember: {                    JavaJSObject(nativeHandle).setMember(context->string, context->value);                    break;                }                                case RemoveMember: {                    JavaJSObject(nativeHandle).removeMember(context->string);                    break;                }                            case GetSlot: {                    result.l = JavaJSObject(nativeHandle).getSlot(context->index);                    break;                }                                case SetSlot: {                    JavaJSObject(nativeHandle).setSlot(context->index, context->value);                    break;                }                            case ToString: {                    result.l = (jobject) JavaJSObject(nativeHandle).toString();                    break;                }                    case Finalize: {                    JavaJSObject(nativeHandle).finalize();                    break;                }                                default: {                    fprintf (stderr, "%s:  invalid JavaScript call\n", __PRETTY_FUNCTION__);                }            }        }        context->result = result;    }    return result;}JavaJSObject::JavaJSObject(jlong nativeJSObject){    _imp = jlong_to_impptr(nativeJSObject);        ASSERT(_imp);    _rootObject = findProtectingRootObject(_imp);    ASSERT(_rootObject);}RootObject* JavaJSObject::rootObject() const{     return _rootObject && _rootObject->isValid() ? _rootObject.get() : 0; }jobject JavaJSObject::call(jstring methodName, jobjectArray args) const{    JS_LOG ("methodName = %s\n", JavaString(methodName).UTF8String());    RootObject* rootObject = this->rootObject();    if (!rootObject)        return 0;        // Lookup the function object.    ExecState* exec = rootObject->globalObject()->globalExec();    JSLock lock(false);        Identifier identifier(exec, JavaString(methodName));    JSValuePtr function = _imp->get(exec, identifier);    CallData callData;    CallType callType = function.getCallData(callData);    if (callType == CallTypeNone)        return 0;    // Call the function object.    ArgList argList;    getListFromJArray(exec, args, argList);    rootObject->globalObject()->globalData()->timeoutChecker.start();    JSValuePtr result = JSC::call(exec, function, callType, callData, _imp, argList);    rootObject->globalObject()->globalData()->timeoutChecker.stop();    return convertValueToJObject(result);}jobject JavaJSObject::eval(jstring script) const{    JS_LOG ("script = %s\n", JavaString(script).UTF8String());        JSValuePtr result;    JSLock lock(false);        RootObject* rootObject = this->rootObject();    if (!rootObject)        return 0;    rootObject->globalObject()->globalData()->timeoutChecker.start();    Completion completion = JSC::evaluate(rootObject->globalObject()->globalExec(), rootObject->globalObject()->globalScopeChain(), makeSource(JavaString(script)));    rootObject->globalObject()->globalData()->timeoutChecker.stop();    ComplType type = completion.complType();        if (type == Normal) {        result = completion.value();        if (!result)            result = jsUndefined();    } else        result = jsUndefined();        return convertValueToJObject (result);}jobject JavaJSObject::getMember(jstring memberName) const{    JS_LOG ("(%p) memberName = %s\n", _imp, JavaString(memberName).UTF8String());    RootObject* rootObject = this->rootObject();    if (!rootObject)        return 0;    ExecState* exec = rootObject->globalObject()->globalExec();        JSLock lock(false);    JSValuePtr result = _imp->get(exec, Identifier(exec, JavaString(memberName)));    return convertValueToJObject(result);}void JavaJSObject::setMember(jstring memberName, jobject value) const{    JS_LOG ("memberName = %s, value = %p\n", JavaString(memberName).UTF8String(), value);    RootObject* rootObject = this->rootObject();    if (!rootObject)        return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -