web-dev-qa-db-fra.com

Variables de page dans le script de contenu

Existe-t-il un moyen de récupérer les variables javascript d'une page à partir d'un script de contenu Google Chrome?

25
esqew

Si vous en avez vraiment besoin, vous pouvez insérer un élément <script> dans le DOM de la page. le code à l'intérieur de votre élément <script> sera exécuté et ce code aura accès aux variables JavaScript à la portée de la fenêtre. Vous pouvez ensuite les communiquer au script de contenu en utilisant les attributs data- et en lançant des événements personnalisés.

Cela vous semble maladroit? Pourquoi oui, c’est intentionnellement, pour toutes les raisons citées dans la documentation citée par serg. Mais si vous avez vraiment, vraiment besoin de le faire, vous pouvez le faire. Voir ici et ici pour plus d'informations. Et bonne chance!

59
npdoty

J'ai créé une petite méthode d'assistance, amusez-vous :)

pour récupérer les variables de la fenêtre "lannister", "toujours", "paie", "son", "dettes" , vous exécutez ce qui suit:

var windowVariables = retrieveWindowVariables(["lannister", "always", "pays", "his", "debts"]);
console.log(windowVariables.lannister);
console.log(windowVariables.always);

mon code:

function retrieveWindowVariables(variables) {
    var ret = {};

    var scriptContent = "";
    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', " + currVariable + ");\n"
    }

    var script = document.createElement('script');
    script.id = 'tmpScript';
    script.appendChild(document.createTextNode(scriptContent));
    (document.body || document.head || document.documentElement).appendChild(script);

    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        ret[currVariable] = $("body").attr("tmp_" + currVariable);
        $("body").removeAttr("tmp_" + currVariable);
    }

    $("#tmpScript").remove();

    return ret;
}

s'il vous plaît noter que j'ai utilisé jQuery .. vous pouvez facilement utiliser le js natif "removeAttribute" et "removeChild" à la place.

15
Liran Brimer

En utilisant la solution de Liran, j’ajoute un correctif pour Objects, voici la solution correcte:

function retrieveWindowVariables(variables) {
    var ret = {};

    var scriptContent = "";
    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        scriptContent += "if (typeof " + currVariable + " !== 'undefined') $('body').attr('tmp_" + currVariable + "', JSON.stringify(" + currVariable + "));\n"
    }

    var script = document.createElement('script');
    script.id = 'tmpScript';
    script.appendChild(document.createTextNode(scriptContent));
    (document.body || document.head || document.documentElement).appendChild(script);

    for (var i = 0; i < variables.length; i++) {
        var currVariable = variables[i];
        ret[currVariable] = $.parseJSON($("body").attr("tmp_" + currVariable));
        $("body").removeAttr("tmp_" + currVariable);
    }

     $("#tmpScript").remove();

    return ret;
}
10
Taras Kosteskyi

Non.

Les scripts de contenu s'exécutent dans un environnement spécial appelé un monde isolé. Ils ont accès au DOM de la page dans laquelle ils sont injectés, mais pas aux variables JavaScript ni aux fonctions créées par la page. Chaque script de contenu est considéré comme si aucun autre script JavaScript ne s'exécutait sur la page sur laquelle il s'exécutait. La même chose est vraie en sens inverse: JavaScript en cours d'exécution sur la page ne peut appeler aucune fonction ni accéder aux variables définies par les scripts de contenu.

Les mondes isolés permettent à chaque script de contenu de modifier son environnement JavaScript sans se soucier des conflits avec la page ou avec d'autres scripts de contenu. Par exemple, un script de contenu peut inclure JQuery v1 et la page peut inclure JQuery v2, sans conflit.

Un autre avantage important des mondes isolés est qu'ils séparent complètement le code JavaScript de la page du code JavaScript des extensions. Cela nous permet d’offrir une fonctionnalité supplémentaire aux scripts de contenu qui ne doivent pas être accessibles à partir de pages Web sans se soucier de l’accès des pages Web à celui-ci.

0
serg

Si vous savez à quelles variables vous souhaitez accéder, vous pouvez créer un script de contenu personnalisé rapide pour récupérer leurs valeurs.

Dans popup.js:

chrome.tabs.executeScript(null, {code: 'var name = "property"'}, function() {
    chrome.tabs.executeScript(null, {file: "retrieveValue.js"}, function(ret) {
        for (var i = 0; i < ret.length; i++) {
            console.log(ret[i]); //prints out each returned element in the array
        }
    });
});

Dans retrieveValue.js:

function returnValues() {
    return document.getElementById("element")[name];
    //return any variables you need to retrieve
}
returnValues();

Vous pouvez modifier le code pour renvoyer des tableaux ou d'autres objets.

0
victor

En fait, j'ai travaillé avec l'API localStorge. Note: pour utiliser ceci, notre contenu devrait être capable de lire le localStorage. Dans le fichier manifest.json, ajoutez simplement la chaîne "storage":

"permissions": [...,"storage"]

La fonction Hijack existe dans le script de contenu:

function Hijack(callback) {
    "use strict";
    var code = function() {
      //We have access to topframe - no longer a contentscript          
      var ourLocalStorageObject = {
        globalVar: window.globalVar,
        globalVar2: window.globalVar2
      };
      var dataString = JSON.stringify(ourLocalStorageObject);
      localStorage.setItem("ourLocalStorageObject", dataString);
    };
    var script = document.createElement('script');
    script.textContent = '(' + code + ')()';
    (document.head||document.documentElement).appendChild(script);
    script.parentNode.removeChild(script);
    callback();
  }

Maintenant, nous pouvons appeler depuis le sommaire

document.addEventListener("DOMContentLoaded", function(event) { 
    Hijack(callback);
});

ou si vous utilisez jQuery dans votre sommaire, comme moi:

$(document).ready(function() { 
    Hijack(callback);
});

extraire le contenu:

function callback() {
    var localStorageString = localStorage.getItem("ourLocalStorageObject");
    var ourLocalStorageObject= JSON.parse(localStorageString);

    console.log("I can see now on content script", ourLocalStorageObject);
    //(optional cleanup):
    localStorage.removeItem("ourLocalStorageObject");
}

Cela peut être appelé plusieurs fois. Ainsi, si votre page modifie des éléments ou du code interne, vous pouvez ajouter des écouteurs d'événements pour mettre à jour votre extension avec les nouvelles données.

Modifier: j'ai ajouté des rappels afin que vous puissiez être sûr que vos données ne seront pas invalides (ce problème m'était propre)

0
Elia Grady