Obtaining "this" tab ID from content script in Chrome extension?

JavascriptGoogle Chrome-Extension

Javascript Problem Overview


From a content script, is it possible to access that tab's id?

I want to send a message to the background page from the content script that tells my extension to "do something with this tab" using the chrome.tabs.* API.

A tabID is needed, and there is no point in doing a bunch of logic in the background page to hunt for a tabID when my content script can simply tell it the tabID in the message contents.

Javascript Solutions


Solution 1 - Javascript

Tab id is automatically passed inside MessageSender object:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
	console.log("sent from tab.id=", sender.tab.id);
});

Solution 2 - Javascript

If you want the tabId of yourself (in my case in Content Script) without requiring "tabs" permission, a workaround is to have Content Script send a dummy message to the background script, then have background script respond with sender.tab.id back to the Content Script!

e.g. in content.js:

chrome.runtime.sendMessage({ text: "what is my tab_id?" }, tabId => {
   console.log('My tabId is', tabId);
});

and in background.js:

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    if (msg.text == "what is my tab_id?") {
        sendResponse({tab: sender.tab.id});
     }
});

it's a stupid workaround that worked for me. :)

PS. Oh, if you have tabs permission then you can run this async query very easily:

chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
    var myTabId = tabs[0].id;
    chrome.tabs.sendMessage(myTabId, {text: "hi"}, function(response) {
        alert(response);
    });
});

Solution 3 - Javascript

If you're using Ports for two-way long-lived connections, the second argument in the callback is a Port object, so to access the tab ID is then:

chrome.runtime.onConnect.addListener(port => {
  if (port.name === "foo") {
	port.onMessage.addListener((msg, sendingPort) => {
	  console.log("sent from tab.id=", sendingPort.sender.tab.id);
    });
  }
});

Solution 4 - Javascript

If a content script is injected programmatically, another approach is to store tabId in a global variable:

const injectTabId = (callback) => chrome.tabs.executeScript(
  tabId,
  {code: `window.tabId = ${tabId}`},
  callback
);

const injectFile = () => chrome.tabs.executeScript(
  tabId,
  {file: 'content.js'}
);

injectTabId(injectFile);

In the content script, access it with window.tabId. The variable won't be exposed to page scripts because of content scripts living in an isolated world.

Solution 5 - Javascript

Correction of the selected answer for nowadays:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log("sent from tab.id=", sender.id);
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionvoid.pointerView Question on Stackoverflow
Solution 1 - JavascriptsergView Answer on Stackoverflow
Solution 2 - JavascriptAidinView Answer on Stackoverflow
Solution 3 - JavascriptLounge9View Answer on Stackoverflow
Solution 4 - JavascriptVitaly KuznetsovView Answer on Stackoverflow
Solution 5 - JavascriptPsartekView Answer on Stackoverflow