Actualiza tu código

Actualizaciones que no están relacionadas con otros problemas

Esta es la primera de tres secciones en las que se describen los cambios necesarios para el código que no forma parte del service worker de extensión. Esta sección se aplica a los cambios de código obligatorios que no están relacionados con otros problemas. En las siguientes dos secciones, se explica cómo reemplazar las solicitudes web de bloqueo y mejorar la seguridad.

Reemplaza tabs.executeScript() por scripting.executeScript().

En Manifest V3, executeScript() pasa de la API de tabs a la API de scripting. Esto requiere cambios en los permisos del archivo de manifiesto, además de los cambios reales en el código.

Para el método executeScript(), necesitas lo siguiente:

  • El permiso "scripting".
  • Permisos de host o "activeTab"

El método scripting.executeScript() es similar a cómo funcionaba con tabs.executeScript(). Hay algunas diferencias.

  • Mientras que el método anterior solo podía tomar un único archivo, el nuevo método puede tomar un array de archivos.
  • También pasas un objeto ScriptInjection en lugar de InjectDetails. Existen muchas diferencias entre los dos. Por ejemplo, tabId ahora se pasa como miembro de ScriptInjection.target en lugar de como argumento de método.

En el ejemplo, se muestra cómo hacerlo.

Manifest V2
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();

chrome.tabs.executeScript(
  tab.id,
  {
    file: 'content-script.js'
  }
);

En un archivo de secuencia de comandos en segundo plano

Manifest V3
async function getCurrentTab()
let tab = await getCurrentTab();

chrome.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['content-script.js']
});

En el service worker de la extensión.

Se reemplazaron tabs.insertCSS() y tabs.removeCSS() por scripting.insertCSS() y scripting.removeCSS().

En Manifest V3, insertCSS() y removeCSS() se mueven de la API de tabs a la API de scripting. Esto requiere cambios en los permisos del archivo de manifiesto, además de cambios en el código:

  • El permiso "scripting".
  • Permisos de host o permiso "activeTab"

Las funciones de la API de scripting son similares a las de tabs. Hay algunas diferencias.

  • Cuando llames a estos métodos, pasarás un objeto CSSInjection en lugar de InjectDetails.
  • El tabId ahora se pasa como miembro de CSSInjection.target en lugar de como argumento de método.

En el ejemplo, se muestra cómo hacerlo para insertCSS(). El procedimiento para removeCSS() es el mismo.

Manifest V2
chrome.tabs.insertCSS(tabId, injectDetails, () => {
  // callback code
});

En un archivo de secuencia de comandos en segundo plano

Manifest V3
const insertPromise = await chrome.scripting.insertCSS({
  files: ["style.css"],
  target: { tabId: tab.id }
});
// Remaining code. 

En el service worker de extensiones.

Cómo reemplazar las acciones del navegador y de la página con acciones

Las acciones del navegador y de la página eran conceptos separados en Manifest V2. Aunque empezaron con roles distintos, las diferencias entre ellos disminuyeron con el tiempo. En Manifest V3, estos conceptos se consolidan en la API de Action. Esto requiere cambios en tu manifest.json y en el código de extensión que sean diferentes de lo que habrías agregado a la secuencia de comandos en segundo plano de Manifest V2.

Las acciones de Manifest V3 se parecen más a las acciones del navegador. Sin embargo, la API de action no proporciona hide() ni show() como lo hacía pageAction. Si aún necesitas acciones de página, puedes emularlas con contenido declarativo, o bien llamar a enable() o disable() con un ID de pestaña.

Se reemplazaron "browser_action" y "page_action" por "action".

En manifest.json, reemplaza los campos "browser_action" y "page_action" por el campo "action". Consulta la referencia para obtener información sobre el campo "action".

Manifest V2
{
  ...
  "page_action": { ... },
  "browser_action": {
    "default_popup": "popup.html"
   }
  ...
}
Manifest V3
{
  ...
  "action": {
    "default_popup": "popup.html"
  }

  ...
}

Reemplaza las APIs de BrowserAction y pageAction por la API de Action

Si tu manifiesto v2 usaba las APIs de browserAction y pageAction, ahora debes usar la API de action.

Manifest V2
chrome.browserAction.onClicked.addListener(tab => { ... });
chrome.pageAction.onClicked.addListener(tab => { ... });
Manifest V3
chrome.action.onClicked.addListener(tab => { ... });

Cómo reemplazar devoluciones de llamada por promesas

En el manifiesto v3, muchos métodos de la API de la extensión muestran promesas. Una Promise es un proxy o marcador de posición para un valor que muestra un método asíncrono. Si nunca usaste promesas, puedes leer sobre ellas en MDN. En esta página, se describe lo que debes saber para usarlos en una extensión de Chrome.

Para la retrocompatibilidad, muchos métodos continúan admitiendo devoluciones de llamada después de que se agrega la compatibilidad con promesas. Ten en cuenta que no puedes usar ambos en la misma llamada a función. Si pasas una devolución de llamada, la función no mostrará una promesa y, si quieres que se muestre una promesa, no pases una devolución de llamada. Algunas funciones de la API, como los objetos de escucha de eventos, seguirán requiriendo devoluciones de llamada. Para verificar si un método admite promesas, busca la función “Promise” etiqueta en su referencia de API.

Para convertir una devolución de llamada en una promesa, quita la devolución de llamada y controla la promesa que se muestra. El siguiente ejemplo se toma del ejemplo de permisos opcionales, específicamente de newtab.js. La versión de devolución de llamada muestra cómo se vería la llamada de ejemplo a request() con una devolución de llamada. Ten en cuenta que la versión de promesa se podría volver a escribir con async y await.

Devolución de llamada
chrome.permissions.request(newPerms, (granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});
Promesa
const newPerms = { permissions: ['topSites'] };
chrome.permissions.request(newPerms)
.then((granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});

Reemplaza las funciones que esperan un contexto en segundo plano de Manifest V2

Otros contextos de extensiones solo pueden interactuar con los service workers de extensiones mediante el envío de mensajes. Por lo tanto, deberás reemplazar las llamadas que esperan un contexto en segundo plano, específicamente:

  • chrome.runtime.getBackgroundPage()
  • chrome.extension.getBackgroundPage()
  • chrome.extension.getExtensionTabs()

Las secuencias de comandos de tu extensión deben usar el paso de mensajes para comunicarse entre un trabajador de servicio y otras partes de la extensión. Actualmente, esto se puede lograr con sendMessage() y la implementación de chrome.runtime.onMessage en el trabajador del servicio de extensión. A largo plazo, debes planificar reemplazar estas llamadas por postMessage() y el controlador de eventos de mensajes de un trabajador de servicio.

Reemplaza las APIs no compatibles

Los métodos y las propiedades que se indican a continuación deben cambiar en Manifest V3.

Método o propiedad de Manifest V2 Reemplazar por
chrome.extension.connect() chrome.runtime.connect()
chrome.extension.connectNative() chrome.runtime.connectNative()
chrome.extension.getExtensionTabs() chrome.extension.getViews()
chrome.extension.getURL() chrome.runtime.getURL()
chrome.extension.lastError Cuando los métodos devuelven promesas, usa promise.catch().
chrome.extension.onConnect chrome.runtime.onConnect
chrome.extension.onConnectExternal chrome.runtime.onConnectExternal
chrome.extension.onMessage chrome.runtime.onMessage
chrome.extension.onRequest chrome.runtime.onMessage
chrome.extension.onRequestExternal chrome.runtime.onMessageExternal
chrome.extension.sendMessage() chrome.runtime.sendMessage()
chrome.extension.sendNativeMessage() chrome.runtime.sendNativeMessage()
chrome.extension.sendRequest() chrome.runtime.sendMessage()
chrome.runtime.onSuspend (secuencias de comandos en segundo plano) No es compatible con los service workers de extensiones. En su lugar, usa el evento de documento beforeunload.
chrome.tabs.getAllInWindow() chrome.tabs.query()
chrome.tabs.getSelected() chrome.tabs.query()
chrome.tabs.onActiveChanged chrome.tabs.onActivated
chrome.tabs.onHighlightChanged chrome.tabs.onHighlighted
chrome.tabs.onSelectionChanged chrome.tabs.onActivated
chrome.tabs.sendRequest() chrome.runtime.sendMessage()
chrome.tabs.Tab.selected chrome.tabs.Tab.highlighted