En mi extensión de Chrome, tengo una página emergente y un script de fondo.
De forma predeterminada, cuando hago clic en el icono de la extensión en dos ventanas diferentes, se abre una ventana emergente en ambas ventanas. Quiero limitar la cantidad de ventanas emergentes abiertas por la extensión para que sea como máximo una a la vez.
Así es como el escenario completo que estoy tratando de crear:
Window A abrió una ventana emergente.Window B abrió una ventana emergente, en cuyo caso, la Window A se cerrará.Window C , vaya a 2 , pero esta vez Window A<-Window B y Window B<-Window CSé que se creó una ventana emergente porque tengo una conexión de puerto simple que se invoca en el inicio de la ventana emergente. Por lo tanto, el fondo es, en teoría, consciente de todas las ventanas emergentes que se crean, es decir, ese es el código que ejecuto en la ventana emergente para conectarme:
const port = chrome.runtime.connect({ name: 'popup-communications' });Intenté resolver el problema de 3 maneras, todas fallaron.
Intento 1 Mantenga presionada la última ventana emergente que se conectó. Si aparece uno nuevo, cierre el antiguo antes de guardar el nuevo. Use chrome.extension.getViews para obtener el nuevo puerto. Me imaginé que esto funcionaría, pero los clics rápidos en el ícono de la extensión (para invocar browserAction) hacen que este estado emergente sea confuso.
let popUp; chrome.runtime.onConnect.addListener(function connect(port) { if (port.name === 'popup-communications') { // attempt 1 if (popUp) { popUp?.close?.(); popUp = null; console.log('removed old pop up'); } [popUp] = chrome.extension.getViews({ type: 'popup', }); }); Intento 2 Cierre todas las ventanas emergentes que recibió de chrome.extension.getView , excepto la última. El problema con este enfoque es que chrome.extension.getView no garantiza ningún orden.
let popUp; chrome.runtime.onConnect.addListener(function connect(port) { if (port.name === 'popup-communications') { // attempt 2 const popUps = chrome.extension.getViews({ type: 'popup', }); console.log(popUps); for (let i = 0; i < popUps.length - 1; i++) { popUps[i].close(); } }); También experimenté con chrome.browserAction.disable y chrome.browserAction.enable . Esta solución mantiene, de hecho, mantiene 1 ventana emergente en todo momento, pero quiero que la ventana emergente esté disponible cada vez que haga clic en el ícono de la extensión, y esto no sucederá con este enfoque (en su lugar, tendré que encontrar la ventana relevante con esta ventana emergente)
¿Hay alguna manera de lograr lo que estoy tratando de hacer aquí?
Pude lograr este comportamiento de la siguiente manera.
El fondo escucha las ventanas emergentes de conexión.
Cuando se conecta una ventana emergente, transmitirá un mensaje a todas las ventanas emergentes abiertas para que se cierren. Tenga en cuenta que este mensaje no se envía a través del puerto ya que la conexión del puerto no se transmite.
Debería existir una forma de optimizar, ya que como máximo se puede abrir otra ventana emergente, pero eso lo dejaré para otro momento y prefiero no crear variables globales.
chrome.runtime.onConnect.addListener(function connect(port) { if (port.name === 'popup-communications') { port.onMessage.addListener(function (msg) { if (msg.here) { const activeTabId = msg.here; // broadcast close request chrome.runtime.sendMessage({closeUnmatched: activeTabId}); } }); } });Realice una búsqueda de su ID de pestaña.
Agregue un detector de mensajes para saber cuándo cerrar. Si el mensaje para cerrar no coincide con la identificación de la pestaña actual, la ventana emergente se cerrará. window.close() es suficiente para cerrar una ventana emergente.
"anuncie" en segundo plano que la ventana emergente está lista enviando la identificación de la pestaña sobre el puerto.
async function getCurrentTab() { let queryOptions = {active: true, currentWindow: true}; let [tab] = await chrome.tabs.query(queryOptions); return tab; } function addListener(myTabId) { chrome.runtime.onMessage.addListener(function (msg) { if (msg.closeUnmatched && msg.closeUnmatched !== myTabId) { window.close(); } }); } (async function constructor() { const port = chrome.runtime.connect({name: 'popup-communications'}); // whoami lookup const {id: myTabId} = await getCurrentTab(); // add handler to self-close addListener(myTabId); // tell background I'm here port.postMessage({here: myTabId}); // do whatever with port.. }());Supongo que los pasos 1-3 se pueden realizar más rápido que el usuario cambiando pestañas/ventanas para activar otra ventana emergente. La conexión del puerto estaba complicando las cosas, pero lo dejé en la respuesta, ya que es posible que tenga un caso de uso para ello.