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 la extensión. Esta sección es para 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 el Manifiesto V3, executeScript() se traslada 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 en el código real.
Para el método executeScript(), necesitas lo siguiente:
- El permiso
"scripting". - Permisos de host o el permiso
"activeTab"
El método scripting.executeScript() es similar a cómo funcionaba con tabs.executeScript(). Existen algunas diferencias.
- Mientras que el método anterior solo podía tomar un archivo, el nuevo puede tomar un array de archivos.
- También pasas un objeto
ScriptInjectionen lugar deInjectDetails. Existen varias diferencias entre ambos. Por ejemplo, ahoratabIdse pasa como miembro deScriptInjection.targeten lugar de como argumento de método.
En el ejemplo, se muestra cómo hacerlo.
async function getCurrentTab() {/* ... */} let tab = await getCurrentTab(); browser.tabs.executeScript( tab.id, { file: 'content-script.js' } );
En un archivo de secuencia de comandos en segundo plano
async function getCurrentTab() let tab = await getCurrentTab(); browser.scripting.executeScript({ target: {tabId: tab.id}, files: ['content-script.js'] });
En el service worker de la extensión
Reemplaza tabs.insertCSS() y tabs.removeCSS() por scripting.insertCSS() y scripting.removeCSS()
En el Manifiesto 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 el permiso
"activeTab"
Las funciones de la API de scripting son similares a las de tabs. Existen algunas diferencias.
- Cuando llamas a estos métodos, pasas un objeto
CSSInjectionen lugar deInjectDetails. - Ahora,
tabIdse pasa como miembro deCSSInjection.targeten lugar de como argumento de método.
En el ejemplo, se muestra cómo hacerlo para insertCSS(). El procedimiento para removeCSS() es el mismo.
browser.tabs.insertCSS(tabId, injectDetails, () => { // callback code });
En un archivo de secuencia de comandos en segundo plano
const insertPromise = await browser.scripting.insertCSS({ files: ["style.css"], target: { tabId: tab.id } }); // Remaining code.
En el service worker de la extensión
Reemplaza las acciones del navegador y de la página por acciones
Las acciones del navegador y las acciones de página eran conceptos independientes en el Manifiesto V2. Aunque comenzaron con roles distintos, las diferencias entre ellos disminuyeron con el tiempo. En el Manifiesto V3, estos conceptos se consolidan en la API de Action. Esto requiere cambios en tu manifest.json y en el código de la extensión que es diferente del que habrías colocado en tu secuencia de comandos en segundo plano de Manifest V2.
Las acciones en 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 llamar a enable() o disable() con un ID de pestaña.
Reemplaza "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".
{ ... "page_action": { ... }, "browser_action": { "default_popup": "popup.html" } ... }
{ ... "action": { "default_popup": "popup.html" } ... }
Reemplaza las APIs de browserAction y pageAction por la API de action
Cuando tu Manifest V2 usaba las APIs de browserAction y pageAction, ahora deberías usar la API de action.
browser.browserAction.onClicked.addListener(tab => { ... }); browser.pageAction.onClicked.addListener(tab => { ... });
browser.action.onClicked.addListener(tab => { ... });
Reemplaza las devoluciones de llamada por promesas
En el Manifiesto V3, muchos métodos de la API de extensiones devuelven promesas. Una Promise es un proxy o marcador de posición para un valor que devuelve un método asíncrono. Si nunca usaste Promises, puedes obtener información sobre ellas en MDN. En esta página, se describe lo que necesitas saber para usarlos en una extensión de Chrome.
Para mantener la retrocompatibilidad, muchos métodos siguen 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 devolverá una promesa. Si quieres que se devuelva 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 etiqueta "Promise" en su referencia de la 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 de la muestra 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 la muestra a request() con una devolución de llamada. Ten en cuenta que la versión de la promesa se podría reescribir con async y await.
browser.permissions.request(newPerms, (granted) => { if (granted) { console.log('granted'); } else { console.log('not granted'); } });
const newPerms = { permissions: ['topSites'] }; browser.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 extensión solo pueden interactuar con los service workers de extensión a través del paso de mensajes. Por lo tanto, deberás reemplazar las llamadas que esperan un contexto en segundo plano, específicamente:
browser.runtime.getBackgroundPage()browser.extension.getBackgroundPage()browser.extension.getExtensionTabs()
Las secuencias de comandos de tu extensión deben usar el paso de mensajes para comunicarse entre un service worker y otras partes de la extensión. Actualmente, esto se puede lograr usando sendMessage() y, luego, implementando browser.runtime.onMessage en el service worker de tu extensión. A largo plazo, deberías planificar el reemplazo de estas llamadas por postMessage() y un controlador de eventos de mensajes de un service worker.
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 |
|---|---|
browser.extension.connect() |
browser.runtime.connect() |
browser.extension.connectNative() |
browser.runtime.connectNative() |
browser.extension.getExtensionTabs() |
browser.extension.getViews() |
browser.extension.getURL() |
browser.runtime.getURL() |
browser.extension.lastError |
Cuando los métodos devuelvan promesas, usa promise.catch(). |
browser.extension.onConnect |
browser.runtime.onConnect |
browser.extension.onConnectExternal |
browser.runtime.onConnectExternal |
browser.extension.onMessage |
browser.runtime.onMessage |
browser.extension.onRequest |
browser.runtime.onMessage |
browser.extension.onRequestExternal |
browser.runtime.onMessageExternal |
browser.extension.sendMessage() |
browser.runtime.sendMessage() |
browser.extension.sendNativeMessage() |
browser.runtime.sendNativeMessage() |
browser.extension.sendRequest() |
browser.runtime.sendMessage() |
browser.runtime.onSuspend (secuencias de comandos en segundo plano) |
No se admite en los service workers de extensiones. En su lugar, usa el evento de documento beforeunload. |
browser.tabs.getAllInWindow() |
browser.tabs.query() |
browser.tabs.getSelected() |
browser.tabs.query() |
browser.tabs.onActiveChanged |
browser.tabs.onActivated |
browser.tabs.onHighlightChanged |
browser.tabs.onHighlighted |
browser.tabs.onSelectionChanged |
browser.tabs.onActivated |
browser.tabs.sendRequest() |
browser.runtime.sendMessage() |
browser.tabs.Tab.selected |
browser.tabs.Tab.highlighted |