JSContext* XPCJSContextStack::GetSafeJSContext() { if (mSafeJSContext) return mSafeJSContext; // Start by getting the principal holder and principal for this // context. If we can't manage that, don't bother with the rest. nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal(); nsresult rv = principal->Init(); if (NS_FAILED(rv)) MOZ_CRASH(); nsXPConnect* xpc = nsXPConnect::XPConnect(); JSRuntime *rt = xpc->GetRuntime()->Runtime(); if (!rt) MOZ_CRASH(); mSafeJSContext = JS_NewContext(rt, 8192); if (!mSafeJSContext) MOZ_CRASH(); JSAutoRequest req(mSafeJSContext); JS::RootedObject glob(mSafeJSContext); JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter); JS::CompartmentOptions options; options.setZone(JS::SystemZone); glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options); if (!glob) MOZ_CRASH(); // Make sure the context is associated with a proper compartment // and not the default compartment. js::SetDefaultObjectForContext(mSafeJSContext, glob); // Note: make sure to set the private before calling // InitClasses nsCOMPtr<nsIScriptObjectPrincipal> sop = new SandboxPrivate(principal, glob); JS_SetPrivate(glob, sop.forget().get()); // After this point either glob is null and the // nsIScriptObjectPrincipal ownership is either handled by the // nsCOMPtr or dealt with, or we'll release in the finalize // hook. if (NS_FAILED(xpc->InitClasses(mSafeJSContext, glob))) MOZ_CRASH(); JS_FireOnNewGlobalObject(mSafeJSContext, glob); // Save it off so we can destroy it later. mOwnSafeJSContext = mSafeJSContext; return mSafeJSContext; }
JSContext* XPCJSContextStack::InitSafeJSContext() { MOZ_ASSERT(!mSafeJSContext); // Start by getting the principal holder and principal for this // context. If we can't manage that, don't bother with the rest. nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal(); nsresult rv = principal->Init(); if (NS_FAILED(rv)) MOZ_CRASH(); nsXPConnect* xpc = nsXPConnect::XPConnect(); JSRuntime *rt = xpc->GetRuntime()->Runtime(); if (!rt) MOZ_CRASH(); mSafeJSContext = JS_NewContext(rt, 8192); if (!mSafeJSContext) MOZ_CRASH(); JSAutoRequest req(mSafeJSContext); ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true); JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter); JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setTrace(TraceXPCGlobal); mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options); if (!mSafeJSContextGlobal) MOZ_CRASH(); JS_AddNamedObjectRoot(mSafeJSContext, &mSafeJSContextGlobal, "SafeJSContext global"); // Note: make sure to set the private before calling // InitClasses nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, mSafeJSContextGlobal); JS_SetPrivate(mSafeJSContextGlobal, sp.forget().take()); // After this point either glob is null and the // nsIScriptObjectPrincipal ownership is either handled by the // nsCOMPtr or dealt with, or we'll release in the finalize // hook. if (NS_FAILED(xpc->InitClasses(mSafeJSContext, mSafeJSContextGlobal))) MOZ_CRASH(); JS::RootedObject glob(mSafeJSContext, mSafeJSContextGlobal); JS_FireOnNewGlobalObject(mSafeJSContext, glob); return mSafeJSContext; }
JSContext* XPCJSContextStack::InitSafeJSContext() { MOZ_ASSERT(!mSafeJSContext); // Start by getting the principal holder and principal for this // context. If we can't manage that, don't bother with the rest. nsRefPtr<nsNullPrincipal> principal = new nsNullPrincipal(); nsresult rv = principal->Init(); if (NS_FAILED(rv)) MOZ_CRASH(); nsXPConnect* xpc = nsXPConnect::XPConnect(); JSRuntime *rt = xpc->GetRuntime()->Runtime(); if (!rt) MOZ_CRASH(); mSafeJSContext = JS_NewContext(rt, 8192); if (!mSafeJSContext) MOZ_CRASH(); JSAutoRequest req(mSafeJSContext); ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true); JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter); // Note - We intentionally avoid firing OnNewGlobalObject while // simultaneously skipping the call to setInvisibleToDebugger(true) here. // This lets us piggy-back on the assertions in the JS engine (which make // sure that, for non-invisible globals, we always fire onNewGlobalObject // before creating scripts), to assert that we never create scripts with // the SafeJSContextGlobal. This is all happening way before anyone could be // listening for debugger notifications anyway. JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setTrace(TraceXPCGlobal); mSafeJSContextGlobal = CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options); if (!mSafeJSContextGlobal) MOZ_CRASH(); nsRefPtr<SandboxPrivate> sp = new SandboxPrivate(principal, mSafeJSContextGlobal); JS_SetPrivate(mSafeJSContextGlobal, sp.forget().take()); return mSafeJSContext; }
GlobalObject * JSRuntime::createSelfHostingGlobal(JSContext *cx) { MOZ_ASSERT(!cx->isExceptionPending()); MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); JS::CompartmentOptions options; options.setDiscardSource(true); options.setZone(JS::FreshZone); JSCompartment *compartment = NewCompartment(cx, nullptr, nullptr, options); if (!compartment) return nullptr; static const Class shgClass = { "self-hosting-global", JSCLASS_GLOBAL_FLAGS, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, JS_GlobalObjectTraceHook }; AutoCompartment ac(cx, compartment); Rooted<GlobalObject*> shg(cx, GlobalObject::createInternal(cx, &shgClass)); if (!shg) return nullptr; cx->runtime()->selfHostingGlobal_ = shg; compartment->isSelfHosting = true; compartment->isSystem = true; if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions)) return nullptr; JS_FireOnNewGlobalObject(cx, shg); return shg; }
nsresult Init() { mRuntime = JS_NewRuntime(sRuntimeHeapSize, JS_NO_HELPER_THREADS); NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY); /* * Not setting this will cause JS_CHECK_RECURSION to report false * positives */ JS_SetNativeStackQuota(mRuntime, 128 * sizeof(size_t) * 1024); mContext = JS_NewContext(mRuntime, 0); NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY); JSAutoRequest ar(mContext); JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setVersion(JSVERSION_LATEST); mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr, JS::DontFireOnNewGlobalHook, options); NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY); JS::Rooted<JSObject*> global(mContext, mGlobal); JSAutoCompartment ac(mContext, global); js::SetDefaultObjectForContext(mContext, global); JS_InitStandardClasses(mContext, global); JS_SetErrorReporter(mContext, PACErrorReporter); if (!JS_DefineFunctions(mContext, global, PACGlobalFunctions)) return NS_ERROR_FAILURE; JS_FireOnNewGlobalObject(mContext, global); return NS_OK; }
bool XPCShellEnvironment::Init() { nsresult rv; // unbuffer stdout so that output is in the correct order; note that stderr // is unbuffered by default setbuf(stdout, 0); nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); if (!rtsvc) { NS_ERROR("failed to get nsJSRuntimeService!"); return false; } JSRuntime *rt; if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) { NS_ERROR("failed to get JSRuntime from nsJSRuntimeService!"); return false; } if (!mGlobalHolder.Hold(rt)) { NS_ERROR("Can't protect global object!"); return false; } AutoSafeJSContext cx; JS_SetContextPrivate(cx, this); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { NS_ERROR("failed to get nsXPConnect service!"); return false; } nsCOMPtr<nsIPrincipal> principal; nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && securityManager) { rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal)); if (NS_FAILED(rv)) { fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } } else { fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals"); } nsRefPtr<BackstagePass> backstagePass; rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); if (NS_FAILED(rv)) { NS_ERROR("Failed to create backstage pass!"); return false; } JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setVersion(JSVERSION_LATEST); nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast<nsIGlobalObject *>(backstagePass), principal, 0, options, getter_AddRefs(holder)); if (NS_FAILED(rv)) { NS_ERROR("InitClassesWithNewWrappedGlobal failed!"); return false; } JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject()); if (!globalObj) { NS_ERROR("Failed to get global JSObject!"); return false; } JSAutoCompartment ac(cx, globalObj); backstagePass->SetGlobalObject(globalObj); if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment", PRIVATE_TO_JSVAL(this), JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY | JSPROP_PERMANENT) || !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) || !JS_DefineProfilingFunctions(cx, globalObj)) { NS_ERROR("JS_DefineFunctions failed!"); return false; } mGlobalHolder = globalObj; FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r"); if (runtimeScriptFile) { fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename); ProcessFile(cx, globalObj, kDefaultRuntimeScriptFilename, runtimeScriptFile, false); fclose(runtimeScriptFile); } return true; }
int XRE_XPCShellMain(int argc, char** argv, char** envp) { JSRuntime* rt; JSContext* cx; int result; nsresult rv; gErrFile = stderr; gOutFile = stdout; gInFile = stdin; NS_LogInit(); // A initializer to initialize histogram collection // used by telemetry. UniquePtr<base::StatisticsRecorder> telStats = MakeUnique<base::StatisticsRecorder>(); nsCOMPtr<nsIFile> appFile; rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appFile)); if (NS_FAILED(rv)) { printf("Couldn't find application file.\n"); return 1; } nsCOMPtr<nsIFile> appDir; rv = appFile->GetParent(getter_AddRefs(appDir)); if (NS_FAILED(rv)) { printf("Couldn't get application directory.\n"); return 1; } XPCShellDirProvider dirprovider; dirprovider.SetAppFile(appFile); nsCOMPtr<nsIFile> greDir; if (argc > 1 && !strcmp(argv[1], "-g")) { if (argc < 3) return usage(); rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(greDir)); if (NS_FAILED(rv)) { printf("Couldn't use given GRE dir.\n"); return 1; } dirprovider.SetGREDirs(greDir); argc -= 2; argv += 2; } else { #ifdef XP_MACOSX // On OSX, the GreD needs to point to Contents/Resources in the .app // bundle. Libraries will be loaded at a relative path to GreD, i.e. // ../MacOS. nsCOMPtr<nsIFile> tmpDir; XRE_GetFileFromPath(argv[0], getter_AddRefs(greDir)); greDir->GetParent(getter_AddRefs(tmpDir)); tmpDir->Clone(getter_AddRefs(greDir)); tmpDir->SetNativeLeafName(NS_LITERAL_CSTRING("Resources")); bool dirExists = false; tmpDir->Exists(&dirExists); if (dirExists) { greDir = tmpDir.forget(); } dirprovider.SetGREDirs(greDir); #else nsAutoString workingDir; if (!GetCurrentWorkingDirectory(workingDir)) { printf("GetCurrentWorkingDirectory failed.\n"); return 1; } rv = NS_NewLocalFile(workingDir, true, getter_AddRefs(greDir)); if (NS_FAILED(rv)) { printf("NS_NewLocalFile failed.\n"); return 1; } #endif } if (argc > 1 && !strcmp(argv[1], "-a")) { if (argc < 3) return usage(); nsCOMPtr<nsIFile> dir; rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(dir)); if (NS_SUCCEEDED(rv)) { appDir = do_QueryInterface(dir, &rv); dirprovider.SetAppDir(appDir); } if (NS_FAILED(rv)) { printf("Couldn't use given appdir.\n"); return 1; } argc -= 2; argv += 2; } while (argc > 1 && !strcmp(argv[1], "-r")) { if (argc < 3) return usage(); nsCOMPtr<nsIFile> lf; rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(lf)); if (NS_FAILED(rv)) { printf("Couldn't get manifest file.\n"); return 1; } XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf); argc -= 2; argv += 2; } #ifdef MOZ_CRASHREPORTER const char* val = getenv("MOZ_CRASHREPORTER"); if (val && *val) { rv = CrashReporter::SetExceptionHandler(greDir, true); if (NS_FAILED(rv)) { printf("CrashReporter::SetExceptionHandler failed!\n"); return 1; } MOZ_ASSERT(CrashReporter::GetEnabled()); } #endif { if (argc > 1 && !strcmp(argv[1], "--greomni")) { nsCOMPtr<nsIFile> greOmni; nsCOMPtr<nsIFile> appOmni; XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni)); if (argc > 3 && !strcmp(argv[3], "--appomni")) { XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni)); argc-=2; argv+=2; } else { appOmni = greOmni; } XRE_InitOmnijar(greOmni, appOmni); argc-=2; argv+=2; } nsCOMPtr<nsIServiceManager> servMan; rv = NS_InitXPCOM2(getter_AddRefs(servMan), appDir, &dirprovider); if (NS_FAILED(rv)) { printf("NS_InitXPCOM2 failed!\n"); return 1; } 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; } // Override the default XPConnect interrupt callback. We could store the // old one and restore it before shutting down, but there's not really a // reason to bother. sScriptedInterruptCallback.init(rt, UndefinedValue()); JS_SetInterruptCallback(rt, XPCShellInterruptCallback); JS_SetErrorReporter(rt, XPCShellErrorReporter); dom::AutoJSAPI jsapi; jsapi.Init(); cx = jsapi.cx(); argc--; argv++; ProcessArgsForCompartment(cx, argv, argc); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { printf("failed to get nsXPConnect service!\n"); return 1; } nsCOMPtr<nsIPrincipal> systemprincipal; // 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<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && securityManager) { rv = securityManager->GetSystemPrincipal(getter_AddRefs(systemprincipal)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global gJSPrincipals = nsJSPrincipals::get(systemprincipal); JS_HoldPrincipals(gJSPrincipals); } } else { fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals"); } } const JSSecurityCallbacks* scb = JS_GetSecurityCallbacks(rt); MOZ_ASSERT(scb, "We are assuming that nsScriptSecurityManager::Init() has been run"); shellSecurityCallbacks = *scb; JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks); #ifdef TEST_TranslateThis nsCOMPtr<nsIXPCFunctionThisTranslator> translator(new nsXPCFunctionThisTranslator); xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator); #endif nsRefPtr<BackstagePass> backstagePass; rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to create BackstagePass: %8x\n", static_cast<uint32_t>(rv)); return 1; } // Make the default XPCShell global use a fresh zone (rather than the // System Zone) to improve cross-zone test coverage. JS::CompartmentOptions options; options.setZone(JS::FreshZone) .setVersion(JSVERSION_LATEST); nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast<nsIGlobalObject*>(backstagePass), systemprincipal, 0, options, getter_AddRefs(holder)); if (NS_FAILED(rv)) return 1; { JS::Rooted<JSObject*> glob(cx, holder->GetJSObject()); if (!glob) { return 1; } // Even if we're building in a configuration where source is // discarded, there's no reason to do that on XPCShell, and doing so // might break various automation scripts. JS::CompartmentOptionsRef(glob).setDiscardSource(false); backstagePass->SetGlobalObject(glob); JSAutoCompartment ac(cx, glob); if (!JS_InitReflect(cx, glob)) { return 1; } if (!JS_DefineFunctions(cx, glob, glob_functions) || !JS_DefineProfilingFunctions(cx, glob)) { return 1; } JS::Rooted<JSObject*> envobj(cx); envobj = JS_DefineObject(cx, glob, "environment", &env_class); if (!envobj) { return 1; } JS_SetPrivate(envobj, envp); nsAutoString workingDirectory; if (GetCurrentWorkingDirectory(workingDirectory)) gWorkingDirectory = &workingDirectory; JS_DefineProperty(cx, glob, "__LOCATION__", JS::UndefinedHandleValue, JSPROP_SHARED, GetLocationProperty, nullptr); // We are almost certainly going to run script here, so we need an // AutoEntryScript. This is Gecko-specific and not in any spec. dom::AutoEntryScript aes(backstagePass); result = ProcessArgs(aes.cx(), glob, argv, argc, &dirprovider); JS_DropPrincipals(rt, gJSPrincipals); JS_SetAllNonReservedSlotsToUndefined(aes.cx(), glob); JS_GC(rt); } JS_GC(rt); } // this scopes the nsCOMPtrs if (!XRE_ShutdownTestShell()) NS_ERROR("problem shutting down testshell"); // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM rv = NS_ShutdownXPCOM( nullptr ); MOZ_ASSERT(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 = nullptr; #endif telStats = nullptr; appDir = nullptr; appFile = nullptr; dirprovider.ClearGREDirs(); dirprovider.ClearAppDir(); dirprovider.ClearPluginDir(); dirprovider.ClearAppFile(); #ifdef MOZ_CRASHREPORTER // Shut down the crashreporter service to prevent leaking some strings it holds. if (CrashReporter::GetEnabled()) CrashReporter::UnsetExceptionHandler(); #endif NS_LogTerm(); return result; }
int XRE_XPCShellMain(int argc, char **argv, char **envp) { JSRuntime *rt; JSContext *cx; int result; nsresult rv; gErrFile = stderr; gOutFile = stdout; gInFile = stdin; NS_LogInit(); nsCOMPtr<nsIFile> appFile; rv = XRE_GetBinaryPath(argv[0], getter_AddRefs(appFile)); if (NS_FAILED(rv)) { printf("Couldn't find application file.\n"); return 1; } nsCOMPtr<nsIFile> appDir; rv = appFile->GetParent(getter_AddRefs(appDir)); if (NS_FAILED(rv)) { printf("Couldn't get application directory.\n"); return 1; } XPCShellDirProvider dirprovider; dirprovider.SetAppFile(appFile); if (argc > 1 && !strcmp(argv[1], "-g")) { if (argc < 3) return usage(); if (!dirprovider.SetGREDir(argv[2])) { printf("SetGREDir failed.\n"); return 1; } argc -= 2; argv += 2; } if (argc > 1 && !strcmp(argv[1], "-a")) { if (argc < 3) return usage(); nsCOMPtr<nsIFile> dir; rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(dir)); if (NS_SUCCEEDED(rv)) { appDir = do_QueryInterface(dir, &rv); dirprovider.SetAppDir(appDir); } if (NS_FAILED(rv)) { printf("Couldn't use given appdir.\n"); return 1; } argc -= 2; argv += 2; } while (argc > 1 && !strcmp(argv[1], "-r")) { if (argc < 3) return usage(); nsCOMPtr<nsIFile> lf; rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(lf)); if (NS_FAILED(rv)) { printf("Couldn't get manifest file.\n"); return 1; } XRE_AddManifestLocation(NS_COMPONENT_LOCATION, lf); argc -= 2; argv += 2; } #ifdef MOZ_CRASHREPORTER // This is needed during startup and also shutdown, so keep it out // of the nested scope. // Special exception: will remain usable after NS_ShutdownXPCOM nsCOMPtr<nsICrashReporter> crashReporter; #endif { if (argc > 1 && !strcmp(argv[1], "--greomni")) { nsCOMPtr<nsIFile> greOmni; nsCOMPtr<nsIFile> appOmni; XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni)); if (argc > 3 && !strcmp(argv[3], "--appomni")) { XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni)); argc-=2; argv+=2; } else { appOmni = greOmni; } XRE_InitOmnijar(greOmni, appOmni); argc-=2; argv+=2; } nsCOMPtr<nsIServiceManager> servMan; rv = NS_InitXPCOM2(getter_AddRefs(servMan), appDir, &dirprovider); if (NS_FAILED(rv)) { printf("NS_InitXPCOM2 failed!\n"); return 1; } #ifdef MOZ_CRASHREPORTER const char *val = getenv("MOZ_CRASHREPORTER"); crashReporter = do_GetService("@mozilla.org/toolkit/crash-reporter;1"); if (val && *val) { crashReporter->SetEnabled(true); } #endif 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; } rtsvc->RegisterContextCallback(ContextCallback); // Override the default XPConnect operation callback. We could store the // old one and restore it before shutting down, but there's not really a // reason to bother. JS_SetOperationCallback(rt, XPCShellOperationCallback); cx = JS_NewContext(rt, 8192); if (!cx) { printf("JS_NewContext failed!\n"); return 1; } argc--; argv++; ProcessArgsForCompartment(cx, argv, argc); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { printf("failed to get nsXPConnect service!\n"); return 1; } nsCOMPtr<nsIPrincipal> systemprincipal; // 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<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && securityManager) { rv = securityManager->GetSystemPrincipal(getter_AddRefs(systemprincipal)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global gJSPrincipals = nsJSPrincipals::get(systemprincipal); JS_HoldPrincipals(gJSPrincipals); } } else { fprintf(gErrFile, "+++ Failed to get ScriptSecurityManager service, running without principals"); } } const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(rt); MOZ_ASSERT(scb, "We are assuming that nsScriptSecurityManager::Init() has been run"); shellSecurityCallbacks = *scb; JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks); #ifdef TEST_TranslateThis nsCOMPtr<nsIXPCFunctionThisTranslator> translator(new nsXPCFunctionThisTranslator); xpc->SetFunctionThisTranslator(NS_GET_IID(nsITestXPCFunctionCallback), translator); #endif nsCxPusher pusher; pusher.Push(cx); nsRefPtr<BackstagePass> backstagePass; rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); if (NS_FAILED(rv)) { fprintf(gErrFile, "+++ Failed to create BackstagePass: %8x\n", static_cast<uint32_t>(rv)); return 1; } JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setVersion(JSVERSION_LATEST); nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast<nsIGlobalObject *>(backstagePass), systemprincipal, 0, options, getter_AddRefs(holder)); if (NS_FAILED(rv)) return 1; { JS::Rooted<JSObject*> glob(cx, holder->GetJSObject()); if (!glob) { return 1; } backstagePass->SetGlobalObject(glob); JSAutoCompartment ac(cx, glob); if (!JS_InitReflect(cx, glob)) { JS_EndRequest(cx); return 1; } if (!JS_DefineFunctions(cx, glob, glob_functions) || !JS_DefineProfilingFunctions(cx, glob)) { JS_EndRequest(cx); return 1; } JS::Rooted<JSObject*> envobj(cx); envobj = JS_DefineObject(cx, glob, "environment", &env_class, nullptr, 0); if (!envobj) { JS_EndRequest(cx); return 1; } JS_SetPrivate(envobj, envp); nsAutoString workingDirectory; if (GetCurrentWorkingDirectory(workingDirectory)) gWorkingDirectory = &workingDirectory; JS_DefineProperty(cx, glob, "__LOCATION__", JSVAL_VOID, GetLocationProperty, nullptr, 0); JS_AddValueRoot(cx, &sScriptedOperationCallback); result = ProcessArgs(cx, glob, argv, argc, &dirprovider); JS_RemoveValueRoot(cx, &sScriptedOperationCallback); JS_DropPrincipals(rt, gJSPrincipals); JS_SetAllNonReservedSlotsToUndefined(cx, glob); JS_GC(rt); } pusher.Pop(); JS_GC(rt); JS_DestroyContext(cx); } // this scopes the nsCOMPtrs if (!XRE_ShutdownTestShell()) NS_ERROR("problem shutting down testshell"); // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM rv = NS_ShutdownXPCOM( nullptr ); MOZ_ASSERT(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 = nullptr; #endif appDir = nullptr; appFile = nullptr; dirprovider.ClearGREDir(); dirprovider.ClearAppDir(); dirprovider.ClearPluginDir(); dirprovider.ClearAppFile(); #ifdef MOZ_CRASHREPORTER // Shut down the crashreporter service to prevent leaking some strings it holds. if (crashReporter) { crashReporter->SetEnabled(false); crashReporter = nullptr; } #endif NS_LogTerm(); return result; }
bool XPCShellEnvironment::Init() { nsresult rv; #ifdef HAVE_SETBUF // unbuffer stdout so that output is in the correct order; note that stderr // is unbuffered by default setbuf(stdout, 0); #endif nsCOMPtr<nsIJSRuntimeService> rtsvc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1"); if (!rtsvc) { NS_ERROR("failed to get nsJSRuntimeService!"); return false; } JSRuntime *rt; if (NS_FAILED(rtsvc->GetRuntime(&rt)) || !rt) { NS_ERROR("failed to get JSRuntime from nsJSRuntimeService!"); return false; } if (!mGlobalHolder.Hold(rt)) { NS_ERROR("Can't protect global object!"); return false; } gOldContextCallback = JS_SetContextCallback(rt, ContextCallback); JSContext *cx = JS_NewContext(rt, 8192); if (!cx) { NS_ERROR("JS_NewContext failed!"); JS_SetContextCallback(rt, gOldContextCallback); gOldContextCallback = NULL; return false; } mCx = cx; JS_SetContextPrivate(cx, this); nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (!xpc) { NS_ERROR("failed to get nsXPConnect service!"); return false; } nsCOMPtr<nsIPrincipal> principal; nsCOMPtr<nsIScriptSecurityManager> securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && securityManager) { rv = securityManager->GetSystemPrincipal(getter_AddRefs(principal)); if (NS_FAILED(rv)) { fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global mJSPrincipals = nsJSPrincipals::get(principal); JS_HoldPrincipals(mJSPrincipals); } } else { fprintf(stderr, "+++ Failed to get ScriptSecurityManager service, running without principals"); } nsCxPusher pusher; pusher.Push(mCx); nsRefPtr<BackstagePass> backstagePass; rv = NS_NewBackstagePass(getter_AddRefs(backstagePass)); if (NS_FAILED(rv)) { NS_ERROR("Failed to create backstage pass!"); return false; } JS::CompartmentOptions options; options.setZone(JS::SystemZone) .setVersion(JSVERSION_LATEST); nsCOMPtr<nsIXPConnectJSObjectHolder> holder; rv = xpc->InitClassesWithNewWrappedGlobal(cx, static_cast<nsIGlobalObject *>(backstagePass), principal, 0, options, getter_AddRefs(holder)); if (NS_FAILED(rv)) { NS_ERROR("InitClassesWithNewWrappedGlobal failed!"); return false; } JS::Rooted<JSObject*> globalObj(cx, holder->GetJSObject()); if (!globalObj) { NS_ERROR("Failed to get global JSObject!"); return false; } backstagePass->SetGlobalObject(globalObj); { JSAutoRequest ar(cx); JSAutoCompartment ac(cx, globalObj); if (!JS_DefineFunctions(cx, globalObj, gGlobalFunctions) || !JS_DefineProfilingFunctions(cx, globalObj)) { NS_ERROR("JS_DefineFunctions failed!"); return false; } } mGlobalHolder = globalObj; FILE* runtimeScriptFile = fopen(kDefaultRuntimeScriptFilename, "r"); if (runtimeScriptFile) { fprintf(stdout, "[loading '%s'...]\n", kDefaultRuntimeScriptFilename); ProcessFile(cx, globalObj, kDefaultRuntimeScriptFilename, runtimeScriptFile, JS_FALSE); fclose(runtimeScriptFile); } return true; }