14

I am writing a Chrome plugin with a content script and a background script, and I am trying to make the two communicate.

In my content script, I am doing

chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
      console.log(response.farewell);
});

and in my background script, I am doing

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

My manifest looks like this:

{
    "manifest_version": 2,
    "name": "Tesing Phase",
    "version": "1.0",
    "background": {
        "persistent": false,
        "scripts": ["bgscript.js"]
    },
    "content_scripts": [{
        "js": ["contentscript.js"],
        "all_frames": true,
        "run_at" : "document_start",
        "matches": ["*://*/*"]
    }],
    "web_accessible_resources": ["script.js"]
}

When I run my plugin, I get the following error:

Uncaught TypeError: Object #<Object> has no method 'sendMessage' 

I tried logging chrome.runtime, and there was no method sendMessage. I am using version 25.0 of Chromium on Ubuntu. I tried using sendRequest as well, but it said it's depreciated and sendMessage should be used.

Can anyone point me out what I am missing here? Are there any permissions needed for this to work?

Kevin Ji
  • 10,479
  • 4
  • 40
  • 63
Jiby Jose
  • 3,745
  • 4
  • 24
  • 32

1 Answers1

36

chrome.runtime.sendMessage / onMessage (and other related events/methods such as connect) were introduced in Chrome 26.

If you want to write an extension which is compatible with Chrome 20 - 25, use chrome.extension.sendMessage.

A way to achieve optimal compatibility is to define the chrome.runtime methods yourself. For example, run the following code before the rest of your code (background/content script):

if (!chrome.runtime) {
    // Chrome 20-21
    chrome.runtime = chrome.extension;
} else if(!chrome.runtime.onMessage) {
    // Chrome 22-25
    chrome.runtime.onMessage = chrome.extension.onMessage;
    chrome.runtime.sendMessage = chrome.extension.sendMessage;
    chrome.runtime.onConnect = chrome.extension.onConnect;
    chrome.runtime.connect = chrome.extension.connect;
}

Then you can just use the latest API format:

// Bind event:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    // Do something
});

// Send message:
chrome.runtime.sendMessage({greeting: 'hello'});

If you feel uncomfortable with modifying methods on the chrome.runtime object, you can use the following approach instead:

var runtimeOrExtension = chrome.runtime && chrome.runtime.sendMessage ?
                         'runtime' : 'extension';

// Bind event:
chrome[runtimeOrExtension].onMessage.addListener(
  function(message, sender, sendResponse) {
    // Do something
});

// Send message:
chrome[runtimeOrExtension].sendMessage({greeting: 'hello'});
gignu
  • 1,763
  • 1
  • 14
  • 24
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • 2
    Thanks a lot.It worked using chrome.extension.I think this info is missing in the google chrome dev pages. – Jiby Jose Mar 30 '13 at 14:33
  • this looks great, but is this methodology still valid for chrome versions up to 31? or would it need to be adapted? and does anyone know if the old deprecated message passing methods have been dropped entirely from the latest version of chrome – user280109 Jan 03 '14 at 17:22
  • @user280109 It's still valid. Though you could also just use `chrome.runtime.` without any compatibility layers, because hardly anyone uses Chrome 25- any more thanks to Google's auto-updater. – Rob W Jan 03 '14 at 17:23
  • @robw thanks man. btw i found out that some users are still using chrome25 as some linux distributions only have up to chromium25 in their repositories, i know its an edge case scenario, but something to think about i guess. with linux i think the autoupdating isnt so automatic, when using repositories. – user280109 Jan 04 '14 at 19:48
  • btw shouldnt the following lines: chrome.runtime.onMessage = chrome.extension.onMessage; chrome.runtime.sendMessage = chrome.extension.sendMessage; be this instead: chrome.runtime.onMessage = chrome.extension.onRequest; chrome.runtime.sendMessage = chrome.extension.sendRequest; – user280109 Jan 04 '14 at 21:49
  • 1
    @user280109 No. `onRequest`/`sendRequest` was used in Chrome 19 and earlier. See http://stackoverflow.com/a/11811936/938089 for exact details. – Rob W Jan 04 '14 at 21:51
  • another question, are the following 2 lines required, even if you dont directly call the onconnect or connect methods? chrome.runtime.onConnect = chrome.extension.onConnect; chrome.runtime.connect = chrome.extension.connect; the reason i ask is, i have excluded those lines, because i wasnt actually using those function calls. but now i am having issues with my background page freezing up and not returning messages. i wonder if this would cause it. im having problems debugging the frozen background page, when i try and debug it the window comes up but its completely blank – user280109 Feb 12 '14 at 19:48
  • These lines are not needed if you don't use them. Your issue is probably caused by something else. – Rob W Feb 12 '14 at 21:16