Инъекция функций JS на страницу из сценария Greasemonkey в Chrome

у меня есть скрипт Greasemonkey, который отлично работает в Firefox и Opera. Однако я борюсь с тем, чтобы заставить его работать в Chrome. Проблема заключается в инъекции функции на страницу, которая может быть вызвана кодом со страницы. Вот что я делаю до сих пор:

во-первых, я получаю вспомогательную ссылку на unsafeWindow для Firefox. Это позволяет мне иметь один и тот же код для FF и Opera (и Chrome, я думал).

var uw = (this.unsafeWindow) ? this.unsafeWindow : window;

далее, я впрыскиваю функцию в страница. Это действительно очень тонкая оболочка, которая ничего не делает, кроме вызова соответствующей функции в контексте моего сценария GM:

uw.setConfigOption = function(newValue) {
    setTimeout(setConfigOption, 0, newValue);
}

тогда в моем скрипте есть соответствующая функция:

setConfigOption = function(newValue) {
    // do something with it, e.g. store in localStorage
}

наконец, я вставляю некоторый HTML на страницу со ссылкой для вызова функции.

var p = document.createElement('p');
p.innerHTML = '<a href="javascript:setConfigOption(1)">set config option to 1</a>';
document.getElementById('injection-point').appendChild(p);

обобщить: В Firefox, когда пользователь нажимает эту введенную ссылку, он выполнит вызов функции на unsafeWindow, который затем запускает таймаут, который вызывает соответствующую функцию в контексте моего сценария GM, который затем выполняет фактическую обработку. (Поправьте меня,если я ошибаюсь.)

в Chrome я просто получаю ошибку" Uncaught ReferenceError: setConfigOption не определен". И действительно, вход в "окно".setConfigOption "в консоль дает "неопределенный". В Firebug и консоли разработчика Opera есть функция.

возможно, есть другой способ сделать это, но некоторые из моих функций вызывается Flash-объектом на странице, что, по моему мнению, делает необходимым наличие функций в контексте страницы.

я быстро взглянул на альтернативы unsafeWindow на вики Greasemonkey, но все они выглядят довольно уродливо. Я полностью на неправильном пути здесь или я должен более внимательно изучить их?

: я следовал Макс С. советы и теперь он работает как в Firefox, так и в Chrome. Потому что функции, которые мне были нужны, чтобы страница была доступна, пришлось перезвонить в обычные, я переместил весь свой скрипт на страницу, т. е. он полностью завернут в функцию, которую он назвал " main ()".

чтобы сделать дополнительное уродство этого взлома немного более терпимым, я мог бы, по крайней мере, отказаться от использования unsafeWindow и wrappedJSObject сейчас.

мне все еще не удалось получить content scope runner из Вики Greasemonkey работает. Он должен сделать то же самое и, похоже, он выполняется просто отлично, но мои функции никогда не доступны для <a> элементы со страницы, например. Я еще не понял почему.

4 ответов


единственный способ связаться с кодом, запущенным на странице в Chrome, - это через DOM, поэтому вам придется использовать хак, как вставка <script> тег с вашим кодом. Обратите внимание, что это может оказаться ошибкой, если ваш скрипт должен запускаться перед всем остальным на странице.

EDIT: вот как хорошее расширение оповещения это:

function main () {
  // ...
  window.alert = function() {/* ... */};
  // ...
}

var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head || document.documentElement).appendChild(script);

у меня есть это :

contentscript.js:

function injectJs(link) {
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}

injectJs(chrome.extension.getURL('injected.js'));

вводят.js:

function main() {
     alert('Hello World!');
}

main();

я быстро взглянул на альтернативы unsafeWindow на вики Greasemonkey, но все они выглядят довольно уродливо. Я полностью на неправильном пути здесь или я должен более внимательно изучить их?

вы должны посмотреть, потому что это только доступный вариант. Я бы предпочел использовать расположение hack.

именем MyScript.пользователь.js:

function myFunc(){
  alert('Hello World!');
}

location.href="javascript:(function(){" + myFunc + "})()"

example.com/mypage.html

<script>
myFunc() // Hello World!
</script>

конечно, это некрасиво. Но это хорошо работает.


Content Scope Runner метод, упомянутый Max S. лучше, чем взлом местоположения, потому что его легче отлаживать.


другие ответы либо заставляют вас использовать выражения функции, импортировать дополнительные внешние файлом или использовать длинный латаный Хак.

этот ответ добавит javascript на страницу непосредственно из вашего исходного кода. Он будет использовать ECMAScript 6 (ES6) шаблон литералы чтобы получить многострочную строку javascript без особых усилий на странице.

var script = document.createElement('script'); 
script.type = "text/javascript"; 
script.innerHTML = ` 
   function test() {
      alert(1);
   }
`;
document.getElementsByTagName('head')[0].appendChild(script);

обратите внимание на backticks ``, которые определяют начало и конец многострочных.