Как передать параметр JavaScript в файл содержимого script, который вводится с помощью:
chrome.tabs.executeScript(tab.id, {file: "content.js"});
Как передать параметр JavaScript в файл содержимого script, который вводится с помощью:
chrome.tabs.executeScript(tab.id, {file: "content.js"});
Там нет такой вещи, как "передать параметр в файл".
Что вы можете сделать, это либо вставить содержимое script перед выполнением файла, либо отправить сообщение после вставки файла. Ниже приведен пример этих различных методов.
Если вы хотите определить некоторые переменные перед вставкой файла, просто вставьте chrome.tabs.executeScript
:
chrome.tabs.executeScript(tab.id, {
code: 'var config = 1;'
}, function() {
chrome.tabs.executeScript(tab.id, {file: 'content.js'});
});
Если ваша переменная не так проста, я рекомендую использовать JSON.stringify
для преобразования объекта в строку:
var config = {somebigobject: 'complicated value'};
chrome.tabs.executeScript(tab.id, {
code: 'var config = ' + JSON.stringify(config)
}, function() {
chrome.tabs.executeScript(tab.id, {file: 'content.js'});
});
В предыдущем методе переменные могут использоваться в content.js
следующим образом:
// content.js
alert('Example:' + config);
Предыдущий метод может использоваться для установки параметров после JS файла. Вместо определения переменных непосредственно в глобальной области вы можете использовать API передачи сообщений для передачи параметров:
chrome.tabs.executeScript(tab.id, {file: 'content.js'}, function() {
chrome.tabs.sendMessage(tab.id, 'whatever value; String, object, whatever');
});
В содержании script (content.js
) вы можете прослушивать эти сообщения с помощью события chrome.runtime.onMessage
и обрабатывать сообщение:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
// Handle message.
// In this example, message === 'whatever value; String, object, whatever'
});
Существует пять общих способов передачи данных в контент script с помощью tabs.executeScript()
(MDN):
chrome.storage.local
(MDN) чтобы передать данные (перед вводом вашего script).document_start
, без необходимости в содержании script для выполнения асинхронного запроса.chrome.storage.onChanged
(MDN) в вашем содержании script, чтобы прослушать фон script, чтобы установить значение, используя chrome.storage.local.set()
(MDN).chrome.storage.local
(перед выполнением script)Используя этот метод, вы поддерживаете парадигму выполнения, которую вы используете, вводя script, который выполняет функцию, а затем завершает работу. Он также не имеет потенциальной проблемы безопасности при использовании динамического значения для создания исполняемого кода, что делается во втором варианте ниже.
chrome.storage.local.set()
(MDN).chrome.storage.local.set()
вызовите tabs.executeScript()
(MDN).var updateTextTo = document.getElementById('comments').value;
chrome.storage.local.set({
updateTextTo: updateTextTo
}, function () {
chrome.tabs.executeScript({
file: "content_script3.js"
});
});
chrome.storage.local.get()
(MDN).storage.local
(например, удалите ключ с помощью chrome.storage.local.remove()
(MDN)).chrome.storage.local.get('updateTextTo', function (items) {
assignTextToTextareas(items.updateTextTo);
chrome.storage.local.remove('updateTextTo');
});
function assignTextToTextareas(newText){
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
}
См. Примечания 1 и 2.
До выполнения вашего script вы можете ввести код, который устанавливает переменную в контенте script, который может использовать ваш основной script:
В следующем случае "'" + JSON.stringify().replace(/\\/g,'\\\\').replace(/'/g,"\\'") + "'"
следует кодировать данные в текст, который будет правильным JSON, если он интерпретируется как код, перед тем как положить его в строка code
. Методы .replace()
необходимы для A) имеют текст, который правильно интерпретируется как строка при использовании в качестве кода, и B) цитирует любой '
, который существует в данных. Затем он использует JSON.parse()
, чтобы вернуть данные в строку в вашем контенте script. Хотя это кодирование строго не требуется, это хорошая идея, так как вы не знаете содержание значения, которое вы собираетесь отправить в контент script. Это значение может быть легко может привести к повреждению кода, который вы вводите (т.е. Пользователь может использовать '
и/или "
в тексте, который они ввели). Если вы этого не сделаете, каким-то образом избегайте значения, есть отверстие безопасности, которое может привести к выполнению произвольного кода.
chrome.tabs.executeScript()
(MDN)20 > , вызовите tabs.executeScript()
, чтобы ввести script (Примечание: tabs.executeScript()
будет выполнять скрипты в том порядке, в котором вы вызываете tabs.executeScript()
, как долго так как они имеют одинаковое значение для runAt
. Таким образом, ожидание обратного вызова маленького code
строго не требуется).var updateTextTo = document.getElementById('comments').value;
chrome.tabs.executeScript({
code: "var newText = JSON.parse('" + encodeToPassToContentScript(updateTextTo) + "');"
}, function () {
chrome.tabs.executeScript({
file: "content_script3.js"
});
});
function encodeToPassToContentScript(obj){
//Encodes into JSON and quotes \ characters so they will not break
// when re-interpreted as a string literal. Failing to do so could
// result in the injection of arbitrary code and/or JSON.parse() failing.
return JSON.stringify(obj).replace(/\\/g,'\\\\').replace(/'/g,"\\'")
}
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
См. Примечания 1, 2 и 3.
Для этого требуется, чтобы ваш контент script для установки прослушивателя для сообщения, посланного всплывающим окном, или, возможно, фона script (если взаимодействие с пользовательским интерфейсом заставляет всплывающее окно закрываться). Это немного сложнее.
tabs.query()
(MDN).tabs.executeScript()
(MDN)tabs.executeScript()
используйте tabs.sendMessage()
(MDN) (который требует знания tabId
), чтобы отправить данные в виде сообщения.var updateTextTo = document.getElementById('comments').value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {
file: "content_script3.js"
}, function(){
chrome.tabs.sendMessage(tabs[0].id,{
updateTextTo: updateTextTo
});
});
});
chrome.runtime.onMessage.addListener()
(MDN).runtime.onMessage
# 3.2 не является обязательным. Вы могли бы сохранить свой код активным, ожидая другого сообщения, но это изменит парадигму, которую вы используете, на ту, где вы загружаете свой код, и она остается резидентом, ожидая сообщения для инициирования действий.
chrome.runtime.onMessage.addListener(assignTextToTextareas);
function assignTextToTextareas(message){
newText = message.updateTextTo;
if (typeof newText === 'string') {
Array.from(document.querySelectorAll('textarea.comments')).forEach(el => {
el.value = newText;
});
}
chrome.runtime.onMessage.removeListener(assignTextToTextareas); //optional
}
См. Примечания 1 и 2.
Примечание 1: Использование Array.from()
прекрасно, если вы не делаете это много раз и используете версия браузера, которая имеет его (Chrome >= версия 45, Firefox >= 32). В Chrome и Firefox Array.from()
медленнее по сравнению с другими методами получения массива из NodeList. Для более быстрого и совместимого преобразования в Array вы можете использовать код asArray()
в этом ответе. Вторая версия asArray()
, предоставленная в этом ответе, также более надежна.
Примечание 2: Если вы хотите ограничить свой код версией Chrome >= 51 или версией Firefox >= 50, у Chrome есть forEach()
для NodeLists с версии v51. Таким образом, преобразование в массив не требуется. Очевидно, что вам не нужно преобразовывать в массив, если вы используете другой тип цикла.
Примечание 3: Хотя я ранее использовал этот метод (вводя script с переменным значением) в свой собственный код, мне напомнили, что я должен был включить его здесь при чтении этот ответ.