Send data between content-script/background

2.3k views Asked by At

This is my current project:

manifest.json:

{
  "name": "Sample Commands Extension",
  "description": "Press Ctrl+Shift+U to send an event (Command+Shift+U on a Mac).",
  "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/commands",
  "manifest_version": 2,
  "version": "1.0",

  "background": {
    "scripts": ["background.js"]
  },

  "commands": {
    "toggle-feature": {
      "suggested_key": { "default": "Alt+Shift+U" },
      "description": "Send a 'toggle-feature' event to the extension"
    }
  }
}

background.js:

    /**
     * Returns all of the registered extension commands for this extension
     * and their shortcut (if active).
     *
     * Since there is only one registered command in this sample extension,
     * the returned `commandsArray` will look like the following:
     *    [{
     *       name: "toggle-feature",
     *       description: "Send a 'toggle-feature' event to the extension"
     *       shortcut: "Ctrl+Shift+U"
     *    }]
     */
    var gettingAllCommands = browser.commands.getAll();
    gettingAllCommands.then((commands) => {
      for (command of commands) {
        console.log(command);
      }
    });

    /**
     * Fired when a registered command is activated using a keyboard shortcut.
     *
     * In this sample extension, there is only one registered command: "Ctrl+Shift+U".
     * On Mac, this command will automatically be converted to "Command+Shift+U".
     */
    browser.commands.onCommand.addListener((command) => {
      console.log("onCommand event received for message: ", command);
      // send to core.js the command?
    });

core.js:

browser.runtime.onMessage.addListener(request => {
  alert(request.greeting);
});

it works with my keyboard shortcut, I get that message I'm logging. My question is: how can I send the command to the core.js, and how can I make it work just with the active current tab one, and not with all the opened ones? The files are on the same folder.

1

There are 1 answers

6
Makyen On BEST ANSWER

You can send a message from the background script to content scripts in a tab by using tabs.sendMessage() (Chrome docs), to which you must provide the tab ID of the tab you wish to receive the message. You can not broadcast a message to all tabs with one API call. To send to only the tab that is the active tab in the current window, you first have to find out which tab that is. You can do that with tabs.query({active:true,currentWindow:true}...) (Chrome docs).

The code below will send a message to the content script in the current tab. The callback version works in either Firefox or Chrome, the Promises version only works in Firefox (Chrome doe not implement browser.*).

Using callbacks (chrome.*, can use in Chrome or Firefox):

/*                   Callback based version (chrome.*)
 * Send a message to the current tab. Arguments are the same as chrome.tabs.sendMessage(),
 *   except no tabId is provided.
 *
 * sendMessageToCurrentTab(
 *     message (any) message to send
 *     options (optional object) same as tabs.sendMessage():'frameId' prop is the frame ID.
 *     callback (optional callback for response)
 * )
 */
function sendMessageToCurrentTab(){
    var args = Array.prototype.slice.call(arguments); //Get arguments as an array
    chrome.tabs.query({active:true,currentWindow:true},function(tabs){
        args.unshift(tabs[0].id); //Add tab ID to be the new first argument.
        chrome.tabs.sendMessage.apply(this,args);
    });
}

Using Promises (browser.*, can use in Firefox):

/*                  Promises based version (browser.*)
 * Send a message to the current tab. Arguments are the same as browser.tabs.sendMessage(),
 *   except no tabId is provided.
 *
 * sendMessageToCurrentTab(
 *     message (any) message to send
 *     options (optional object) same as tabs.sendMessage():'frameId' prop is the frame ID.
 * )
 */
function sendMessageToCurrentTab(){
    var args = Array.prototype.slice.call(arguments); //Get arguments as an array
    return browser.tabs.query({active:true,currentWindow:true}).then(function(tabs){
        args.unshift(tabs[0].id); //Add tab ID to be the new first argument.
        return browser.tabs.sendMessage.apply(this,args);
    });
}

Need to inject the content script first

However, prior to being able to send a message to a content script, the content script needs to be injected in the page. You will need to inject the content script by either using a content_scripts entry in your manifest.json or using chrome.tabs.executeScript(). For example, you could inject the script and send the message (after the script is injected) using:

chrome.tabs.executeScript({
    file:'core.js'
}, function(){
    sendMessageToCurrentTab("test");
});