Пример #1
0
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;
}
Пример #2
0
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(&currentCX)))
        {
            // 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;
        }
    }
}
Пример #3
0
static void
ProcessFile(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
            JSBool forceTTY)
{
    JSScript *script;
    jsval result;
    int lineno, startline;
    JSBool ok, hitEOF;
    char *bufp, buffer[4096];
    JSString *str;

    if (forceTTY) {
        file = stdin;
    } else if (!isatty(fileno(file))) {
        /*
         * It's not interactive - just execute it.
         *
         * Support the UNIX #! shell hack; gobble the first line if it starts
         * with '#'.  TODO - this isn't quite compatible with sharp variables,
         * as a legal js program (using sharp variables) might start with '#'.
         * But that would require multi-character lookahead.
         */
        int ch = fgetc(file);
        if (ch == '#') {
            while((ch = fgetc(file)) != EOF) {
                if(ch == '\n' || ch == '\r')
                    break;
            }
        }
        ungetc(ch, file);
        DoBeginRequest(cx);

        script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
                                                   gJSPrincipals);

        if (script) {
            if (!compileOnly)
                (void)JS_ExecuteScript(cx, obj, script, &result);
            JS_DestroyScript(cx, script);
        }
        DoEndRequest(cx);

        return;
    }

    /* It's an interactive filehandle; drop into read-eval-print loop. */
    lineno = 1;
    hitEOF = JS_FALSE;
    do {
        bufp = buffer;
        *bufp = '\0';

        /*
         * Accumulate lines until we get a 'compilable unit' - one that either
         * generates an error (before running out of source) or that compiles
         * cleanly.  This should be whenever we get a complete statement that
         * coincides with the end of a line.
         */
        startline = lineno;
        do {
            if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
                hitEOF = JS_TRUE;
                break;
            }
            bufp += strlen(bufp);
            lineno++;
        } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
        
        DoBeginRequest(cx);
        /* Clear any pending exception from previous failed compiles.  */
        JS_ClearPendingException(cx);
        script = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
                                               strlen(buffer), "typein", startline);
        if (script) {
            JSErrorReporter older;

            if (!compileOnly) {
                ok = JS_ExecuteScript(cx, obj, script, &result);
                if (ok && result != JSVAL_VOID) {
                    /* Suppress error reports from JS_ValueToString(). */
                    older = JS_SetErrorReporter(cx, NULL);
                    str = JS_ValueToString(cx, result);
                    JS_SetErrorReporter(cx, older);
    
                    if (str)
                        fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
                    else
                        ok = JS_FALSE;
                }
            }
            JS_DestroyScript(cx, script);
        }
        DoEndRequest(cx);
    } while (!hitEOF && !gQuitting);

    fprintf(gOutFile, "\n");
}
nsresult
mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponent,
                                        JSObject **aGlobal,
                                        char **aLocation)
{
    nsresult rv;

    JSPrincipals* jsPrincipals = nsnull;
    JSCLContextHelper cx(mContext);

#ifndef XPCONNECT_STANDALONE
    rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals);
    NS_ENSURE_SUCCESS(rv, rv);

    JSPrincipalsHolder princHolder(mContext, jsPrincipals);
#endif

    nsCOMPtr<nsIXPCScriptable> backstagePass;
    rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass));
    NS_ENSURE_SUCCESS(rv, rv);

    JSCLAutoErrorReporterSetter aers(cx, mozJSLoaderErrorReporter);

    nsCOMPtr<nsIXPConnect> xpc =
        do_GetService(kXPConnectServiceContractID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    // Make sure InitClassesWithNewWrappedGlobal() installs the
    // backstage pass as the global in our compilation context.
    JS_SetGlobalObject(cx, nsnull);

    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
    rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass,
                                              NS_GET_IID(nsISupports),
                                              nsIXPConnect::
                                                  FLAG_SYSTEM_GLOBAL_OBJECT,
                                              getter_AddRefs(holder));
    NS_ENSURE_SUCCESS(rv, rv);

    JSObject *global;
    rv = holder->GetJSObject(&global);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!JS_DefineFunctions(cx, global, gGlobalFun)) {
        return NS_ERROR_FAILURE;
    }

    nsCOMPtr<nsIXPConnectJSObjectHolder> locationHolder;
    rv = xpc->WrapNative(cx, global, aComponent,
                         NS_GET_IID(nsILocalFile),
                         getter_AddRefs(locationHolder));
    NS_ENSURE_SUCCESS(rv, rv);

    JSObject *locationObj;
    rv = locationHolder->GetJSObject(&locationObj);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!JS_DefineProperty(cx, global, "__LOCATION__",
                           OBJECT_TO_JSVAL(locationObj), nsnull, nsnull, 0)) {
        return NS_ERROR_FAILURE;
    }

    nsCAutoString nativePath;
    // Quick hack to unbust XPCONNECT_STANDALONE.
    // This leaves the jsdebugger with a non-URL pathname in the 
    // XPCONNECT_STANDALONE case - but at least it builds and runs otherwise.
    // See: http://bugzilla.mozilla.org/show_bug.cgi?id=121438
#ifdef XPCONNECT_STANDALONE
    localFile->GetNativePath(nativePath);
#else
    NS_GetURLSpecFromFile(aComponent, nativePath);
#endif

    // Before compiling the script, first check to see if we have it in
    // the fastload file.  Note: as a rule, fastload errors are not fatal
    // to loading the script, since we can always slow-load.
    nsCOMPtr<nsIFastLoadService> flSvc = do_GetFastLoadService(&rv);

    // Save the old state and restore it upon return
    FastLoadStateHolder flState(flSvc);
    PRBool fastLoading = PR_FALSE;

    if (NS_SUCCEEDED(rv)) {
        rv = StartFastLoad(flSvc);
        if (NS_SUCCEEDED(rv)) {
            fastLoading = PR_TRUE;
        }
    }

    nsCOMPtr<nsIURI> uri;
    rv = NS_NewURI(getter_AddRefs(uri), nativePath);
    NS_ENSURE_SUCCESS(rv, rv);

    JSScript *script = nsnull;

    if (fastLoading) {
        rv = ReadScript(flSvc, nativePath.get(), uri, cx, &script);
        if (NS_SUCCEEDED(rv)) {
            LOG(("Successfully loaded %s from fastload\n", nativePath.get()));
            fastLoading = PR_FALSE; // no need to write out the script
        } else if (rv == NS_ERROR_NOT_AVAILABLE) {
            // This is ok, it just means the script is not yet in the
            // fastload file.
            rv = NS_OK;
        } else {
            LOG(("Failed to deserialize %s\n", nativePath.get()));

            // Remove the fastload file, it may be corrupted.
            LOG(("Invalid fastload file detected, removing it\n"));
            nsCOMPtr<nsIObjectOutputStream> objectOutput;
            flSvc->GetOutputStream(getter_AddRefs(objectOutput));
            if (objectOutput) {
                flSvc->SetOutputStream(nsnull);
                objectOutput->Close();
            }
            nsCOMPtr<nsIObjectInputStream> objectInput;
            flSvc->GetInputStream(getter_AddRefs(objectInput));
            if (objectInput) {
                flSvc->SetInputStream(nsnull);
                objectInput->Close();
            }
            if (mFastLoadFile) {
                mFastLoadFile->Remove(PR_FALSE);
            }
            fastLoading = PR_FALSE;
        }
    }


    if (!script || NS_FAILED(rv)) {
        // The script wasn't in the fastload cache, so compile it now.
        LOG(("Slow loading %s\n", nativePath.get()));

#ifdef HAVE_PR_MEMMAP
        PRInt64 fileSize;
        rv = aComponent->GetFileSize(&fileSize);
        if (NS_FAILED(rv))
            return rv;

        PRInt64 maxSize;
        LL_UI2L(maxSize, PR_UINT32_MAX);
        if (LL_CMP(fileSize, >, maxSize)) {
            NS_ERROR("file too large");
            return NS_ERROR_FAILURE;
        }

        PRFileDesc *fileHandle;
        rv = aComponent->OpenNSPRFileDesc(PR_RDONLY, 0, &fileHandle);
        NS_ENSURE_SUCCESS(rv, rv);

        // Make sure the file is closed, no matter how we return.
        FileAutoCloser fileCloser(fileHandle);

        PRFileMap *map = PR_CreateFileMap(fileHandle, fileSize,
                                          PR_PROT_READONLY);
        if (!map) {
            NS_ERROR("Failed to create file map");
            return NS_ERROR_FAILURE;
        }

        // Make sure the file map is closed, no matter how we return.
        FileMapAutoCloser mapCloser(map);

        PRUint32 fileSize32;
        LL_L2UI(fileSize32, fileSize);

        char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
        if (!buf) {
            NS_WARNING("Failed to map file");
            return NS_ERROR_FAILURE;
        }

        script = JS_CompileScriptForPrincipals(cx, global,
                                               jsPrincipals,
                                               buf, fileSize32,
                                               nativePath.get(), 1);
        PR_MemUnmap(buf, fileSize32);

#else  /* HAVE_PR_MEMMAP */

        /**
         * No memmap implementation, so fall back to using
         * JS_CompileFileHandleForPrincipals().
         */

        FILE *fileHandle;
        rv = aComponent->OpenANSIFileDesc("r", &fileHandle);
        NS_ENSURE_SUCCESS(rv, rv);

        script = JS_CompileFileHandleForPrincipals(cx, global,
                                                   nativePath.get(),
                                                   fileHandle, jsPrincipals);

        /* JS will close the filehandle after compilation is complete. */

#endif /* HAVE_PR_MEMMAP */
    }
Пример #5
0
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;
}