Сценарии содержимого выполняются в среде «изолированного мира» . Вы должны внедрить свой state()
метод в саму страницу.
Если вы хотите использовать один из chrome.*
API-интерфейсов в сценарии, вам необходимо реализовать специальный обработчик событий, как описано в этом ответе: Расширение Chrome - получение исходного сообщения Gmail .
В противном случае, если вам не нужно использовать chrome.*
API, я настоятельно рекомендую внедрить весь код JS на странице, добавив <script>
тег:
Оглавление
- Способ 1: добавить другой файл
- Способ 2: внедрить встроенный код
- Способ 2b: использование функции
- Способ 3: использование встроенного события
- Динамические значения в введенном коде
Способ 1: добавить другой файл
Это самый простой / лучший метод, когда у вас много кода. Включите ваш фактический код JS в файл, например, в вашем расширении script.js
. Затем пусть ваш контент-скрипт будет следующим (объяснено здесь: Google Chome «Ярлык приложения», пользовательский Javascript ):
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.runtime.getURL('script.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
Примечание. Если вы используете этот метод, внедренный script.js
файл необходимо добавить в "web_accessible_resources"
раздел ( пример ). Если вы этого не сделаете, Chrome откажется загружать ваш скрипт и отобразит в консоли следующую ошибку:
Запрещение загрузки chrome-extension: // [EXTENSIONID] /script.js. Ресурсы должны быть перечислены в ключе манифеста web_accessible_resources, чтобы их могли загружать страницы вне расширения.
Способ 2: внедрить встроенный код
Этот метод полезен, когда вы хотите быстро запустить небольшой фрагмент кода. (См. Также: Как отключить горячие клавиши facebook с расширением Chrome? ).
var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
Примечание: литералы шаблонов поддерживаются только в Chrome 41 и выше. Если вы хотите, чтобы расширение работало в Chrome 40-, используйте:
var actualCode = ['/* Code here. Example: */' + 'alert(0);',
'// Beware! This array have to be joined',
'// using a newline. Otherwise, missing semicolons',
'// or single-line comments (//) will mess up your',
'// code ----->'].join('\n');
Способ 2b: использование функции
Для большой части кода цитирование строки неосуществимо. Вместо использования массива можно использовать функцию и строку:
var actualCode = '(' + function() {
// All code is executed in a local scope.
// For example, the following does NOT overwrite the global `alert` method
var alert = null;
// To overwrite a global variable, prefix `window`:
window.alert = null;
} + ')();';
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();
Этот метод работает, потому что +
оператор над строками и функция преобразуют все объекты в строку. Если вы собираетесь использовать код более одного раза, целесообразно создать функцию, чтобы избежать повторения кода. Реализация может выглядеть так:
function injectScript(func) {
var actualCode = '(' + func + ')();'
...
}
injectScript(function() {
alert("Injected script");
});
Примечание. Поскольку функция сериализована, исходная область действия и все связанные свойства теряются!
var scriptToInject = function() {
console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output: "undefined"
Способ 3: использование встроенного события
Иногда вы хотите сразу запустить некоторый код, например, запустить некоторый код перед <head>
созданием элемента. Это можно сделать, вставив <script>
тег с помощью textContent
(см. Метод 2 / 2b).
Альтернативой, но не рекомендуется, является использование встроенных событий. Это не рекомендуется, поскольку, если на странице определена политика безопасности содержимого, которая запрещает встроенные сценарии, то прослушиватели встроенных событий блокируются. С другой стороны, встроенные сценарии, введенные расширением, все еще работают. Если вы все еще хотите использовать встроенные события, вот как:
var actualCode = '// Some code example \n' +
'console.log(document.documentElement.outerHTML);';
document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');
Примечание. Этот метод предполагает отсутствие других глобальных прослушивателей событий, которые обрабатывают reset
событие. Если есть, вы также можете выбрать одно из других глобальных событий. Просто откройте консоль JavaScript (F12), введите document.documentElement.on
и выберите доступные события.
Динамические значения в введенном коде
Иногда вам нужно передать произвольную переменную введенной функции. Например:
var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
alert(GREETING + NAME);
};
Чтобы внедрить этот код, вам нужно передать переменные в качестве аргументов анонимной функции. Будьте уверены, чтобы реализовать это правильно! Следующее не будет работать:
var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME + ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi, I'm ,Rob)";
// ^^^^^^^^ ^^^ No string literals!
Решение заключается в использовании JSON.stringify
перед передачей аргумента. Пример:
var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';
Если у вас много переменных, целесообразно использовать JSON.stringify
один раз, чтобы улучшить читаемость, следующим образом:
...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';
player.addEventListener("onStateChange", state);