I want to be able to communicate tabs with an extension and store values in variables and share these values between tabs, how can I do this?
Note: This is a tutorial question, read more at:
I want to be able to communicate tabs with an extension and store values in variables and share these values between tabs, how can I do this?
Note: This is a tutorial question, read more at:
Note: link with full functional example to use / test:
For something to run you should use background.js
in your extension and store the values, or to be more precise:
"background": {
"scripts": [
"background.js"
]
},
background works as a back-end server, it keeps running constantly, even without open tabs of a specified site in manifest.json
All tabs generated and that their pages are specified in the manifest.json can access the same execution of background.js
, as there will only be one, that is, for each extension, a process that is running background.js
is generated. p>
Having understood this let's go to the tabs, when the extension starts (at the start of the browser) you will be able to communicate with it, each opened new tab / window can communicate with background.js
To communicate a flap with the background you will need to use:
chrome.runtime.sendMessage
And to receive the request in the background you will need to use:
chrome.runtime.onMessage.addListener
However for this you will need to inject scripts in the pages specified in content_scripts.matches
, for example, create a script called inject.js
in the add-on folder and manifest.json
leave something like this:
"background": {
"scripts": [
"background.js"
]
},
"content_scripts": [{
"matches": [
"*://superuser.com/*",
"*://serverfault.com/*",
"*://stackoverflow.com/*",
"*://*.superuser.com/*",
"*://*.serverfault.com/*",
"*://*.stackoverflow.com/*"
],
"js": [
"inject.js"
]
}],
"permissions": [
"tabs"
]
In the above example, I set the following% pages to the%:
Now in the contents of inject.js
add this:
(function (browser) {
var valorX = 0, valorY = 0, valorZ = 0; //Os valores vão ficar salvos nessas variaveis
browser.runtime.onMessage.addListener(function(request, sender, sendFeedback) {
switch (request) {
case "acaoX":
sendFeedback("Foi chamado a ação X");
valorX++; //Incrementa em valorX toda vez que chamar acaoZ
break;
case "acaoY":
sendFeedback("Foi chamado a ação Y");
valorY++; //Incrementa em valorY toda vez que chamar acaoZ
break;
case "acaoZ":
sendFeedback("Foi chamado a ação Z");
valorZ++; //Incrementa em valorZ toda vez que chamar acaoZ
break;
//Será usado para ver na aba quantas ações de cada foram chamadas
case "total":
sendFeedback({
"x": valorX,
"y": valorY,
"z": valorZ
});
break;
}
});
})(browser||chrome); //compatibilidade para firefox e chrome
Now in background.js
add this:
(function (browser) {
function requisitarAcao(acao, callback) {
if (browser && browser.runtime && browser.runtime.sendMessage) {
browser.runtime.sendMessage(acao, function (response) {
callback(response);
});
}
}
var gerado = false;
//Cria 3 botões no final da página
function gerarBotoes() {
if (gerado) return; //Impede que gere mais de uma vez
gerado = true;
var btnX = document.createElement("button"),
btnY = document.createElement("button"),
btnZ = document.createElement("button"),
btnMostrarTotal = document.createElement("button");
btnX.textContent = "Chama ação X";
btnY.textContent = "Chama ação Y";
btnZ.textContent = "Chama ação Z";
btnMostrarTotal.textContent = "Total";
btnX.onclick = function () {
requisitarAcao("acaoX", function (resposta) {
alert(resposta);
});
};
btnY.onclick = function () {
requisitarAcao("acaoY", function (resposta) {
alert(resposta);
});
};
btnZ.onclick = function () {
requisitarAcao("acaoZ", function (resposta) {
alert(resposta);
});
};
btnMostrarTotal.onclick = function () {
requisitarAcao("total", function (resposta) {
var totalResposta = [
"vezes que chamou a ação X:" + resposta.x,
"vezes que chamou a ação Y:" + resposta.y,
"vezes que chamou a ação Z:" + resposta.z
];
alert(totalResposta.join("\n"));
});
};
document.body.appendChild(btnX);
document.body.appendChild(btnY);
document.body.appendChild(btnZ);
document.body.appendChild(btnMostrarTotal);
}
if (/^(interactive|complete)$/.test(document.readyState)) {
gerarBotoes();
} else {
document.addEventListener("DOMContentLoaded", gerarBotoes);
window.addEventListener("load", gerarBotoes);
}
})(chrome||browser); //compatibilidade para firefox e chrome
Note: I created 3 buttons, but it's just for example, you can be anything, even a loop with
inject.js
, depends on what you want).
Once you have saved everything, load the extension by developer mode and open any of the sites mentioned above in setTimeout
, you will notice this in their footer:
Thenclickasmanytimesasyouwantinthefirst3,theywillbeaddedtogetherandfinally,whenyougettiredclickonthebuttoncalledTotal,itwilldisplaythetotalhitsofthe3linksabove
Nowopenanewtabfromadifferentsitethanitopenedbefore,ifitopenedcontent_scripts.matches
nowopenpt.stackoverflow.com
,butinsteadofclickingtheactionbuttons,clickTotaldirectly:
InmycaseIonlyclickedonceonXandonceonZ,butonthenewtabthevalueshaveremained.
Done,thiswayalltabshavethesamedataandyoucontinuewhereyouleftoff,howeveritisimportanttoknowthatifclosingthebrowseristhesameasfinalizingaserver,youwillendthebackground.jsandsothenexttimeIfyouwanttokeepthedatasavedyouwillneedtousesomethinglikesuperuser.com
: