user2954587
user2954587

Reputation: 4871

Chrome extension callback after tab is active

I have an extension where I'd like to focus tabs at different times for a few seconds.

I am able to change tabs, however, I'd like to pass in a callback function for when the tab is focused.

I've tried passing in a function to sendMessage but it appears to execute right away (seen below). How can I pass in a callback function to be executed in the content script once the tab is focused?

content_script.js

chrome.runtime.sendMessage("Do something", function(resp) {
    console.log(resp)
})

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
  chrome.windows.update(sender.tab.windowId, {"focused": true}, function(window){ });
  chrome.tabs.update(sender.tab.id, {"active": true}, function(tab){
    // callback function
  });
});

Upvotes: 1

Views: 1377

Answers (1)

woxxom
woxxom

Reputation: 73806

Return true from onMessage listener to keep the response channel open, then call sendResponse from a chrome API callback. Note, chrome API callbacks always run asynchronously, i.e. after the main function completes.

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  let callbackCounter = 2;

  chrome.tabs.update(sender.tab.id, {active: true}, function (tab) {
    // this callback runs after the parent function has finished
    if (--callbackCounter === 0) {
      sendResponse({foo: 'bar'});
    }
  });

  chrome.windows.update(sender.tab.windowId, {focused: true}, function (window) {
    // this callback runs after the parent function has finished
    if (--callbackCounter === 0) {
      sendResponse({foo: 'bar'});
    }
  });

  // keep the response channel open 
  return true;
});

In modern browsers this is solved usually with Promise API.
You can use it with Chrome API by loading Mozilla WebExtension polyfill.

browser.runtime.onMessage.addListener((request, sender) => {
  return Promise.all([
    browser.tabs.update(sender.tab.id, {active: true}),
    browser.windows.update(sender.tab.windowId, {focused: true}),
  ]).then(() => {
    // .........
    return {foo: 'bar'};
  });
});

The polyfill also enables you to use await/async syntax:

browser.runtime.onMessage.addListener(async (request, sender) => {
  await Promise.all([
    browser.tabs.update(sender.tab.id, {active: true}),
    browser.windows.update(sender.tab.windowId, {focused: true}),
  ]);
  return {foo: 'bar'};
});

Upvotes: 3

Related Questions