Ошибка «Недопустимый контекст расширения» при вызове chrome.runtime.sendMessage () - PullRequest
0 голосов
/ 23 февраля 2019

У меня есть скрипт содержимого в расширении Chrome, который передает сообщения.Время от времени, когда скрипт содержимого вызывает

chrome.runtime.sendMessage({
  message: 'hello',
});

, он выдает ошибку:

Uncaught Error: Extension context invalidated.

Что означает эта ошибка? Я не смог найти ни одногодокументация по нему.

Это не происходит последовательно.На самом деле, это трудно воспроизвести.Кажется, это произойдет, если я просто оставлю страницу открытой в течение некоторого времени в фоновом режиме.


Еще одна подсказка : я написал много расширений Chrome со скриптами содержимого, которые пропускают сообщения, и яне видел эту ошибку раньше.Основное различие заключается в том, что этот скрипт содержимого внедряется фоновой страницей с использованием

chrome.tabs.executeScript({
  file: 'contentScript.js',
});

Меняет ли использование executeScript вместо файла манифеста каким-либо образом жизненный цикл сценария содержимого?

1 Ответ

0 голосов
/ 23 февраля 2019

Это, безусловно, связано с потерей приемника сообщений в середине соединения между контентом и фоновыми сценариями.

Я использовал этот подход в своих расширениях, так что у меня есть один модуль, которыйЯ могу использовать как фоновые, так и контентные скрипты.

messenger.js

const context = (typeof browser.runtime.getBackgroundPage !== 'function') ? 'content' : 'background'

chrome.runtime.onConnect.addListener(function (port) {
  port.onMessage.addListener(function (request) {
    try {
      const object = window.myGlobalModule[request.class]
      object[request.action].apply(module, request.data)
    } catch () {
      console.error(error)
    }
  })
})

export function postMessage (request) {
  if (context === 'content') {
    const port = chrome.runtime.connect()
    port.postMessage(request)
  }

  if (context === 'background') {
    if (request.allTabs) {
      chrome.tabs.query({}, (tabs) => {
        for (let i = 0; i < tabs.length; ++i) {
          const port = chrome.tabs.connect(tabs[i].id)
          port.postMessage(request)
        }
      })
    } else if (request.tabId) {
      const port = chrome.tabs.connect(request.tabId)
      port.postMessage(request)
    } else if (request.tabDomain) {
      const url = `*://*.${request.tabDomain}/*`
      chrome.tabs.query({ url }, (tabs) => {
        tabs.forEach((tab) => {
          const port = chrome.tabs.connect(tab.id)
          port.postMessage(request)
        })
      })
    } else {
      query({ active: true, currentWindow: true }, (tabs) => {
        const port = chrome.tabs.connect(tabs[0].id)
        port.postMessage(request)
      })
    }
  }
}

export default { postMessage }

Теперь вам просто нужно импортировать этот модуль как в фоновом, так и в фоновом скрипте.Если вы хотите отправить сообщение, просто сделайте:

messenger.postMessage({
   class: 'someClassInMyGlobalModuçe',
   action: 'someMethodOfThatClass',
   data: [] // any data type you want to send
})

Вы можете указать, хотите ли вы отправить на allTabs: true, определенный домен tabDomain: 'google.com' или одну вкладку tabId: 12.

...