"eval не является функцией" при использовании iframe и Greasemonkey/Scriptish

Можно ли как-нибудь заставить этот кусок кода работать внутри Greasemonkey/Scriptish, или мне нужно будет вставить его в саму веб-страницу?

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);

Этот код работает при использовании исходного кода:

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

Но не при использовании в скрипте Greasemonkey я заметил, что есть какой-то барьер безопасности, с которым я не совсем знаком, и попытался использовать unsafeWindow для обхода XPCNativeWrapper.

Пожалуйста, пролите немного света на это.

1 ответ

Решение

Несколько вещей:

  1. Код имеет ошибку; getElementsById это не функция.
  2. Этот код работает в Greasemonkey 1.0 или более поздней версии, если @grant none Директива применяется. Подробнее об этом ниже.
  3. Для скриптов, всех других браузеров и сценариев Greasemonkey, где @grant none это невозможно; вам придется "ввести" код. Подробнее об этом ниже.
  4. Как говорит Джереми Дж. Старчер, eval() следует избегать как можно больше. eval() значительно усложняет работу, обслуживание, отладку и безопасность.


Для Greasemonkey 1.0 и более поздних версий:

В некоторых случаях Greasemonkey больше не использует XPCNativeWrapper, Смотрите документ для @grant директива

Так что это означает, что (1) Если ваш скрипт не использует GM_ функции и (2) скрипт указывает @grant none, тогда ваш код будет работать как есть (за исключением getElementsById опечатка).

Обратите внимание, что никакой другой скрипт-движок не делает этого. (По чертовски веским причинам. Новое поведение Greasemonkey относительно @grant и песочница в лучшем случае противоречива.)

Если вы хотите использовать GM_ функции, то вы должны ввести код iframe. Смотрите следующий раздел.


Для скриптов, привилегированных Greasemonkey, Chrome и т.д.:

Scriptish, Sandboxed Greasemonkey, Chrome и т. Д. Не всегда хорошо обрабатывают фреймы из соответствующих песочниц. (См. Эти вопросы, например.)

Единственный надежный способ запустить этот вид кода из GM/userscript - это внедрить его. Вот так:

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);
}
Другие вопросы по тегам