Stop event listener - javascript

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);
}
});
}
});

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.

Chrome extension, message to content script of newly created tab only works with alert

I'm creating a Chrome extension that takes the url from the current tab and puts it in a field in a newly opened tab.
The field in the new tab seems to only be filled when there's an alert before sending the message. Probably because of asynchronicity, howewer I do sendMessage in the callback function of the creation of the tab.
Here is my background.js:
function sendMessage(msg) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, msg);
});
}
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.getSelected(null, function(tab) {
var tabURL = tab.url;
chrome.tabs.create({url: "https://..<url>.."}, function(tab) {
alert(''); //<- it only seems to work with this alert in it.
sendMessage(tabURL);
});
});
});
And my content.js:
chrome.runtime.onMessage.addListener(
function(request, sender) {
document.getElementById('field').value = request;
});
Found the solution, thanks to abraham:
Made tabURL a global var:
var tabURL = '';
Removed callback function from chrome.tabs.create:
chrome.tabs.create({url: "https://..<url>.."});
Added onUpdated listener to background.js
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
sendMessage(tabURL);
});

Chrome extension: How to sendMessage form background to background?

My background listener is
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse)
In chrome.contextMenus.onClicked listener, I want to use the message system,I call
chrome.runtime.sendMessage
in the listener, but it's not works.
So, how can I sendMessage from background to background ?
Messages dispatched by a page are not received by the same page.
If you want to be able to re-use the onMessage listener, put it in a separate function. For example:
function alwaysDoSomething() {
console.log('Done something!');
}
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
alwaysDoSomething();
});
chrome.contextMenus.onClicked.addListener(function(info, tab) {
alwaysDoSomething();
});
There is an undocumented method that can be used to manually trigger the events. It is undocumented, so use it at your own risk!
chrome.contextMenus.onClicked.addListener(function(info, tab) {
var message = 'whatever';
var sender = {tab: null, id: chrome.runtime.id};
var sendResponse = function() {};
chrome.runtime.onMessage.dispatch(message, sender, sendResponse);
});
I think you should use chrome.extension.onRequestExternal or chrome.extension.onConnectExternal

Establish a communication link between content script and background page

Developing a chrome extension using javascript is one of my university projects.
I don't know how to establish a communication link between content script and background page using messaging. I need some help in this establishing the connection
background.html
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "getHTML"}, function(response) {
console.log(response.data);
});
});
content_script.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "getHTML")
sendResponse({data: document.getElementById('header').innerHTML});
else sendResponse({});
});
A few major issues:
You're depending on some element on the page having the ID header. Such IDs are at the discretion of the site designer, so very few pages actually do have that (including Google). Maybe go for something a little more universal, like the title of the page (document.title).
What does "the extension button" mean? If it means a browser action, that's a part of your extension, so you're correct in wanted to send something from the background script. This is also an easier case, as it's probable that (aside from the issue above of no Google pages having an element of ID header), you're just not capturing the browser action click event. If it's some injected button, however, it's the other way around.
What you want (browser action version)
background.html (inline):
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, { method: "getHTML"}, function(response) {
console.log(response.data);
});
});
});
content_script.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method === "getHTML") {
sendResponse({data: document.title});
} else {
sendResponse({});
}
});
What you might want (injected button click version)
background.html:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method === "getHTML") {
console.log(request.data);
}
});
content_script.js:
function buttonClick() {
chrome.extension.sendRequest({method: "getHTML", data: document.title});
}
Code for response to comment below
Very important recommendation: Chrome's developer reference is probably one of the friendliest out there. If you want to know what parts of the chrome.* API are available, start there.
function getHtml(tabId) {
chrome.tabs.sendRequest(tabId, { method: "getHTML"}, function(response) {
console.log(response.data);
});
}
// Note that this will only work once a tab has loaded
chrome.tabs.onSelectionChanged.addListener(function(tabId) {
getHtml(tabId);
});
// This fires the first time a page is loaded
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo) {
if (changeInfo.status === "complete") {
getHtml(tabId);
}
});
Code for second response to comment below
background.html
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method === "getHTML") {
console.log(request.data);
}
});
content_script.js
document.addEventListener("keypress", function(e) {
chrome.extension.sendRequest({method: "getHTML", data: e.which});
});

Categories