4

My overall goal was to take a screenshot via the background page using:

http://developer.chrome.com/extensions/tabs.html#method-captureVisibleTab

and pass it to the content script so I can use the page's HTML DOM to analyze the screenshot and cut it up the way I would like.

However, I can't seem to pass the dataUrl back to the content script with Message Passing:

http://developer.chrome.com/extensions/messaging.html

I tried JSON.stringify() but to no avail.

This works perfectly fine:

background.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        sendResponse({imgSrc:'hello'});
    }
);

I switch the code to this and nothing gets through:

background.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        chrome.tabs.captureVisibleTab(
            null,
            {},
            function(dataUrl)
            {
                sendResponse({imgSrc:dataUrl});
            }
        )
    }
);

My only proof that the background page is actually taking a screenshot is that I can do

chrome.tabs.captureVisibleTab(null,{},function(dataUrl){console.log(dataUrl);});

and I see

"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAA....etc..."

logged in background.html, which is valid

My question is: How can I send this URL to the content script?

I would prefer not to do all the logic on the background page which can't control anything on the actual visible page.

Xan
  • 74,770
  • 16
  • 179
  • 206
neaumusic
  • 10,027
  • 9
  • 55
  • 83
  • Please refrain from removing the actual question from the question. Add your solution as an answer instead. – Xan Jan 21 '15 at 08:12
  • Voting to close as a duplicate of now-canonical question: http://stackoverflow.com/questions/20077487/chrome-extension-message-passing-response-not-sent – Xan Jan 21 '15 at 08:13

1 Answers1

11

Use chrome.tabs.sendMessage and make sure to return true, not the event listener

background page:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        chrome.tabs.captureVisibleTab(
            null,
            {},
            function(dataUrl)
            {
                sendResponse({imgSrc:dataUrl});
            }
        );

        return true;
    }
);

content script

chrome.runtime.sendMessage({msg: "capture"}, function(response) {
  console.log(response.dataUrl);
});
neaumusic
  • 10,027
  • 9
  • 55
  • 83
Andrey
  • 722
  • 2
  • 8
  • 17
  • ok, I've updated the code. Now background page sends data url back to message from content script. Does it look right now? – Andrey Sep 14 '13 at 07:46
  • CODE IS NOW WORKING! You almost had it right but you're missing the semicolon after chrome.tabs.captureVisibleTab(); and yes apparently I need to return true for some reason?! Do you know why? – neaumusic Sep 16 '13 at 22:10
  • 6
    From [documentation](http://developer.chrome.com/extensions/runtime.html#event-onMessage): SendResponse _function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously_ – Andrey Sep 17 '13 at 14:19
  • last comment about `return true` is *super important*. I spent hour on this stupid nuance. I forgot how JS can be a nightmare... – roy650 Jul 23 '23 at 19:24