Ваш код страдает от нескольких проблем:
- Как вы уже заметили, функция и переменные из нагнетаемого сценария (mySuperScript.js) не видны сценарий содержания (contentScript .js). Это потому, что два сценария работают в разных execution environments.
- Вставка элемента
<script>
со сценарием, на который ссылается атрибут src
, не сразу вызывает выполнение скрипта. Поэтому, даже если скрипты должны запускаться в одной среде, вы все равно не сможете получить к ней доступ.
Чтобы решить эту проблему, сначала подумайте, действительно ли необходимо запустить mySuperScript.js
на странице. Если вы не получаете доступ к каким-либо объектам JavaScript из самой страницы, вам не нужно вводить скрипт. Вы должны попытаться свести к минимуму количество кода, которое выполняется на самой странице, чтобы избежать конфликтов.
Если вы не должны запустить код на страницу, а затем запустить mySuperScript.js
перед тем contentScript.js
, а затем любые функции и переменные немедленно доступны (как обычно, via the manifest или programmatic injection). Если по какой-то причине сценарий действительно нужно загружать динамически, вы можете объявить его в web_accessible_resources
и использовать fetch
или XMLHttpRequest
для загрузки сценария, а затем eval
, чтобы запустить его в контексте контекста вашего контента.
Например:
function loadScript(scriptUrl, callback) {
var scriptUrl = chrome.runtime.getURL(scriptUrl);
fetch(scriptUrl).then(function(response) {
return response.text();
}).then(function(responseText) {
// Optional: Set sourceURL so that the debugger can correctly
// map the source code back to the original script URL.
responseText += '\n//# sourceURL=' + scriptUrl;
// eval is normally frowned upon, but we are executing static
// extension scripts, so that is safe.
window.eval(responseText);
callback();
});
}
// Usage:
loadScript('mySuperScript.js', function() {
someFunctionFromMySuperScript();
});
Если вы действительно должны вызвать функцию на странице из сценария (т.е. mySuperScript.js
должен абсолютно выполняться в контексте страницы), то вы можете придать другой скрипт (через любой из методов от Building a Chrome Extension - Inject code in a page using a Content script), а затем передать сообщение обратно в сценарий содержимого (например, using custom events).
Например:
var script = document.createElement('script');
script.src = chrome.runtime.getURL('mySuperScript.js');
// We have to use .onload to wait until the script has loaded and executed.
script.onload = function() {
this.remove(); // Clean-up previous script tag
var s = document.createElement('script');
s.addEventListener('my-event-todo-rename', function(e) {
// TODO: Do something with e.detail
// (= result of someFunctionFromMySuperScript() in page)
console.log('Potentially untrusted result: ', e.detail);
//^Untrusted because anything in the page can spoof the event.
});
s.textContent = `(function() {
var currentScript = document.currentScript;
var result = someFunctionFromMySuperScript();
currentScript.dispatchEvent(new CustomEvent('my-event-todo-rename', {
detail: result,
}));
})()`;
// Inject to run above script in the page.
(document.head || document.documentElement).appendChild(s);
// Because we use .textContent, the script is synchronously executed.
// So now we can safely remove the script (to clean up).
s.remove();
};
(document.head || document.documentElement).appendChild(script);
(в приведенном выше примере я использую template literals, которые поддерживаются в Chrome 41+)
http://stackoverflow.com/questions/14705593/javascript- can-not-call-content-script-js-function Вы можете взглянуть на этот вопрос. –