Chrome Extension Message Passing - Code included - javascript

I have a contentscript called file.js that creates variable "found". I want to send the values of varibale "found" to a textbox in popup.html
In file.js (I know varible found is working, tested using an alert).
chrome.extension.sendRequest({foundlinks: found}, function(response) {
console.log(response);
});
In Popup.html:
function pulllinks(){
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
document.getElementById("box").value = request.foundlinks;
sendResponse({});
});
And on the form in popup.html:
<input type = "button" onclick="pulllinks();" name = "box" id="box" value = "Grab Links From Page" />
However, its not doing anything. Any ideas?
Thanks!

You need to be sending requests in the opposite direction - from popup to content script:
popup.html:
function pulllinks(){
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {cmd: "findLinks"}, function(response) {
document.getElementById("box").value = response.foundlinks;
});
});
}
file.js:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if(request.cmd == "findLinks") {
//calculate "found" value and send it back
sendResponse({foundlinks: found});
}
});

First of all, your listener for onRequest should exist from the start, so move it outside of the pulllinks function. Secondly, how are you making sure that your sendRequest is being fired while the popup is open?

Related

Difficulty passing messages between background and content script in chrome extension

I'm attemtping to send a message from the content script to the background script, and send a response in return.
This is what I've got in my background script:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log("Message received");
if(request.activeStatusRequest == "disable"){
sendResponse({activeStatusUpdate: "disable"});
}else if(request.activeStatusRequest == "enable"){
sendResponse({activeStatusUpdate: "enable"});
}
return true;
});
This is what I've got in my content script:
printReviews.onclick = function(element) {
if(printReviews.classList.contains("activeButton")){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(
tabs[0].id,
{code: `${injectionLiteralGETURL}`}
);
});
toggleClasses(printReviews, "activeButton", "inactiveButton");
chrome.runtime.sendMessage({activeStatusRequest: "disable"}, function(response){
console.log("response received");
console.log(response.activeStatusUpdate);
});
}
else {
toggleClasses(printReviews, "inactiveButton", "activeButton");
chrome.runtime.sendMessage({activeStatusRequest: "enable"}, function(response){
console.log("response received");
console.log(response.activeStatusUpdate);
});
}
};
The rest of the above code works as expected, except that the none of the console logs in the content script run. The console log in the background script does run, however.
Anyone got any ideas as to what I've done wrong?
If you want to try another method, you could try to add a listener in the content script
Content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log("Message received from background", response.type, response.activeStatusUpdate);
switch(request.type){
case 'SomeFirstAction'
break;
case 'SomeSecondAction'
break;
}
});
Background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log("Message received");
if(request.activeStatusRequest == "disable"){
sendMessageToCurrentTab({type: 'SomeFirstAction', activeStatusUpdate: "disable"});
}else if(request.activeStatusRequest == "enable"){
sendMessageToCurrentTab({type: 'SomeSecondAction', activeStatusUpdate: "enable"});
}
// return true; -> not needed with that method
});
function sendMessageToCurrentTab(message){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, message);
}
}
To have played with callbacks between popup/background/content-script, I prefer just play with messages,because when using sendResponse, the manner it works, it open a port to communicate, but if something change (tab close, popup close), you will have an error because the port will be closed too.
Using the 'Full send message manner', the background need to clearly target the receiver tab.
I also recommand you to use a type or some unique action attribute, because all listener will listen to all action. It will identify the action and it's purpose.
Here I just used a switch in the content script, but the background could use the same logic.
Maybe it's not the greatest way of doing things, but it works well for me.
Hope this can help you

Chrome extension create tab and send msg to it

I tried different things, but it doesn't work.
In my popup.html i've created a button. When i click it, i wan't to create a new tab and send to it a message. Here is the code:
$("#openLink").click(function () {
chrome.tabs.create({url: 'http://jquery.com'}, function (tab) {
console.log(tab.id);
alert(tab.id);
chrome.tabs.sendMessage(tab.id, 'hello');
});
});
And in the content script i try to use this:
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
alert('message received');
});
But it doesn't alert me nothing.
Please help.

Stop event listener

I made a button which openning new page in new tab for example https://google.com. And I'm sending a message to the background script to start taking the URL of new opened page. The problem is that I don't know how to stop the listener after retrieving the URL. So it's continue the execution even after I closed that tab.
Popup.js
$('#click').click(function(e)
{
chrome.tabs.create({url: 'https://google.com'});
chrome.runtime.sendMessage({greeting: "googleisopened"}, function(response) {
console.log(ok);
});
});
Background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "googleisopened")
{
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
alert(changeInfo.url);
});
}
});
I think you're insterested in this function http://api.jquery.com/off/
It removes all of the events from the object so in your case you could just plug it anywhere in your click event like this:
$(this).off('click');
// Or like this if you want to be specific
$('#click').off('click');
Thanks to everyone who tried to help me. I found a solution by myself.
Instead of using listener I started to use tabs.getSelected to retrieve page URL only when needed (not in cycle as in onUpdated.addListener).
So the background script will be next:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "googleisopened")
{
chrome.tabs.getSelected(null, function(tab)
{
chrome.tabs.onUpdated.addListener(mylistener);
function mylistener (tabId, changeInfo, tab)
{
alert(changeInfo.url);
chrome.tabs.onUpdated.removeListener(mylistener);
}
});
}
});

How to run callback function from content script after loading page ? chrome extension

I want to run a callback function from content script after tab loading new page .
Here is my code :
content_script.js
chrome.runtime.onMessage.addListener(function(request, sender, callback) {
if (request.id == "content_script") {
// open google.com
chrome.runtime.sendMessage({
"id" : "openUrl",
"url" : "https://google.com"
}, function(response) {
});
// call background script
// go to the claim code page
chrome.runtime.sendMessage({
"id" : "background"
}, function() {
alert("test");
});
}
});
background.js
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.id == "openUrl") {
var tabId = sender.tab.id;
var url = msg.url;
openUrl(tabId, url);
} else if (msg.id == "background") {
setTimeout(function() {
sendResponse();
}, 5000);
}
});
function openUrl(tabId, url) {
chrome.tabs.update(tabId, {
url : url,
active : false
}, function() {
console.log("open tab url callback");
});
};
I also uploaded the source code to google drive, you can download it using the bellow link :
https://drive.google.com/open?id=15zSn40z4zYkvCZ8B-gclzixvy6b0C8Zr
as you can see the alert test don't show !
However if I remove the code which open new url , then alert ("test") appear !
I am not sure why ! but it looks like javascript lost the reference to the call back function when I open new url .
How can I solve the problem ? what's the correct way ?
Thank you
The sendResponse function becomes invalid after the message callback returns, unless you return true from the event listener to indicate you wish to send a response asynchronously. (https://developer.chrome.com/extensions/runtime#event-onMessage)
Add return true; in background.js to make this handler asynchronous.
Now you get an error Attempting to use a disconnected port object in the sendResponse(); call of background.js, and yes, that's a result of the page navigating away and losing the context that the content script was running in.
There's no way to make this work: The context in which you wanted to call alert() simply doesn't exist anymore.
Try using chrome.tabs.sendMessage instead. But this means you have to set up the listener at the top level, and not inside of any callback. Message passing is hard.

Chrome Extension Development : Message passing Problem

Having a problem while passing messages using content scripts in Google chrome extension dev
My Code structure looks like this:
popup.html:
var oList;
function getHTML()
{
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {action:"getHTML"}, function handler(response) {
oList = response.dom;
});
});
alert("oList = "+oList );
}
and my content Script looks like this:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if(request.action == "getHTML"){
sendResponse({dom: document.getElementsByTagName("HTML").length});
}
});
When I debug my code by putting a breakpoint at "oList = response.dom;" in my popup.html, i get the
right value set from the content script. But while executing the extension, the "alert("oList = "+oList );" code
from the popup.html seems to be executing first before it goes to the server.. And therefore, its value is
not being set.. Can somebody tell me if I am wrong somewhere ?
Most Chrome API methods are asynchronous. It means that when you are calling them the script doesn't wait for their response and simply continues executing. If you want to execute something on response you should put it inside callback function:
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {action:"getHTML"}, function handler(response) {
oList = response.dom;
alert("oList = "+oList );
});
});

Categories