문제

Is there any way I can get this piece of code to work inside Greasemonkey/Scriptish, or would I have to inject it into the webpage itself?

body = document.getElementsByTagName("body")[0];
fakeConsole = 'window.top._console';
injected = document.getElementById("sandbox") ? true : false;
sandboxframe = injected ? document.getElementsById("sandbox") : document.createElement('iframe');
sandbox = null;

if (!injected) {
   body.appendChild(sandboxframe);
   sandboxframe.setAttribute('id', 'sandbox');
   sandboxframe.setAttribute('style', "display:none")
}

var p = sandboxframe.contentWindow.eval('1 + 1');
console.log(p);

This code does work when using source:

 <script type="text/javascript" src="test.js"></script>

But not when using in a Greasemonkey script, I have observed there's some kind of security barrier I'm not quite familiar with and attempted to use unsafeWindow to bypass XPCNativeWrapper.

Please shed some light on this.

도움이 되었습니까?

해결책

Several things:

  1. The code has an error; getElementsById is not a function.
  2. That code otherwise does work in Greasemonkey 1.0 or later, if the @grant none directive applies. More on this below.
  3. For Scriptish, all other browsers, and Greasemonkey scenarios where @grant none is not possible; you will have to "inject" the code. More on this below.
  4. As Jeremy J Starcher says, eval() should be avoided as much as possible. eval() makes performance, maintenance, debugging, and security much harder.

For Greasemonkey 1.0, and later:

In some scenarios, Greasemonkey no longer uses the XPCNativeWrapper. See the doc for the @grant directive.

So this means that (1) If your script uses no GM_ functions and (2) the script specifies @grant none, then your code will run as-is (excepting the getElementsById typo).

Note that no other scripting engine does this. (For darn good reasons. Greasemonkey's new behavior concerning @grant, and the sandbox, is controversial at best.)

If you wish to use GM_ functions, then you must inject the iframe code. See the next section.


For Scriptish, Privileged Greasemonkey, Chrome, etc.:

Scriptish, Sandboxed Greasemonkey, Chrome, etc. all do not handle iframes well from within their respective sandboxes. (See these Q's, for example.)

The only reliable way to run this kind of code from a GM/userscript is to inject it. Like so:

function gmMain () {
    body = document.getElementsByTagName("body")[0];
    fakeConsole = 'window.top._console';
    injected = document.getElementById("sandbox") ? true : false;
    sandboxframe = injected ? document.getElementById("sandbox") : document.createElement('iframe');
    sandbox = null;

    if (!injected) {
       body.appendChild(sandboxframe);
       sandboxframe.setAttribute('id', 'sandbox');
       sandboxframe.setAttribute('style', "display:none")
    }

    var p = sandboxframe.contentWindow.eval('1 + 1');
    console.log(p);
}

addJS_Node (null, null, gmMain);

function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top