Search code examples
javascriptoperafirefox-addon-webextensions

How to communicate from a background to a sidebar script in Firefox WebExtensions? (or vice versa)


I am migrating my extension from the SDK to WebExtensions, and I can not find the way of communicating between a background script and the sidebar. The idea is to pass the text the user highlights and some extra info when he clicks in a context menu. I need to copy this selection in the "selected-text" input, but I can not manipulate the DOM of the sidebar from the script...: (

browser.contextMenus.create({
  id: "save-highlighted-data",
  title: browser.i18n.getMessage("save-data"),
  contexts: ["all"],
  onclick: function(info,tab){ 

    //I got the highlighted data
    console.log("Selected text: " + info.selectionText);

    browser.sidebarAction.setPanel({ 
      panel: browser.extension.getURL("/sidebar/annotation.html")   
    }).then(function(){ 

      //In this context, "this" = the chrome window. But I can not change the document
      //  of the sidebar
      //console.log("window", this.document.querySelector("#selected-text"));
    }); 
  },
  command: "_execute_sidebar_action" //This toggles the sidebar 
});

Any idea? I checked the sidebar examples at the GitHub repo, but they just open a sidebar with not more communication that the sidebar toggle action ("_execute_sidebar_action")


Solution

  • Extension's background, content, sidebar, etc scripts can communicate with each other using runtime.sendMessage() and runtime.onMessage.addListener()

    AFAIK, there isn't any direct connection between sidebar and content DOM at the moment.

    You can use tabs.query() to get the Active Tab (which is the visible tab) or any other tab

    function logTabs(tabs) {
      for (let tab of tabs) {
        // tab.url requires the `tabs` permission
        console.log(tab.url);
      }
    }
    
    function onError(error) {
      console.log(`Error: ${error}`);
    }
    
    var querying = browser.tabs.query({currentWindow: true, active: true});
    querying.then(logTabs, onError);
    

    Or

    chrome.tabs.query({currentWindow: true, active: true}, function (tabs) {
      // tabs[0] is the active tab
    });
    

    You can then use tabs.executeScript() with the tabId you got from tabs.query() (i.e. tabs[0].id) to inject JavaScript code into the page (DOM) and interact with its DOM.