Beispiel #1
0
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;
}