Transición al espacio de nombres del navegador

A partir de Chrome 148, todas las APIs de Chrome Extension están disponibles en el espacio de nombres browser, además del espacio de nombres chrome existente. Por ejemplo, browser.tabs.create({}) y chrome.tabs.create({}) son equivalentes.

El espacio de nombres está disponible dondequiera que puedas llamar a las APIs de extensión, incluidos los secuencias de comandos de contenido, los service workers y los documentos fuera de pantalla. Apunta a los mismos objetos de la API que chrome, por lo que chrome.tabs === browser.tabs.

El espacio de nombres browser surge del trabajo del Grupo de la Comunidad de WebExtensions (WECG), un grupo de la comunidad de W3C en el que los proveedores de navegadores colaboran en estándares de extensión compartidos. El espacio de nombres chrome no desaparecerá; ambos espacios de nombres seguirán funcionando.

Cómo decidir si se adopta el espacio de nombres del navegador

Si usas webextension-polyfill, ve a Nota para usuarios de polyfill antes de cambiar cualquier otra cosa. La respuesta es diferente para ti.

Si compilas una extensión nueva, establece minimum_chrome_version en "148" y usa browser de forma incondicional. Puedes dejar de leer aquí. El resto de esta sección es para las extensiones existentes que deciden cómo adoptar.

Verifica en qué versiones de Chrome están tus usuarios

Si tienes una extensión existente, verifica qué versiones de Chrome ejecutan tus usuarios antes de cambiar. Chrome se actualiza automáticamente, pero algunos usuarios inhabilitan las actualizaciones y otros usan dispositivos más antiguos que no pueden ejecutar la versión más reciente. Confirma con tus propios datos de estadísticas. Si aún no tienes configuradas las estadísticas yet, consulta Supervisa el rendimiento de tu extensión con Google Analytics 4 para comenzar.

A partir de ahí, elige una ruta de acceso:

Adopta de forma incondicional

Establece minimum_chrome_version en tu manifiesto y usa browser de forma incondicional. No se necesita protección del entorno de ejecución:

{
  "minimum_chrome_version": "148"
}

Usa un lanzamiento en etapas cuando aumentes minimum_chrome_version. Si algo sale mal, puedes revertir tu extensión en Chrome Web Store.

Usa la protección del entorno de ejecución

Agrega el siguiente fragmento al principio del código de inicio de tu extensión antes de hacer referencia a browser en cualquier otro lugar:

if (!globalThis.browser) {
  globalThis.browser = chrome;
  // Consider firing an analytics event here to measure how often
  // your users hit this fallback path.
}

Esto convierte a browser en un alias para chrome en versiones anteriores, por lo que el resto del código puede usar browser de forma incondicional.

Nota para usuarios de polyfill

Si tu extensión usa webextension-polyfill, se convierte en una operación no operativa en Chrome 148 y versiones posteriores. El polyfill omitió el ajuste cuando browser ya estaba definido, suponiendo que el navegador host ya había proporcionado la API.

Por este motivo, se revirtió un intento anterior de enviar el espacio de nombres en Chrome 136: con browser recién definido, el polyfill dejó de ajustar, pero el browser.runtime.onMessage de Chrome aún no admitía objetos de escucha que mostraran promesas, que el polyfill había estado proporcionando. Se interrumpieron las extensiones que dependían de ese patrón. Chrome 148 envía el espacio de nombres y los objetos de escucha onMessage nativos que muestran promesas juntos para evitar esa brecha.

Puedes quitar la dependencia de polyfill una vez que tu base de usuarios se haya mudado a Chrome 148.

Otras funciones

Respuestas asíncronas en runtime.sendMessage

En Chrome 148, los objetos de escucha runtime.onMessage pueden mostrar una Promise directamente para enviar una respuesta asíncrona. Esto funciona si lo llamas con chrome.* o browser.*.

Anteriormente, la única forma de responder de forma asíncrona era mostrar un literal true desde el objeto de escucha y llamar a sendResponse más tarde:

// Old pattern - requires returning true to keep the channel open
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  fetch('https://example.com')
    .then(response => sendResponse({ statusCode: response.status }));

  return true; // keeps the message channel open for the async response
});

Ahora puedes mostrar una Promise (o usar una función async) directamente:

// New pattern - return a promise or use async/await
browser.runtime.onMessage.addListener(async (message, sender) => {
  const response = await fetch('https://example.com');
  return { statusCode: response.status };
});

El patrón return true sigue funcionando, por lo que no es necesario cambiar el código existente.