How to communicate tabs with an extension/add-on and store variables?

Asked

Viewed 219 times

6

1 answer

4


Note: link with full and functional example to use/test:

For something to run you must use the background.js in its length and store the values, or to be more precise:

"background": {
    "scripts": [
        "background.js"
    ]
},

The background works as a server back-end, it keeps running constantly, even without open tabs from a site specified on manifest.json

All tabs generated and your pages specified in the manifest.json can access the same execution as the background.js, because there will only be one, ie for each extension is generated a process that is running the background.js.

Having understood this we will stop the tabs, when the extension starts (right at the start of the browser) you will be able to communicate with it, each tab/new window opened will be able to communicate with the background.js

To communicate a tab with the background you will need to use:

  • chrome.runtime.sendMessage

And to receive the request in the background it will be necessary to use:

  • chrome.runtime.onMessage.addListener

However, it will be necessary to inject scripts into 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 defined that the inject.js the following pages will be added:

  • will be injected into any superuser.com page (can be added to a sub-domain)
  • will be injected into any serverfault.com page (can be added to a sub-domain)
  • will be injected into any stackoverflow.com page (can be added to a sub-domain)

Now in the content of background.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 on the inject.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 just to illustrate, you can be anything, even a loop with setTimeout, depends on what you want).

Ready having saved everything, load the extension by developer mode and open any of the sites mentioned above on content_scripts.matches, you will notice this in their footer:

botões gerados pelo add-on nos sites definidos no manifest.json

Then click as many times as you want in the first 3, they will be added and finally, when you get tired click on the button called Total, it will display the total of hits of the 3 links above

Now open a new tab of a site different from the one you opened before, if you opened the pt.stackoverflow.com now open the superuser.com, but instead of clicking on the action buttons, click on Total directly:

resultado

In my case I had only clicked once on X and one on Z, but in the new tab the values remained.

That way all tabs have the same data and you continue where you left off, however it is important to know that if closing the browser is the same as finishing a server, you will finish the background.js and so the next time you launch the browser the browser background.js will start from scratch, if you want to keep the saved data you will need to use something like localStorage:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.