How can I found out if Tab is already opened?

I tried somethingl like

 var url = chrome.extension.getURL(link);
 chrome.tabs.query(
  {     
    "url": "app://*/*"
    }, 
    function(tabs) {
    if (chrome.runtime.lastError)
      console.log(chrome.runtime.lasterror);    
    console.log(tabs);
    }
  );

but the tabs.length is 0

Did you try with url of * to see if any tabs are returned?

I can get any web page using match rules but no webextension page.

What I am trying to do is:

when I click a button in popup.html, new page will be open in the case that it is not already open.

I have tried:

(popup.js)

  if ( ( win in my_namespace.tabs ) && !my_namespace.tabs[win] 
    )    
    chrome.tabs.create(
      {"url": url},
      function(tab) {        
      if (browser.extension.lastError )        console.log(browser.extension.lastError);
      my_namespace.tabs[win] = tab.id;
      }
    );

I have popup.html which opens when I click on button and from this popup the new page is opened. The popup.html contains

script src="…/background.js"/script
script src=“popup.js”/script

background.js contains my_namespaces, which should save the window it. But there is a problem, because the tab.id (saved) does not stay in the memory. It looks like the namespace is reinitiated when I click the button again.

Edit:
This script works until I have the popup open. When it is closed, and then opened again, it will reinitiate the namespace and so the value tab id is lost.

Any idea how to solve this?

Edit 2:
Last thing what I tried is to send message to extension to ask for the variable.

  browser.runtime.sendMessage(
    "open", win,
    function(response) {
    var p = 1;
    console.log("response:");
    console.log(response);
    }
  )

and added listener to background.js
chrome.runtime.onMessage.addListener(
function(m, sender
){
var c = 0;
console.log(m);
}
)

But I did not see any output or response. Added a breakpoint at the line with var c = 0; but the program did not break here, maybe an exception “Object” happened. So I have no idea why I cannot send the message.

Edit 4:
I managed to send the message from popup script to extension (background.js)
browser.runtime.sendMessage(“open”, win)
I can recieve the message, but now it is not clear to me how should I send the response containing the variable in the response.

chrome.runtime.onMessage.addListener(  
  function(m, sender){
    var c = 0;
    switch (m){
      case "open":
        console.log("Do some action, print message");
        console.log(m);
        console.log(sender);
      break;    
    }
  }
)

Edit 5:

I have created onMessage listener in background.js:

chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    var c = 0;
    switch (package.message){
      case "open":
        if (package.subject == "tab")
          {
          win = mynamespace.tabs[package.modul];
          result = win ? false : true; 
        chrome.tabs.sendMessage(
          sender.id,
          { message:"tab-response", 
            subject: {id: sender.id },
            modul: package.modul,            
            result: result,
            info: "response to tab exists message"   
          }
         )
          }
      break;    
    }
  }
)

I can send a testing query:

browser.runtime.sendMessage( 
  { message:"open", 
    subject: "tab",
    modul: win,
    sender:{id:0}
  }
  );

This asks of the addon if there is tab id saved for the module which tab I want to create. If it is saved, it should respond with negative result.

Now I could create another listener for the response, but it is not clear to me how to make these things do what I expect.

The query should look like this:

chrome.tabs.query(
  { active: true,  currentWindow: true}, 
    function(tabs) {
      browser.runtime.sendMessage(
        { message:"open", 
          subject: "tab",
          modul: win,
          sender:{id:tabs[0].id}   
        }
        )
    }
  ); 

But what should be in the callback? Just to add the listener and into the listener add function containing chrome.tabs.create?

But this is second time when I need to create runtime.onMessage listener and only one listener can be created, right?

So the tab creation proccess should be handled from background.js, not from popup.js if I understand it. It’s quite complicated

Edit 6:
I think I have almost find how to do it. So I will not send response back but I will create the tab directly from addon as a reaction for the message sent from popup window.

This seems to me as best approach and not like in that poor example where I copied the popup code from.

The current problem however is that the onRemove event is not fired when I close the tab (which I created after the message has been sent).

chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    switch (package.message){
      case "open":
        if (package.subject == "tab")
          {
          win = myNamespace.tabs[package.modul];
          result = win ? false : true; 
          if (result)
            chrome.tabs.create(
              {"url": package.url },
              function(tab) {        
                if (chrome.extension.lastError )
                  console.log(chrome.extension.lastError);
                else
                  myNamespace.tabs[package.modul] = tab.id;
                
                chrome.tabs.onRemoved.addListener(
                    function( tabId, removeInfo )
                    { myNamespace.tab[package.modul] = null; }
                  );
              }
            );
          }
      break;
    }
  }
)
1 Like

Can you tell me why I cannot receive/catch the message sent to tab?

This is my current code:

background.js

chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    switch (package.message){
      case "initiate-page":    
        if (package.subject == "html-add-listeners")
          {
          switch(package.module){
            case "easy_options":
            case "advanced_options":
            case "images_options":
            
            chrome.tabs.sendMessage(
              package.sender.id,
              { message:"initiate-page-response", 
                subject:"accept-namespace", 
                recepient: {id: package.sender.id },
                module: package.module,
                namespace: namespace,
                info: "response to tab exists message"   
              }
             )
            
            break;
            }
          }
      break;
    }
  }
)

Notice I use package.sender.id which is the id of the tab, which initiated first message (request for background to send namespace containing data loaded from storage).

Script of addon page which is loaded when I open html page with addon options:

// First request
chrome.tabs.query(
{ active: true,  currentWindow: true}, 
  function(tabs) {
    browser.runtime.sendMessage(
      { message:"initiate-page", 
        subject: "html-add-listeners",
        module: "easy_options",
        sender:{id:tabs[0].id}   
      }
      )
  }
);

// Receive the message sent from background
chrome.runtime.onMessage.addListener(  
  function(package, sender
    ){
    switch (package.message){
      case "initiate-page-response":    
        if (package.subject == "accept-namespace")
          {
          switch(package.module){
            case "easy_options":
              document.addEventListener('DOMContentLoaded', namespace.easy.restore);
              document.getElementById("easy_form_save").addEventListener("submit", namespace.easy.save);
              document.getElementById("easy_form_restore").addEventListener("submit", namespace.easy.restore);
              document.getElementById("easy_form_remove_item").addEventListener("submit", namespace.easy.remove_profiles);
              document.getElementById("easy_form_remove_profiles").addEventListener("submit", namespace.easy.remove_profiles);
              document.getElementById("list").addEventListener("change", namespace.easy.restoreDefault);
            break;
            }
          }
      break;
    }
  }
)

In the last listener I can see the message which I have send to addon background; this one is not processed. But I need to receive the message send from background and this one did not come.

1 Like

I wanted to do the same thing, here is what I ended up with after a couple attempts thst worked in Chrome but didn’t in Firefox:

In the background script:

function openOptions() {
    const window = chrome.extension.getViews({ type: 'tab', }) // tabs.query({ url, }) won't accept extension urls
    .find(_=>_.location.pathname === '/ui/home/index.html');   // so use extension.getViews (which only works for tabs from your own extension)
    window
    ? chrome.tabs.update(window.tabId, { active: true, })      // window.focus() desn't work in Firefox
    : chrome.tabs.create({ url: chrome.extension.getURL('ui/home/index.html#options'), }); // (tab not open)
}

and in a script included by ‘/ui/home/index.html’ (to get the window.tabId property):

chrome.tabs.getCurrent(tab => window.tabId = tab.id);

Now you just need to call openOptions (from a messaage handler or directly (ether via chrome.extension.getBackgroundPage() (which throws if your panel is attached to a private window), or you could propably just load the function directly into the panel))

I have found working solution. Not so hard. The only thing one needs to do is remember that the page was opened or closed. This happens on background script.

But I have different problem now which is why the functions are lost from the message object when I send message from background to page. See my thread:

https://discourse.mozilla-community.org/t/sending-function-through-message-fails-is-it-another-bug/9869/1

Edit:
Your url has to be match pattern, not url