sending message to chrome extension from a web page

I want to send message from the console of the random web page to my chrome extension. chrome.extension.sendMessage doesn't seem to work.


Solution 1:

According to the official docs you should use postMessage in the sender and message event listener in the receiver.

Here is an example:

Your website's page.html

var data = { type: "FROM_PAGE", text: "Hello from the webpage!" };
window.postMessage(data, "*");

Content script: (injected using chrome.tabs.executeScript(tabid, {code:...)

window.addEventListener("message", function(event) {
    // We only accept messages from ourselves
    if (event.source != window)
        return;

    if (event.data.type && (event.data.type == "FROM_PAGE")) {
        console.log("Content script received message: " + event.data.text);
    }
});

Here page.html (which is not a part of the extension) posts messages to itself, which are intercepted and inspected by the content script. The reverse is possible through similar means.

To pass from content script to extension, you will have to use one of the available message-passing techniques.

It looks complicated and it is somewhat complicated but all this mumbo-jumbo is very secure.

Solution 2:

Here's a quote from the latest http://developer.chrome.com/extensions/messaging.html, It's much simpler to support this kind of feature now, here's how:

Sending messages from web pages

Similar to cross-extension messaging, your app or extension can receive and respond to messages from regular web pages. To use this feature, you must first specify in your manifest.json which web sites you want to communicate with. For example:

"externally_connectable": {
  "matches": ["*://*.example.com/*"]
}

This will expose the messaging API to any page which matches the URL patterns you specify. The URL pattern must contain at least a second-level domain - that is, hostname patterns like "", ".com", ".co.uk", and ".appspot.com" and <all_urls> are prohibited. From the web page, use the runtime.sendMessage or runtime.connect APIs to send a message to a specific app or extension. For example:

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
  function(response) {
    if (!response.success)
      handleError(url);
  });

From your app or extension, you may listen to messages from web pages via the runtime.onMessageExternal or runtime.onConnectExternal APIs, similar to cross-extension messaging. Only the web page can initiate a connection. Here is an example:

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.url == blacklistedWebsite)
      return;  // don't allow this web page access
    if (request.openUrlInEditor)
      openUrl(request.openUrlInEditor);
  });

Solution 3:

So to elaborate, a more concreate example: An issue with chrome.runtime.sendMessage(...) style is that you have to specify the pag you're on as externally_connectable which doesn't take a global wildcard like "https:///". So if you want that ability, you have to use the postMessage style communication. Capture the message from the window into the contentscript, then from the contentscript, you can send it elsewhere (if desired, like to the background.js etc.)

So in the normal web page, or in injected source that you embed into the normal page, from your contentscript.js, send a message like this:

window.postMessage({ type: "FROM_PAGE_TO_CONTENT_SCRIPT", 
     text: "Hello from the webpage!" }, "*");

ex, you could add it to a button like this:

document.getElementById("theButton").addEventListener("click",
    function() {
       window.postMessage({ type: "FROM_PAGE_TO_CONTENT_SCRIPT", 
                            text: "Hello from the webpage!" }, "*");
}, false);

Then to capture it in the contentscript.js and "send it on" to the rest of the extension, the only caveat is that you only want to "select" messages that seem to be ones that you care about:

window.addEventListener("message", function(event) {
  // We only accept messages from this window to itself [i.e. not from any iframes]
  if (event.source != window)
    return;

  if (event.data.type && (event.data.type == "FROM_PAGE_TO_CONTENT_SCRIPT")) {        
    chrome.runtime.sendMessage(event.data); // broadcasts it to rest of extension, or could just broadcast event.data.payload...
  } // else ignore messages seemingly not sent to yourself
}, false);

Solution 4:

You can switch to the JS execution context of your content script using the <page context> menu at the bottom of a page’s developer JS console, then use chrome.runtime.sendMessage and other chrome.* APIs just as you would within the content script.

enter image description here

Solution 5:

In addition to @hewigovens , I don't have enough points to comment... I'm explaining @renatoargh and @sbichenko If sending message from a default web page -

1) the webpage needs to be quoted in the manifest. e.g.:

"externally_connectable": {
  "matches": ["http://abcde/abcde/main.aspx*"]
}

2) the background.js (background page) excepts the call with onMessageExternal e.g. (calling an extension):

var host_name = "com.my_chrome_extension.com";
 chrome.runtime.onMessageExternal.addListener(function(message, sender, sendResponse) {
    chrome.runtime.sendNativeMessage(host_name, {"run":message});
    sendResponse({"success": "success"});
    return true;
});