NS_IMETHODIMP nsJSSh::ExecuteBuffer() { #ifdef DEBUG // nsCOMPtr<nsIThread> thread; // nsIThread::GetCurrent(getter_AddRefs(thread)); // printf("executing on thread %p\n", thread.get()); #endif JS_BeginRequest(mJSContext); JS_ClearPendingException(mJSContext); JSPrincipals *jsprincipals; mPrincipal->GetJSPrincipals(mJSContext, &jsprincipals); if(NS_FAILED(mContextStack->Push(mJSContext))) { NS_ERROR("failed to push the current JSContext on the nsThreadJSContextStack"); return NS_ERROR_FAILURE; } JSScript *script = JS_CompileScriptForPrincipals(mJSContext, mContextObj, jsprincipals, mBuffer, mBufferPtr, "interactive", 0); if (script) { jsval result; if (JS_ExecuteScript(mJSContext, mContextObj, script, &result) && result!=JSVAL_VOID && mOutput) { // XXX for some wrapped native objects the following code will crash; probably because the // native object is getting released before we reach this: JSString *str = JS_ValueToString(mJSContext, result); if (str) { nsDependentString chars(reinterpret_cast<const PRUnichar*> (JS_GetStringChars(str)), JS_GetStringLength(str)); NS_ConvertUTF16toUTF8 cstr(chars); PRUint32 bytesWritten; mOutput->Write(cstr.get(), cstr.Length(), &bytesWritten); } } JS_DestroyScript(mJSContext, script); } JSContext *oldcx; mContextStack->Pop(&oldcx); NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch"); JSPRINCIPALS_DROP(mJSContext, jsprincipals); JS_EndRequest(mJSContext); return NS_OK; }
AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, JSContext *cx) : mContext(cx), mPushResult(NS_OK) { mContextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if(mContextStack) { JSContext* currentCX; if(NS_SUCCEEDED(mContextStack->Peek(¤tCX))) { // Is the current context already on the stack? if(cx == currentCX) mContextStack = nsnull; else { mContextStack->Push(cx); // Leave the reference to the mContextStack to // indicate that we need to pop it in our dtor. } } } 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; } } }
int main(int argc, char **argv, char **envp) { #ifdef XP_MACOSX InitAutoreleasePool(); #endif JSRuntime *rt; JSContext *cx; JSObject *glob, *envobj; int result; nsresult rv; // unbuffer stdout so that output is in the correct order; note that stderr // is unbuffered by default setbuf(stdout, 0); gErrFile = stderr; gOutFile = stdout; { nsCOMPtr<nsIServiceManager> servMan; rv = NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull); if (NS_FAILED(rv)) { printf("NS_InitXPCOM failed!\n"); return 1; } { nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); if (registrar) registrar->AutoRegister(nsnull); } nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); // get the JSRuntime from the runtime svc if (!rtsvc) { printf("failed to get nsJSRuntimeService!\n"); return 1; } if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) { printf("failed to get JSRuntime from nsJSRuntimeService!\n"); return 1; } JS_SetContextCallback(rt, ContextCallback); cx = JS_NewContext(rt, 8192); if (!cx) { printf("JS_NewContext failed!\n"); return 1; } nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { printf("failed to get nsXPConnect service!\n"); return 1; } // Since the caps security system might set a default security manager // we will be sure that the secman on this context gives full trust. nsRefPtr<FullTrustSecMan> secman = new FullTrustSecMan(); xpc->SetSecurityManagerForJSContext(cx, secman, 0xFFFF); #ifndef XPCONNECT_STANDALONE // Fetch the system principal and store it away in a global, to use for // script compilation in Load() and ProcessFile() (including interactive // eval loop) { nsCOMPtr<nsIPrincipal> princ; nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && securityManager) { rv = securityManager->GetSystemPrincipal(getter_AddRefs(princ)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global rv = princ->GetJSPrincipals(cx, &gJSPrincipals); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to obtain JS principals from SystemPrincipal.\n"); } secman->SetSystemPrincipal(princ); } } else { fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals"); } } #endif #ifdef TEST_TranslateThis nsCOMPtr<nsIXPCFunctionThisTranslator> translator(new nsXPCFunctionThisTranslator); xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator, nsnull); #endif nsCOMPtr<nsIJSContextStack> cxstack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); if (!cxstack) { printf("failed to get the nsThreadJSContextStack service!\n"); return 1; } if(NS_FAILED(cxstack->Push(cx))) { printf("failed to push the current JSContext on the nsThreadJSContextStack!\n"); return 1; } nsCOMPtr<nsIXPCScriptable> backstagePass; nsresult rv = rtsvc->GetBackstagePass(getter_AddRefs(backstagePass)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to get backstage pass from rtsvc: %8x\n", rv); return 1; } nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, NS_GET_IID(nsISupports), nsIXPConnect:: FLAG_SYSTEM_GLOBAL_OBJECT, getter_AddRefs(holder)); if (NS_FAILED(rv)) return 1; rv = holder->GetJSObject(&glob); if (NS_FAILED(rv)) { NS_ASSERTION(glob == nsnull, "bad GetJSObject?"); return 1; } JS_BeginRequest(cx); if (!JS_DefineFunctions(cx, glob, glob_functions)) { JS_EndRequest(cx); return 1; } envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0); if (!envobj || !JS_SetPrivate(cx, envobj, envp)) { JS_EndRequest(cx); return 1; } argc--; argv++; result = ProcessArgs(cx, glob, argv, argc); //#define TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN 1 #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN // test of late call and release (see below) nsCOMPtr<nsIJSContextStack> bogus; xpc->WrapJS(cx, glob, NS_GET_IID(nsIJSContextStack), (void**) getter_AddRefs(bogus)); #endif JSPRINCIPALS_DROP(cx, gJSPrincipals); JS_ClearScope(cx, glob); JS_GC(cx); JSContext *oldcx; cxstack->Pop(&oldcx); NS_ASSERTION(oldcx == cx, "JS thread context push/pop mismatch"); cxstack = nsnull; JS_GC(cx); JS_DestroyContext(cx); xpc->SyncJSContexts(); } // this scopes the nsCOMPtrs // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM rv = NS_ShutdownXPCOM( NULL ); NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); #ifdef TEST_CALL_ON_WRAPPED_JS_AFTER_SHUTDOWN // test of late call and release (see above) JSContext* bogusCX; bogus->Peek(&bogusCX); bogus = nsnull; #endif #ifdef XP_MACOSX FinishAutoreleasePool(); #endif return result; }
PRBool nsJSSh::LoadURL(const char *url, jsval* retval) { nsCOMPtr<nsIIOService> ioserv = do_GetService(NS_IOSERVICE_CONTRACTID); if (!ioserv) { NS_ERROR("could not get io service"); return PR_FALSE; } nsCOMPtr<nsIChannel> channel; ioserv->NewChannel(nsDependentCString(url), nsnull, nsnull, getter_AddRefs(channel)); if (!channel) { NS_ERROR("could not create channel"); return PR_FALSE; } nsCOMPtr<nsIInputStream> instream; channel->Open(getter_AddRefs(instream)); if (!instream) { NS_ERROR("could not open stream"); return PR_FALSE; } nsCString buffer; nsAutoArrayPtr<char> buf(new char[1024]); if (!buf) { NS_ERROR("could not alloc buffer"); return PR_FALSE; } PRUint32 bytesRead = 0; do { if (NS_FAILED(instream->Read(buf, 1024, &bytesRead))) { NS_ERROR("stream read error"); return PR_FALSE; } buffer.Append(buf, bytesRead); LOG(("appended %d bytes:\n%s", bytesRead, buffer.get())); } while (bytesRead > 0); LOG(("loaded %d bytes:\n%s", buffer.Length(), buffer.get())); JS_BeginRequest(mJSContext); JSPrincipals *jsprincipals; mPrincipal->GetJSPrincipals(mJSContext, &jsprincipals); if(NS_FAILED(mContextStack->Push(mJSContext))) { NS_ERROR("failed to push the current JSContext on the nsThreadJSContextStack"); return NS_ERROR_FAILURE; } jsval result; JSBool ok = JS_EvaluateScriptForPrincipals(mJSContext, mContextObj, jsprincipals, buffer.get(), buffer.Length(), url, 1, &result); JSPRINCIPALS_DROP(mJSContext, jsprincipals); JSContext *oldcx; mContextStack->Pop(&oldcx); NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch"); if (ok && retval) *retval=result; JS_EndRequest(mJSContext); return ok; }
~JSPrincipalsHolder() { JSPRINCIPALS_DROP(mCx, mPrincipals); }
PRBool CreateFakeBrowserWindow(JSContext* cx, JSObject* parent, nsIPrincipal* systemPrincipal) { nsresult rv; jsval value; nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (xpc == nsnull) { JS_ReportError(cx, "Adblock Plus: Coult not retrieve nsIXPConnect - wrong Gecko version?"); return PR_FALSE; } rv = xpc->FlagSystemFilenamePrefix("adblockplus.dll/"); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Failed to enable protection for inline JavaScript"); return PR_FALSE; } JSObject* obj = JS_NewObject(cx, nsnull, nsnull, parent); if (obj == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to create fake browser window object - out of memory?"); return PR_FALSE; } JS_SetGlobalObject(cx, obj); // Have to loop through the methods manually because JS_DefineFunctions won't do anything for some reason for (JSFunctionSpec *fs = window_methods; fs->name; fs++) { JSFunction *fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, fs->flags); if (!fun) { JS_ReportError(cx, "Adblock Plus: Failed to attach native methods to fake browser window"); return PR_FALSE; } } if (!JS_DefineProperties(cx, obj, window_properties)) { JS_ReportError(cx, "Adblock Plus: Failed to attach native properties to fake browser window"); return PR_FALSE; } JSPrincipals* principals; rv = systemPrincipal->GetJSPrincipals(cx, &principals); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Could not convert system principal into JavaScript principals"); return PR_FALSE; } for (int i = 0; includes[i]; i += 2) { JSScript* inlineScript = JS_CompileScriptForPrincipals(cx, obj, principals, includes[i+1], strlen(includes[i+1]), includes[i], 1); if (inlineScript == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to compile %s", includes[i]); return PR_FALSE; } if (!JS_ExecuteScript(cx, obj, inlineScript, &value)) { JS_ReportError(cx, "Adblock Plus: Failed to execute %s", includes[i]); return PR_FALSE; } JS_DestroyScript(cx, inlineScript); } JSPRINCIPALS_DROP(cx, principals); nsCOMPtr<nsISupports> wrapped; rv = xpc->WrapJS(cx, obj, NS_GET_IID(nsISupports), getter_AddRefs(wrapped)); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Failed to create XPConnect wrapper for fake browser window"); return PR_FALSE; } fakeBrowserWindow = do_QueryInterface(wrapped); if (fakeBrowserWindow == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to QI fake browser window"); return PR_FALSE; } jsval readerVal; JS_GetProperty(cx, obj, "_dtdReader", &readerVal); if (readerVal == JSVAL_VOID) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve DTD reader object"); return PR_FALSE; } JSObject* reader = JSVAL_TO_OBJECT(readerVal); for (int i = 0; i < NUM_LABELS; i++) { JSString* str = JS_NewStringCopyZ(cx, context_labels[i]); if (str == nsnull) { JS_ReportError(cx, "Adblock Plus: Could not create JavaScript string for '%s' - out of memory?", context_labels[i]); return PR_FALSE; } jsval args[] = {STRING_TO_JSVAL(str)}; jsval retval; if (!JS_CallFunctionName(cx, reader, "getEntity", 1, args, &retval)) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve entity '%s' from overlay.dtd", context_labels[i]); return PR_FALSE; } str = JS_ValueToString(cx, retval); if (str == nsnull) { JS_ReportError(cx, "Adblock Plus: Could not convert return value of _dtdReader.getEntity() to string"); return PR_FALSE; } strcpy_s(labelValues[i], sizeof(labelValues[i]), JS_GetStringBytes(str)); } return PR_TRUE; }
NS_METHOD nsCLiveconnect::Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, 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; jsval js_val; int dummy_cost = 0; JSBool dummy_bool = PR_FALSE; JSErrorReporter saved_state = NULL; jobject result = NULL; const char *codebase = NULL; JSPrincipals *principals = NULL; JSBool eval_succeeded = PR_FALSE; jsj_env = jsj_enter_js(jEnv, mJavaClient, NULL, &cx, NULL, &saved_state, principalsArray, numPrincipals, securitySupports); if (!jsj_env) return NS_ERROR_FAILURE; result = NULL; AutoPushJSContext autopush(securitySupports, cx); if (NS_FAILED(autopush.ResultOfPush())) goto done; if (!script) { JS_ReportError(cx, "illegal null string eval argument"); goto done; } /* Set up security stuff */ if (JSJ_callbacks && JSJ_callbacks->get_JSPrincipals_from_java_caller) principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv, cx, principalsArray, numPrincipals, securitySupports); codebase = principals ? principals->codebase : NULL; /* Have the JS engine evaluate the unicode string */ eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, script, length, codebase, 0, &js_val); if (!eval_succeeded) goto done; /* Convert result to a subclass of java.lang.Object */ jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, jsj_get_jlObject_descriptor(cx, jEnv), &dummy_cost, &result, &dummy_bool); done: if (principals) JSPRINCIPALS_DROP(cx, principals); if (!jsj_exit_js(cx, jsj_env, saved_state)) return NS_ERROR_FAILURE; *pjobj = result; return NS_OK; }
AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports, JSContext *cx) : mContext(cx), mPushResult(NS_OK) { nsCOMPtr<nsIJSContextStack> contextStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1"); JS_BeginRequest(cx); 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); JSFunction *fun = JS_CompileFunctionForPrincipals(cx, JS_GetGlobalObject(cx), jsprinc, "anonymous", 0, nsnull, "", 0, "", 1); JSPRINCIPALS_DROP(cx, jsprinc); if (fun) { JSScript *script = JS_GetFunctionScript(cx, fun); mFrame.fun = fun; mFrame.script = script; mFrame.callee = JS_GetFunctionObject(fun); mFrame.scopeChain = JS_GetParent(cx, mFrame.callee); mFrame.down = cx->fp; mRegs.pc = script->code + script->length - 1; JS_ASSERT(static_cast<JSOp>(*mRegs.pc) == JSOP_STOP); mRegs.sp = NULL; mFrame.regs = &mRegs; cx->fp = &mFrame; } else mPushResult = NS_ERROR_OUT_OF_MEMORY; } } }
js_CloseTokenStream(JSContext *cx, JSTokenStream *ts) { if (ts->principals) JSPRINCIPALS_DROP(cx, ts->principals); return !ts->file || fclose(ts->file) == 0; }