Внедрить JS на страницу Google Chrome с переменными из пользовательского скрипта? - PullRequest
2 голосов
/ 09 сентября 2010

У меня есть скрипт, который использовал unsafeWindow в FireFox, так как он не работал, я искал другой вариант и нашел его, мне просто интересно: как я могу использовать переменную из моего usercript в обход обхода unsafeWindow?

Мой код:

// ==UserScript==
// @name   Test
// @description  Test
// @include   http://www.google*
// ==/UserScript==

var toAlert = "This is what I want to alert...";
alert("Before implementation...");
contentEval( function(){ alert(toAlert);});
alert("And after...");
function contentEval(source) {
  // Check for function input.
  if ('function' == typeof source) {
    // Execute this function with no arguments, by adding parentheses.
    // One set around the function, required for valid syntax, and a
    // second empty set calls the surrounded function.
    source = '(' + source + ')();'
  }

  // Create a script node holding this  source code.
  var script = document.createElement('script');
  script.setAttribute("type", "application/javascript");
  script.textContent = source;

  // Insert the script node into the page, so it will run, and immediately
  // remove it to clean up.
  document.body.appendChild(script);
  document.body.removeChild(script);
}

И это не работает ... Что я делаю не так?

1 Ответ

4 голосов
/ 09 сентября 2010

Ваш сценарий будет работать, если в глобальной области страницы определено toAlert.

В Chrome расширение / Greasemonkey JavaScript не может совместно использовать переменные или замыкания со страницей JavaScript.
Вот почему выне может внедрить эту функцию напрямую, из области расширения в область страницы, но должен воссоздать ее из исходной строки.

Это означает, что если вы создаете функцию в области страницы, любые переменные или функцииВаша функция должна либо:

  1. Уже присутствовать в глобальном масштабе на исходной странице.
    Или
  2. Сценарий также добавляется на исходную страницу.

Например, изменение вашего кода следующим образом ...

//-- Must recreate the variable that the function requires.
scriptStr  = 'var toAlert="' + toAlert +'";';

//-- Now the function.
scriptStr += '(' + source.toString() + ')();'

var script = document.createElement('script');
script.textContent = scriptStr;

... работает, но этот подход явно запутывается.

Умная вещь, которую нужно сделать, это либо:
(A) сохранить весь ваш JavaScript в расширении;не взаимодействуйте с JavaScript страницы.

Или (B), если вам нужно взаимодействовать с JS страницы или загружать библиотеки, такие как jQuery, а затем поместить все вашего кода в одну основную () и запишите его на исходную страницу.

Примерно так:

function localMain ()
{
    /*--- Put EVERYTHING inside this wrapper, functions and variables.
        Call or use nothing else that's defined in the GM script here.
        Can use objects in the source page's scope, though.
    */
}

//--- Now create the function in the page's scope and run it.
var scriptNode          = document.createElement ("script");
scriptNode.textContent  = localMain.toString() + "\n localMain ();";
document.head.appendChild (scriptNode);

Обратите внимание, что если вы также загружаете библиотеку в область видимости страницы, то вам может понадобитьсязадержка запуска localMain() с использованием таймера и проверки этой библиотеки.

...