0

When the user clicks my item in the context menu, I want to send a message from background.js and listen for it in my content script, script.js so that I can run some code to manipulate the DOM.

I copied the example code from the Chrome Message Parsing docs as-is, however I can't get the listener function to trigger.

Here's my manifest.json file:

{
  "manifest_version": 2,

  "name": "Background image downloader",
  "description": "Easily lets you download images that are set as background-image in CSS",
  "version": "0.0.1",

  "permissions": [
    "tabs",
    "contextMenus"
  ],

  "web_accessible_resources": [
    "script.js"
  ],

  "icons": {
    "16": "assets/icon_16.png",
    "48": "assets/icon_48.png",
    "128": "assets/icon_128.png"
  },

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

Here's background.js:

// Inject the content script into each page (script.js)
// http://stackoverflow.com/questions/9515704/building-a-chrome-extension-inject-code-in-a-page-using-a-content-script
var s = document.createElement("script");
s.src = chrome.extension.getURL("script.js");
s.onload = function() {
  this.parentNode.removeChild(this);
};
(document.head || document.documentElement).appendChild(s);

// Handle the click on the context menu
function getClickHandler(info, tab) {
  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
    console.log(tabs[0].id);
    chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
      console.log(response.farewell);
    });
  });
};

// Create the context menu
chrome.contextMenus.create({
  "title" : "Download image",
  "type" : "normal",
  "contexts" : ["all"],
  "onclick" : getClickHandler
});

And here's script.js:

console.log('script.js loaded');

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    debugger // This never gets triggered
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if (request.greeting == "hello")
      sendResponse({farewell: "goodbye"});
  });

What am I doing wrong?

Benjamin Humphrey
  • 3,770
  • 2
  • 23
  • 41
  • 2
    See [extension architecture](https://developer.chrome.com/extensions/overview#arch). You're injecting a script element into the background page. And it's not a [content script](https://developer.chrome.com/extensions/content_scripts). See the [official sample extensions](https://developer.chrome.com/extensions/samples) for the actually working code (filter the list by `executeScript` in particular) – wOxxOm Oct 31 '15 at 12:31

1 Answers1

1

Using sample code without understanding is usually a bad idea.

By creating a <script> tag, you inject code in the current page's context - which happens to be your background page.

  1. If you need your code to execute alongside normal pages, you need Content Scripts.

    The docs describe it in ample detail, but there are 2 broad ways to use them: declare them in the manifest and programmatically inject.

  2. There are limitations to content scripts, in that they can't interact with pages' own code. That's where the snippet you quote comes in - but only from within an already running content script.

    In many cases you don't need that; in any case, code injected this way loses its special extension privileges and can't use onMessage.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206
  • Awesome, thank you. The solution was simply declaring the script in the manifest with `content_scripts` and matching to `"http://*/*", "https://*/*"`. The listener is working now. Thanks for your help! – Benjamin Humphrey Nov 01 '15 at 03:25