3 votes

Erreur "Extension context invalidated" lors de l'appel à chrome.runtime.sendMessage()

J'ai un contenu script dans une extension Chrome qui fait passer des messages. De temps en temps, lorsque le script de contenu appelle

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

une erreur se produit :

Uncaught Error: Extension context invalidated.

Que signifie cette erreur ? Je n'ai pas trouvé de documentation à ce sujet.

Cela ne se produit pas systématiquement. En fait, c'est difficile à reproduire. Il semble que cela se produise si je laisse la page ouverte pendant un certain temps en arrière-plan.


Un autre indice : J'ai écrit de nombreuses extensions Chrome avec du contenu scripts qui passent des messages et je n'ai jamais vu cette erreur auparavant. La principale différence est que ce contenu scripts est injecté par la page d'arrière-plan en utilisant.

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

Est-ce que l'utilisation de executeScript au lieu du fichier manifeste change en quelque sorte le cycle de vie du contenu script ?

2voto

herodrigues Points 808

Cela est certainement lié au fait que l'écouteur de messages est perdu au milieu de la connexion entre le contenu et les scripts d'arrière-plan.

J'ai utilisé cette approche dans mes extensions, afin d'avoir un seul module que je peux utiliser à la fois en arrière-plan et dans les scripts de contenu.

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 }

Il ne vous reste plus qu'à importer ce module dans le contenu et le fond script. Si vous voulez envoyer un message, il suffit de le faire :

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

Vous pouvez spécifier si vous voulez envoyer à allTabs: true un domaine spécifique tabDomain: 'google.com' ou un seul onglet tabId: 12 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X