Problem - Multiple instances of Extension launched.

176 views
Skip to first unread message

Adrian Marin

unread,
Aug 8, 2023, 7:03:39 PM8/8/23
to Chromium Extensions
Good night,

Sometimes totally ramdomly the extension just PopUp another instance, so I end with multiple extensions launched. How can avoid this? I've tryed many different things and looks like no one of these works.

Gonna post my code here:

chrome.action.onClicked.addListener(function (listener) {
  openExtension();
});

let queue = [];
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  switch (request.type) {
    case "extension-connect":
      queue.push({ type: "new-pairing", message: request.message, origin: request.origin });
      openExtension();
      break;
    case "extension-send":
      queue.push({ type: "send-transaction", message: request.message, origin: request.origin });
      openExtension();
      break;
    case "wallet-ready":
      queue.forEach(queueElem => {
        chrome.runtime.sendMessage({ type: queueElem.type, message: queueElem.message, origin: queueElem.origin });
      })
      break;
  }

  sendResponse();
});

let popupTabId = null;
let popupWindowId = null;

function openExtension() {
  console.log('tabId: ', popupTabId)
  if (!popupTabId) openTabPopup();
  else {
    chrome.tabs.get(popupTabId, function (tab) {
      console.log('Tab info: ', tab)
      if (chrome.runtime.lastError || !tab) {
        console.log('Chrome error: ', chrome.runtime.lastError)
        popupTabId = null;
        openTabPopup();
      } else {
        chrome.tabs.update(tab.id, { active: true });
        chrome.windows.update(popupWindowId, { focused: true })
      }
    });
  }
}

function openTabPopup() {

  var options_url = chrome.runtime.getURL('index.html');
  chrome.tabs.create(
    {
      url: options_url,
      active: false
    },
    function (tab) {
      popupTabId = tab.id;

      chrome.windows.create({
        tabId: tab.id,
        type: 'popup',
        focused: true,
        width: 600,
        height: 850,
        left: 1000,
        top: 0
      }, (window) => {
        popupWindowId = window.id;
      });

    }
  );

}

wOxxOm

unread,
Aug 9, 2023, 1:21:22 AM8/9/23
to Chromium Extensions, Adrian Marin
The problem is most likely your global variables like popupTabId as they don't survive when the service worker is terminated after 30 seconds of inactivity. The solution is not to rely on them and instead find the window by its URL.

Here's an example that requires "tabs" in manifest.json's "permissions". This permission adds a highly misleading installation warning that the extension can read navigation history (it can't, at least in the common understanding of the word, but it can observe navigated URLs and page titles/icons).

async function openExtension() {
  const url = chrome.runtime.getURL('index.html');
  const [tab] = await chrome.tabs.query({url: url + '*'});
  if (tab) {
    await chrome.windows.update(tab.windowId, { focused: true });
  } else {
    await chrome.windows.create({
      url,
      type: 'popup',

      width: 600,
      height: 850,
      left: 1000,
      top: 0,
    });
  }
}


Here's an example without this warning:

async function openExtension() {
  const url = chrome.runtime.getURL('index.html');
  const client = (await clients.matchAll()).find(c => c.url.startsWith(url));
  if (client) {
    client.postMessage('focus');
  } else {
    await chrome.windows.create({
      url,
      type: 'popup',

      width: 600,
      height: 850,
      left: 1000,
      top: 0,
    });
  }
}


but you'll need to add a listener in index.html's script (for example in index.js):

self.onmessage = async e => {
  if (e.data === 'focus') {
    const tab = await chrome.tabs.getCurrent();
    await chrome.windows.update(tab.windowId, { focused: true });
  }
};

Adrian Marin

unread,
Aug 9, 2023, 3:09:22 AM8/9/23
to Chromium Extensions, wOxxOm, Adrian Marin
Good morning,

Thanks you very much!

It worked but we have needed to put the index.html without the <extensionId>/index.html in the create otherwise It wasn't working because It didn't assign the url to the tab and never could find in the query. Does it makes sense?

Regards.

wOxxOm

unread,
Aug 9, 2023, 3:19:42 AM8/9/23
to Chromium Extensions, Adrian Marin, wOxxOm
It's best if you show the code to illustrate your question because your original code was correct in that regard as well the code in my answer.

Adrian Marin

unread,
Aug 9, 2023, 3:34:10 AM8/9/23
to Chromium Extensions, wOxxOm, Adrian Marin
Sure!!

async function openExtension__() {
  const url = chrome.runtime.getURL('index.html');
  console.log('url', url)
  const [tab] = await chrome.tabs.query({ url: url + '/*' });
  if (tab) {
    await chrome.windows.update(tab.windowId, { focused: true });
  } else {
    await chrome.windows.create({
      url: 'index.html',

wOxxOm

unread,
Aug 9, 2023, 4:07:05 AM8/9/23
to Chromium Extensions, Adrian Marin, wOxxOm
There's a mistake/typo in your code: an extra "/" that wasn't present in my example. It should be just '*' and not '/*'.

Adrian Marin

unread,
Aug 9, 2023, 4:26:27 AM8/9/23
to Chromium Extensions, wOxxOm, Adrian Marin
The solution 1 that you provide works well for us, but in the solution 2 we have tryed but we can't get any value with  await clients.matchAll()we always get as response []. Also the extension never gets focused since we never send the event to the listener in the Index.

wOxxOm

unread,
Aug 9, 2023, 7:48:05 AM8/9/23
to Chromium Extensions, Adrian Marin, wOxxOm
Try matchAll({includeUncontrolled: true})

wOxxOm

unread,
Aug 9, 2023, 11:22:48 AM8/9/23
to Chromium Extensions, wOxxOm, Adrian Marin
I don't know why `clients` doesn't work for you without seeing the full extension, it may be a bug in Chrome. There's also one thing missing in my example: checking for the popup's existence while it's being opened. You can do it via a global variable, which is fine in this case as it'll be used for less than a second.

Here's a very basic example:

let openingPopup;

async function openExtension() {
  if (openingPopup) return;
  openingPopup = true;

  // ...... the main code

  openingPopup = false;
}

Reply all
Reply to author
Forward
0 new messages