Расширяемый код Chrome vs Content scripts vs Injected scripts

Я пытаюсь заставить расширение Chrome запускать функцию init() всякий раз, когда загружается новая страница, но мне трудно понять, как это сделать. Из того, что я понимаю, мне нужно сделать следующее в background.html:

  • Используйте chrome.tabs.onUpdated.addListener(), чтобы проверить, когда страница изменено
  • Используйте chrome.tabs.executeScript для запуска script.

Это код, который у меня есть:

//background.html
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    chrome.tabs.executeScript(null, {code:"init();"});
});

//script.js
function init() {
    alert("It works!");
}

Мне также интересно, будет ли функция init() иметь доступ к моим другим функциям, расположенным в других JS файлах?

Ответ 1

JavaScript-код в расширениях Chrome можно разделить на следующие группы:

  • Код расширения - Полный доступ ко всем разрешенным API chrome.*.
    Это включает в себя справочную страницу и все страницы, которые имеют прямой доступ к ней через chrome.extension.getBackgroundPage(), например всплывающие окна браузера .

  • Скрипты содержимого (через файл манифеста или chrome.tabs.executeScript) - Частичный доступ к некоторым API chrome, полный доступ к странице DOM ( не для любого из объектов window, включая фреймы).
    Скрипты содержимого выполняются в области между расширением и страницей. Глобальный объект window Контента script отличается от глобального пространства имен страницы/расширения.

  • Введенные скрипты (через этот метод в Контенте script) - Полный доступ ко всем свойствам на странице. Отсутствует доступ к любому из API chrome.*.
    Введенные сценарии ведут себя так, как если бы они были включены самой страницей и никак не связаны с расширением. См. этот пост, чтобы узнать больше информации о различных методах инъекции.

Чтобы отправить сообщение из введенного script в контент script, необходимо использовать события. См. этот ответ для примера. Примечание. Сообщение, переносимое в пределах расширения из одного контекста в другой, является автоматически (JSON) - сериализовано и проанализировано.


В вашем случае код на фоновой странице (chrome.tabs.onUpdated), скорее всего, вызывается до того, как содержимое script script.js будет оценены. Итак, вы получите ReferenceError, потому что init нет.

Кроме того, когда вы используете chrome.tabs.onUpdated, убедитесь, что вы проверяете, полностью ли загружена страница, потому что событие срабатывает дважды: перед загрузкой и завершением:

//background.html
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        // Execute some script when the page is fully (DOM) ready
        chrome.tabs.executeScript(null, {code:"init();"});
    }
});