📄 nscliveconnect.cpp
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * This file is part of the Java-vendor-neutral implementation of LiveConnect * * It contains the implementation providing nsIFactory XP-COM interface. * */#include <stdlib.h>#include <string.h>#include "prtypes.h"#include "prprf.h"#include "prlog.h"#include "jsj_private.h"#include "jsjava.h"#include "jscntxt.h" /* For js_ReportErrorAgain().*/#include "netscape_javascript_JSObject.h" /* javah-generated headers */#include "nsISecurityContext.h"#include "nsIServiceManager.h"#include "nsIJSContextStack.h"PR_BEGIN_EXTERN_C/* A captured JavaScript error, created when JS_ReportError() is called while running JavaScript code that is itself called from Java. */struct CapturedJSError { char * message; JSErrorReport report; /* Line # of error, etc. */ jthrowable java_exception; /* Java exception, error, or null */ CapturedJSError * next; /* Next oldest captured JS error */};PR_END_EXTERN_C#include "nsCLiveconnect.h"#include "jsinterp.h" // XXX private API so we can auto-push a JSStackFrame#include "nsIScriptSecurityManager.h"#include "nsIPrincipal.h"#include "nsNetUtil.h"#include "nsISecurityContext.h"#include "prmem.h"/***************************************************************************/// A class to put on the stack to manage JS contexts when we are entering JS.// This pushes and pops the given context// with the nsThreadJSContextStack service as this object goes into and out// of scope. It is optimized to not push/pop the cx if it is already on top// of the stack. We need to push the JSContext when we enter JS because the// JS security manager looks on the context stack for permissions information.class AutoPushJSContext{public: AutoPushJSContext(nsISupports* aSecuritySupports, JSContext *cx); ~AutoPushJSContext(); nsresult ResultOfPush() { return mPushResult; };private: nsCOMPtr<nsIJSContextStack> mContextStack; JSContext* mContext; JSStackFrame mFrame; nsresult mPushResult;};AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, JSContext *cx) : mContext(cx), mPushResult(NS_OK){ nsCOMPtr<nsIJSContextStack> contextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); JSContext* currentCX; if(contextStack && // Don't push if the current context is already on the stack. (NS_FAILED(contextStack->Peek(¤tCX)) || cx != currentCX) ) { if (NS_SUCCEEDED(contextStack->Push(cx))) { // Leave the reference in mContextStack to // indicate that we need to pop it in our dtor. mContextStack.swap(contextStack); } } nsCOMPtr<nsIScriptSecurityManager> secMan( do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &mPushResult)); if (NS_FAILED(mPushResult)) return; nsCOMPtr<nsIPrincipal> principal; mPushResult = secMan->GetPrincipalFromContext(cx, getter_AddRefs(principal)); if (NS_FAILED(mPushResult)) { JS_ReportError(cx, "failed to get a principal"); return; } // See if JavaScript is enabled for the current window PRBool jsEnabled = PR_FALSE; mPushResult = secMan->CanExecuteScripts(cx, principal, &jsEnabled); if (!jsEnabled) mPushResult = NS_ERROR_FAILURE; memset(&mFrame, 0, sizeof(mFrame)); if (NS_SUCCEEDED(mPushResult)) { // See if there are any scripts on the stack. // If not, we need to add a dummy frame with a principal. PRBool hasScript = PR_FALSE; JSStackFrame* tempFP = cx->fp; while (tempFP) { if (tempFP->script) { hasScript = PR_TRUE; break; } tempFP = tempFP->down; }; if (!hasScript) { JSPrincipals* jsprinc; principal->GetJSPrincipals(cx, &jsprinc); mFrame.script = JS_CompileScriptForPrincipals(cx, JS_GetGlobalObject(cx), jsprinc, "", 0, "", 1); JSPRINCIPALS_DROP(cx, jsprinc); if (mFrame.script) { mFrame.down = cx->fp; cx->fp = &mFrame; } else mPushResult = NS_ERROR_OUT_OF_MEMORY; } }}AutoPushJSContext::~AutoPushJSContext(){ if (mContextStack) mContextStack->Pop(nsnull); if (mFrame.script) mContext->fp = mFrame.down;}////////////////////////////////////////////////////////////////////////////// from nsISupports and AggregatedQueryInterface:// Thes macro expands to the aggregated query interface scheme.NS_IMPL_AGGREGATED(nsCLiveconnect)NS_METHODnsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr){ NS_ENSURE_ARG_POINTER(aInstancePtr); if (aIID.Equals(NS_GET_IID(nsISupports))) { *aInstancePtr = GetInner(); } else if (aIID.Equals(NS_GET_IID(nsILiveconnect))) { *aInstancePtr = NS_STATIC_CAST(nsILiveconnect*, this); } else { *aInstancePtr = nsnull; return NS_NOINTERFACE; } NS_ADDREF((nsISupports*) *aInstancePtr); return NS_OK;}////////////////////////////////////////////////////////////////////////////// from nsILiveconnect:/** * get member of a Native JSObject for a given name. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a member. * @param pjobj - return parameter as a java object representing * the member. If it is a basic data type it is converted to * a corresponding java type. If it is a NJSObject, then it is * wrapped up as java wrapper netscape.javascript.JSObject. */NS_METHOD nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj){ if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jobject member = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null member name"); member = NULL; goto done; } if (!JS_GetUCProperty(cx, js_obj, name, length, &js_val)) goto done; jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool);done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = member; return NS_OK;}/** * get member of a Native JSObject for a given index. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param index - Index of a member. * @param pjobj - return parameter as a java object representing * the member. */NS_METHOD nsCLiveconnect::GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[], int numPrincipals, nsISupports *securitySupports, jobject *pjobj){ if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jobject member = NULL; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; // =-= sudu: check to see if slot can be passed in as is. // Should it be converted to a jsint? if (!JS_GetElement(cx, js_obj, slot, &js_val)) goto done; if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &member, &dummy_bool)) goto done;done: if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = member; return NS_OK;}/** * set member of a Native JSObject for a given name. * * @param jEnv - JNIEnv on which the call is being made. * @param obj - A Native JS Object. * @param name - Name of a member. * @param jobj - Value to set. If this is a basic data type, it is converted * using standard JNI calls but if it is a wrapper to a JSObject * then a internal mapping is consulted to convert to a NJSObject. */NS_METHOD nsCLiveconnect::SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[], int numPrincipals, nsISupports *securitySupports){ if(jEnv == NULL || obj == 0) { return NS_ERROR_FAILURE; } JSJavaThreadState *jsj_env = NULL; JSObjectHandle *handle = (JSObjectHandle*)obj; JSObject *js_obj = handle->js_obj; JSContext *cx = NULL; jsval js_val; JSErrorReporter saved_state = NULL; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!name) { JS_ReportError(cx, "illegal null member name"); goto done; } if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) goto done; JS_SetUCProperty(cx, js_obj, name, length, &js_val);done: jsj_exit_js(cx, jsj_env, saved_state); return NS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -