I've got a very odd problem. I have an extension that takes a screenshot of webpages. I created it using this extension as a reference. It works perfectly and the world is happy.
The extension communicates back and forth with a content script and it uses deprecated APIs to do so. In an effort to keep the extension from using outdated code, I went ahead and made the following replacements:
chrome.tabs.sendRequest(...) -> chrome.tabs.sendMessage(...)
chrome.extension.onRequest(...) -> chrome.runtime.onMessage(...)
chrome.extension.sendRequest(...) -> chrome.runtime.sendMessage(...)
Doing that breaks the extension and it no longer works. If I use the deprecated code, it all works fine again.
I did some tracking and discovered that the extension breaks at the following code:
CONTENT SCRIPT
chrome.runtime.sendMessage(sender.id, data, function(captured) {
window.clearTimeout(cleanUpTimeout);
console.log("came back from extension...");
if (captured) {
// Move on to capture next arrangement.
processArrangements(); //function defined elsewhere
} else {
// If there's an error in popup.js, the response value can be
// undefined, so cleanup
cleanUp(); // function defined elsewhere
}
});
EXTENSION
chrome.runtime.onMessage.addListener(function(message, sender, cb){
appendLog("received message from content script. callback is " + cb);
if (message.msg === 'capturePage') {
capturePage(message, sender, cb);
} else {
console.error('Unknown message received from content script: ' + message.msg);
}
});
function capturePage(data, sender, cb) {
... // some code omitted for clarity
chrome.tabs.captureVisibleTab(
null, {format: 'png', quality: 100}, function(dataURI) {
if (dataURI) {
var image = new Image();
image.onload = function() {
screenshot.ctx.drawImage(image, data.x, data.y);
//appendLog("calling callback function. callback is: " + cb);
cb(true); // **callback isn't called on content script**
};
image.src = dataURI;
}
});
}
I've omitted some code for clarity and the missing code is irrelevant. Let me explain what you see up there:
On the extension, inside the capturePage function, the line cb(true) executes. I can confirm it does because I'm able to see the "calling callback function" that comes right before it. However, the callback code on the content script does NOT run. Again, I can confirm this because I don't see the "came back from extension" message.
Here's the bizarre part: if I call cb(true) BEFORE I call chrome.tabs.captureVisibleTab(), the callback code on the content script DOES execute normally. That means chrome.tabs.captureVisibleTab() is interfering with the execution of cb(true) on the content script somehow. Maybe a port is closed when I call captureVisibleTab() - I'm not sure. The fact of the matter is that cb(true) will not execute on the content script after calling captureVisibleTab() but it will execute if I call it before.
On the extension, I tried storing the callback function, cb, in a variable outside capturePage() and then calling another function which would then call cb... but that doesn't work either.
I added the "" permission to my extension thinking maybe that would change things, but no. That changes nothing.
Again, if I replace the 4 lines of code where the deprecated APIs are, my extension works as expected. Thus, the problem is a combination of sendMessage() and captureVisibleTab(). There is no syntax error and I'm not leaving anything out. If I omit the call to captureVisibleTab(), the cb call will execute normally on the content script. What on earth???
How bizarre is that? I don't want to leave those deprecated API calls there. But then again, what could possibly be preventing the call back code to execute on the content script? I'm set on thinking the port is closed/replaced when we call captureVisibleTab(), but I'm not really sure and I've investigating it further.
I came across this online but I'm not sure if it's related to my issue. I also couldn't find anything similar here on stackoverflow and hence I created this question. Can anyone shed some light on this?
Thanks