2

I know message passing is used for the purpose but somehow it is not working on onClick event of my background page. I am getting following exception:

Error in event handler for (unknown): TypeError: Cannot read property 'data' of undefined
    at chrome-extension://aimjdbbnlgjodealdppjdpligkbjbmmb/background.js:27:31
    at disconnectListener (extensions::messaging:338:9)
    at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
    at Event.dispatchToListener (extensions::event_bindings:386:22)
    at Event.dispatch_ (extensions::event_bindings:371:27)
    at Event.dispatch (extensions::event_bindings:392:17)
    at dispatchOnDisconnect (extensions::messaging:293:27) 

Code given below:

manifest.json

{
    "manifest_version": 2,
    "name" : "My Ext",
    "description" : "XXX",
    "version" : "1.0",
    "permissions": [
        "tabs"
  ],
    "content_scripts" : [{
        "matches" : ["http://example.com/"],
        "js" : ["jquery.js","script.js"]
    }],
"background":{
  "scripts": ["jquery.js","background.js"]
},
    "browser_action": {
        "default_title": "XX"
      }
}

dashboard.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script src="jquery.js"></script>
    <script src="background.js"></script>
  </head>
  <body>
      <form>
      <textarea id="search"></textarea>
      <input id="button" type="button" value="Search" />
      </form>
  </body>
</html>

Script.js

var currentURL = document.location.href;
$(document).ready(function(){

    $("#button").click(function()
    {
        alert( "Handler for .click() called." );
    });
});

chrome.extension.onMessage.addListener(function(msg, sender, sendResponse)
{
    alert(msg);
    if (msg.method == "getHTML")
      sendResponse({data: "Welcome from Content Script"});
});

background.js

$(document).ready(function()
{
    chrome.browserAction.onClicked.addListener(function(activeTab){
  var loaderURL = chrome.extension.getURL("dashboard.html");
  _tab = activeTab;
  chrome.tabs.create({ url: loaderURL });
});
    $("#button").click(function()
    {
        chrome.extension.sendMessage({method: "getHTML",param:"myParam"}, function(response)
        {
                alert(response.data);
        });
    });

});

I can't use chrome.tabs.sendMessage because onClick event I am unable to find tab Id

Volatil3
  • 14,253
  • 38
  • 134
  • 263
  • I don't see any manifest or any info on how the above files are used (nor do I feel like guessing)... – gkalpak Jan 04 '14 at 07:50
  • @ExpertSystem pardon, it got skippd. Question updated – Volatil3 Jan 04 '14 at 08:07
  • So where is `dashboard.html` used ? – gkalpak Jan 04 '14 at 08:15
  • it is a background page. on clicking button, it loads dashboard.html which has a SEARCH button. upon clicking this it should send TEXTAREA content to content script – Volatil3 Jan 04 '14 at 08:24
  • Sorry, I just took a closer look at `background.js`. – gkalpak Jan 04 '14 at 08:27
  • My approach might be wrong. All I want to send text area values to content script. Then those values will be used to parse data from DOM – Volatil3 Jan 04 '14 at 08:30
  • I don't know if this is the root of the problem, but you are using the deprecated `chrome.extension.sendMessage/onMessage`. You should be using `chrome.runtime.sendMessage/onMessage` instead. Besides, it is a bad practice to use your `background.js` as script in another file (other than the background page). `dashboard.html` is **not** a background page, but a view (there is only up to one background page per extension - the one declared in manifest). – gkalpak Jan 04 '14 at 08:38
  • chrome.runtime always says undefined "data" – Volatil3 Jan 04 '14 at 08:39
  • @ExpertSystem I try to implement your approach, may it work: http://stackoverflow.com/questions/19758028/chrome-extension-get-dom-content – Volatil3 Jan 04 '14 at 08:43
  • Good choice ! My solutions always work :) – gkalpak Jan 04 '14 at 08:48
  • Possible duplicate of http://stackoverflow.com/questions/19758028/chrome-extension-get-dom-content. – gkalpak Jan 04 '14 at 08:50
  • @ExpertSystem **chrome.tabs.sendMessage(tab.id, { text: "report_back" }, doStuffWithDOM);** I can't pass tab.id in *$("#button").click(function()** method – Volatil3 Jan 04 '14 at 08:52
  • @ExpertSystem getting **Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval ** on dashboard.html – Volatil3 Jan 04 '14 at 08:58
  • What version of jquery are you using ? – gkalpak Jan 04 '14 at 11:16
  • 1.9. it's not issue of jquery – Volatil3 Jan 04 '14 at 12:44
  • Are you using `eval` somewhere ? Could you post the actual code somewhere, so we can take a look ? – gkalpak Jan 04 '14 at 12:50
  • All of my code given in original question. Nothing left. I guess *script* tag in dashboard.html causing this issue. See above – Volatil3 Jan 04 '14 at 12:52
  • The script tags as they appear in your question should not violate any policy, so something is different than in your question. Please, post the updated code. – gkalpak Jan 04 '14 at 13:01
  • @ExpertSystem this was the code I used while made a post. You may test it too. – Volatil3 Jan 04 '14 at 13:18

1 Answers1

2

First, you need to replace the deprecated chrome.extension.onMessage with chrome.runtime.onMessage in script.js.

The main problem is that to send messages to content scripts you need to use chrome.tabs.sendMessage (which also requires to know the tab-ID).
An easy way to get this working, is to pass the tab-ID as a query parameter, when opening a dashboard.html view, e.g. dashboard.html?tabId=XX (see the modified background.js below).

background.js:

var queryStr = '?tabId=';
var loaderURL = chrome.extension.getURL('/popup/popup.html') + queryStr;
$(document).ready(function () {
    chrome.browserAction.onClicked.addListener(function (tab) {
        chrome.tabs.create({ url: loaderURL + tab.id });
    });

    if (location.search && (location.search.indexOf(queryStr) === 0)) {
        var tabID = parseInt(location.search.substring(queryStr.length));
        $('#button').click(function () {
            chrome.tabs.sendMessage(tabID, {
                method: 'getHTML',
                param:  'myParam'
            }, function (response) {
                if (chrome.runtime.lastError) {
                    alert('ERROR: ' + chrome.runtime.lastError.message);
                } else {
                    alert(response.data);
                }
            });
        });
    }
});

As shown above, it is always a good idea to check for chrome.runtime.lastError in chrome API callbacks to see if anything went wrong. In your case, you would see an error stating there is no receiving end, which would point to the right direction.

gkalpak
  • 47,844
  • 8
  • 105
  • 118
  • OK I test it. Do I need to make any changes at content_script end? – Volatil3 Jan 04 '14 at 14:28
  • Just the changes I mention in my answer (i.e. use `chrome.runtime.onMessage` instead of `chrome.extension.onMessage`). – gkalpak Jan 04 '14 at 14:33
  • Thanks! it worked! but.. not sure i ask here or create another Question.. what if background.js is at receiving end? How do I accept data from content script on some buttin click event similar to one mentioned above? – Volatil3 Jan 04 '14 at 17:44
  • The documentation is pretty clear on how to perform Message Passing (I suggest a closer look). For listening on bg-page use `chrome.runtime.onMessage`. – gkalpak Jan 04 '14 at 17:50
  • In that case, I suggest posting a new question with the relevant code (and problem description). – gkalpak Jan 04 '14 at 17:57
  • check please: http://stackoverflow.com/questions/20924782/receiving-message-from-chrome-extensions-content-script-to-background-js-file-o – Volatil3 Jan 04 '14 at 18:15