Расширение Chrome: вызывать скрипт страницы путем инъекции

Можно ли внедрить файл javascript в DOM и сразу же выполнить его? Я хочу вызывать функции javascript на странице/DOM. Единый контент-скрипт работать не будет из-за изолированных миров. Для использования chrome.tabs.executeScript() требуется фоновая страница.

Простой пример:
JavaScript DOM

function sayHello(){
  alert('Hello World');
}

Файл Javascript для вставки

console.log('Injection complete. Now calling DOM script.');
sayHello();

person Kim    schedule 28.03.2012    source источник


Ответы (1)


Вот два моих любимых способа...

// Executing an anonymous script
function exec(fn) {
   var script = document.createElement('script');
   script.setAttribute("type", "application/javascript");
   script.textContent = '(' + fn + ')();';
   document.documentElement.appendChild(script); // run the script
   document.documentElement.removeChild(script); // clean up
}

script = function() {
//sayHello();
alert('hello');
}

exec(script);

// Append a script from a file in your extension
function appendScript(scriptFile) {
   var script = document.createElement('script');
   script.setAttribute("type", "application/javascript");
   script.setAttribute("src", chrome.extension.getURL(scriptFile));
   document.documentElement.appendChild(script); // run the script
}

appendScript('someFile.js');

Также chrome.tabs.executeScript() можно использовать из всплывающего окна действия браузера/страницы, и приведенный выше код также работает в скрипте содержимого.

ИЗМЕНИТЬ
Благодаря комментариям @renocor, вот вариант первого метода, который позволяет вам отправлять аргументы внедренной функции....

function exec(fn) {
    var args = '';
    if (arguments.length > 1) {
        for (var i = 1, end = arguments.length - 2; i <= end; i++) {
            args += typeof arguments[i]=='function' ? arguments[i] : JSON.stringify(arguments[i]) + ', ';
        }
        args += typeof arguments[i]=='function' ? arguments[arguments.length - 1] : JSON.stringify(arguments[arguments.length - 1]);
    }
    var script = document.createElement('script');
    script.setAttribute("type", "application/javascript");
    script.textContent = '(' + fn + ')(' + args + ');';
    document.documentElement.appendChild(script); // run the script
    document.documentElement.removeChild(script); // clean up
}

script = function(what, huh, nah, yeah) {
    console.debug(arguments);
    console.debug('what=', what);
    console.debug('huh=', huh);
    console.debug('nah=', nah);
    console.debug('yeah=', yeah);
    if (typeof yeah=='function') yeah();
}

exec(script, 'meh', ['bleh'], {
    a: {
        b: 0
    }
}, function(){
    alert('hi');
});

console.debug('No arguments');

exec(script);
person PAEz    schedule 28.03.2012
comment
Я удаляю скрипт только с помощью анонимной функции, потому что в любом случае он будет запускаться только один раз, и поэтому он больше бесполезен, и его лучше очистить ... в противном случае вы будете продолжать добавлять теги скрипта каждый раз, когда вы его используете. - person PAEz; 29.03.2012
comment
В первом случае, если вы хотите передать функции переменные: function exec(fn, opts) { if (!opts) var opts = {}; var script = document.createElement('script'); script.setAttribute (тип, приложение/javascript); script.textContent = '(function(){var opts = ' + JSON.stringify(opts) + ';(' + fn + ')();})();'; ... } Полезно... по крайней мере для меня. - person Parziphal; 20.04.2013
comment
@renocor Отличная идея, определенно полезная. Я рассмотрел идею и сделал ее немного по-другому, не могли бы вы проверить ( gist.github.com/PAEz/ ), и если вам это нравится, я добавлю его в ответ (ваш способ может быть лучше .... я не знаю). Большое спасибо за ваш вклад. - person PAEz; 20.04.2013
comment
@renocor Только что обновил его, чтобы вы также могли передавать функцию в качестве аргумента ( gist.github.com/PAEz/ ).... круто - person PAEz; 20.04.2013
comment
Да, это даже лучше. На самом деле я не знал об аргументах var, поэтому я передал только один аргумент, хе-хе. - person Parziphal; 21.04.2013