web-dev-qa-db-fra.com

Comment accéder à la page Web DOM plutôt qu'à la page d'extension DOM?

J'écris une extension Chrome et j'essaie de superposer une <div> sur la page Web actuelle dès qu'un bouton est cliqué dans le fichier popup.html.

Lorsque j'accède au document.body.insertBefore méthode à partir de popup.html, elle superpose la <div> dans la fenêtre contextuelle, plutôt que sur la page Web actuelle.

Dois-je utiliser la messagerie entre background.html et popup.html pour accéder au DOM de la page Web? Je voudrais tout faire dans popup.html, et utiliser jQuery aussi, si possible.

62
Steven

Comme indiqué dans Présentation des extensions Chrome: architecture (qui est une lecture incontournable):

Si votre extension doit interagir avec des pages Web, alors elle a besoin d'un script de contenu. Un script de contenu est du JavaScript qui s'exécute dans le contexte d'une page qui est été chargé dans le navigateur. Considérez un script de contenu comme faisant partie de cette page chargée, pas comme faisant partie de l'extension avec laquelle il a été empaqueté (son extension parent).

Une popup de browserAction est la page que vous voyez lorsque vous cliquez sur l'icône dans la barre d'outils du navigateur, c'est une page HTML avec l'URL chrome-extension://, Donc lorsque vous accédez à son DOM, vous affectez la popup. La même chose s'applique à une page d'arrière-plan/d'options d'une extension.

Pour accéder/manipuler le DOM de la page Web, vous avez deux façons:

  1. Soit déclarer script (s) de conten dans manifest.json et utiliser messagerie :

    chrome.tabs.sendMessage() de votre page d'arrière-plan/popup au script de contenu injecté chrome.runtime.onMessage écouteur, qui effectuera des actions sur la page Web et transférera les résultats via sendResponse rappel selon la documentation (note: seuls les objets JSON-ifiables comme les nombres, les chaînes, les tableaux, les objets simples sont supportés, ce qui signifie pas les éléments DOM, pas les classes, pas les fonctions). Dans le cas où le script de contenu doit initier une communication vers une page d'extension, il doit utiliser chrome.runtime.sendMessage() .

  2. Ou utilisez API Tabs pour injecter un script de contenu :
    chrome.tabs.executeScript(tabId, details, callback)

    • Requis autorisations : "tabs", "https://www.example.com/*"
      (ou "<all_urls>" et des variantes comme "*://*/*", "http://*/*", "https://*/*")

    • Un meilleur choix, en cas d'activation utilisateur explicite, consiste à utiliser "activeTab" Permission au lieu de "tabs" Et "<all_urls>" Car il sert d'alternative pour nombreuses utilisations de "<all_urls>", mais n'affiche aucun message d'avertissement pendant l'installation.

    • .executeScript() peut être utilisé avec une fonction de rappel qui reçoit un tableau des dernières expressions évaluées dans le script de contenu injecté, un élément par chaque trame dans laquelle il est injecté dans l'onglet. Chrome utilise JSON.parse() et JSON.stringify() sur les résultats en interne, limitant ainsi les types pris en charge à des objets simples et à des valeurs de chaîne simples comme nombre/chaîne ou des tableaux de celui-ci.
      Donc, cela ne fonctionne pas pour les éléments DOM, les fonctions, les propriétés personnalisées, les getters/setters: vous devrez mapper/extraire manuellement les données requises et les transmettre dans un simple tableau/objet.

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 à aucune variable JavaScript ou des fonctions créées par la page. Il regarde chaque script de contenu comme s'il n'y avait pas d'autre JavaScript en cours d'exécution sur la page sur laquelle il s'exécute. Il en va de même en sens inverse: JavaScript exécuté sur la page ne peut appeler aucune fonction ni accéder aux variables définies par les scripts de contenu.

Il est toujours possible d'aller plus loin et accéder aux variables/fonctions JavaScript de la page Web .



Comme exemple de la deuxième méthode, montrons ce div quand une action du navigateur est cliquée.
Nous utiliserons chrome.tabs.executeScript() dans le gestionnaire de clics browserAction pour injecter un fichier de script de contenu (ou une chaîne de code littérale si elle est petite, voir le la documentation de la méthode) au DOM de cette page.

var someVar = {text: 'test', foo: 1, bar: false};
chrome.tabs.executeScript({
    code: '(' + function(params) {
        document.body.insertAdjacentHTML('beforeend',
            '<div style="all:unset; position:fixed; left:0; top:0; right:0; bottom:0;' +
                'background-color:rgba(0,255,0,0.3)">' + params.text + '</div>'
        );
        return {success: true, html: document.body.innerHTML};
    } + ')(' + JSON.stringify(someVar) + ');'
}, function(results) {
    console.log(results[0]);
});

Comme vous pouvez le voir, nous avons utilisé la conversion de chaîne automatique du code de fonction pour pouvoir écrire le code injecté en JavaScript normal avec la coloration syntaxique et le linting. L'inconvénient évident est que le navigateur perd du temps à analyser le code, mais généralement c'est moins de 1 milliseconde donc négligeable.

104
Mohamed Mansour