4

I dont really unterstand how the Chrome Extension API works. It was a rough to understand how the background.js and the content.js works, but my current Problem is, that the function insertCSS(); seems to need the tabId, even if the official documentation says that its optional.

So, none of the Answers on this plattform could help me, because I dont even understand the Concept of the whole API.

So can anybody explain me, why something like this is not possible?

var tabInfo = chrome.tabs.getCurrentTab();

var id = tabInfo.tabId;
  • The `tabId` is indeed optional _if_ you're operating on the current visible tab. There's not enough information in the question right now to understand what is the logic you're trying to implement. – Xan Apr 12 '19 at 21:29
  • Answering _strictly_ the "why" question, "because the API does not return a value, it's [asynchronous](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call)". `getCurrentTab` is also not exactly what you expect. To answer the question in a useful way, you need to explain how this code gets triggered. – Xan Apr 12 '19 at 21:33
  • This Code is made for a special Website, that should change the stylesheets when you click on a button on that Website. That Button is implemented within the Extention. The Button are made up in the content.js when the Website is fully loaded. Then there is an eventListener that send a message to the background.js –  Apr 12 '19 at 22:24
  • So I presume that some event in the page is caught by the content script, which then messages the background, correct? – Xan Apr 12 '19 at 22:26
  • Correct. Editet my Comment. –  Apr 12 '19 at 22:27
  • Then you should use the fact that onMessage event already has the tab ID information. – Xan Apr 12 '19 at 22:28
  • Perfect. I will try to find more Information about that. But tomorrow, thank you very much by now. –  Apr 12 '19 at 22:31

1 Answers1

8

There are several questions to be answered here.

Literal question

So can anybody explain me, why something like this is not possible?

var tabInfo = chrome.tabs.getCurrentTab();

Short answer: because most of the Chrome API does not return a value; it is asynchronous, meaning that some other component of Chrome will work on getting the answer while JS execution resumes.

A comprehensive overview of JS asynchronicity can be read at this canonical question.

There are two ways to deal with it:

  • Use callbacks, and be aware that the actual callback execution happens after the rest of the calling code.
  • Use async/await and/or Promises. The WebExtension polyfill can help with that, but it's outside the scope of the question.

Question in title

Simplest Way to get the current Tab Id?

or "why chrome.tabs.getCurrentTab won't help you".

chrome.tabs.getCurrentTab() returns the tab ID of the calling page. See the docs.

This is of limited utility: only extension pages (and not content scripts) can call this API.

Extension pages are:

  • background (no tab ID),
  • popup (no tab ID),
  • options page (it's complicated as it's embedded in a Chrome page),
  • "other" extension pages opened in a visible tab (here, it works as expected).

It's not your use case, as established in the comments.

The actual way to get the current active tab is chrome.tabs.query() with the query {active: true, currentWindow: true}, but keep on reading.

Actual question you're having

As reconstructed from the comments, here's the actual scenario you're having:

I have an event in a content script. I need to call the tabs.insertCSS API, so I'm messaging the background page to do it for me. How do I get the tabId for this call?

Well, the key here is to take a closer look at the runtime.onMessage event listener signature:

The callback parameter should be a function that looks like this:

function(any message, MessageSender sender, function sendResponse) {...};

What's a MessageSender?

An object containing information about the script context that sent a message or request.

tabs.Tab (optional) tab
The tabs.Tab which opened the connection, if any. This property will only be present when the connection was opened from a tab (including content scripts), and only if the receiver is an extension, not an app.

[...]

Jackpot. We're sending the message from a content script, and the listener is handed the sender.tab information "for free". We just need a quick detour into tabs API docs to see what a Tab contains, and we have it:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  chrome.tabs.insertCSS(sender.tab.id, {/*...*/});
});

Misconception

my current Problem is, that the function insertCSS() seems to need the tabId, even if the official documentation says that its optional

It doesn't. If you call it omitting the tabId, which makes the details object the first argument, then Chrome will assume you want the "the active tab of the current window".

It may seem that this doesn't work if you're trying to execute it in the Dev Tools window for the background page. That's because in this instance there's no such tab. The current window is the one you're putting the console command in. So what the call does without the tabId is very sensitive to what actually is the current window.

It may also be the case that you don't have the permissions to inject in the current active tab, that would also fail.

Generally, it pays to be specific with the tab ID, it removes uncertainty about the logic of the extension.

Xan
  • 74,770
  • 16
  • 179
  • 206
  • Thank you very much, that helped me alot. I now understood how I can get the TabId and solved that specific problem. The extension works fine in Firefox, but not in Chrome. The Callback returns in both Browsers a succesfull result, but the stylesheets were only changed in firefox. –  Apr 13 '19 at 10:40
  • 1
    Make a separate question with minimal code path that does this. – Xan Apr 13 '19 at 10:45
  • Thank you so much for this good answer. I like how you both answered the question they _thought_ they were asking and the question they **should have** asked. I DDGd for "chrome extension get current tab id" and wound up here, and would have been totally lost had you not seen through what the asker should have asked and answered that instead :) – Max Coplan Jul 16 '23 at 00:10