web-dev-qa-db-fra.com

Comment obtenir la valeur du champ de saisie à partir de Chrome Extension

Je travaille pour apprendre à créer une extension Google Chrome. J'ai un formulaire de contact sur une page Web que j'utilise pour les tests. J'essaie de créer une extension qui lira le saisissez les valeurs des champs à partir de ce formulaire. Pour le moment, j'ai:

manifest.json

{
    "manifest_version": 2,

    "name": "Contact Form Friend",
    "description": "This extension gets contact form info.",
    "version": "1.0",

    "browser_action": {
      "default_icon": "icon.png",
      "default_popup": "popup.html"
    },

    "permissions": [
      "activeTab",
      "<all_urls>"
    ]
  }

popup.html

<!doctype html>
<html>
  <head>
    <title>Getting Started Extension's Popup</title>
    <style type="text/css">
      body {
        margin: 10px;
        white-space: nowrap;
      }

      h1 {
        font-size: 15px;
      }

      #container {
        align-items: center;
        display: flex;
        justify-content: space-between;
      }
    </style>

    <script src="popup.js"></script>
  </head>

    <body>
        <h1>Info</h1>
        <div id="info">

        </div>
    </body>
</html>

popup.js

function getHost() {
    return document.documentElement;
}

document.addEventListener('DOMContentLoaded', () => {
    const infoDisplay = document.getElementById('info');    
    const scriptToRun = `(${getHost})()`;

    // Run the script in the context of the tab
    chrome.tabs.executeScript({
      code: scriptToRun 
    }, (result) => {            
      var values = [];

      var inputFields = result.getElementsByTagName('input');
      infoDisplay.innerHTML = 'inputs: ' + inputFields.length;
      for (var i = 0; i < inputFields.length; i++) {
        values.Push(inputFields[i].value);
      }

      infoDisplay.innerHTML += '<br />fields: ' + values.length;
    });
});

Lorsque j'exécute cela, il agit comme s'il ne pouvait pas accéder aux champs de saisie à partir de la page Web sur laquelle l'utilisateur se trouve (pas la page Web de l'extension). Qu'est-ce que je fais mal? Suis-je en manque d'une autorisation? Je ne le crois pas. Cependant, cela ne fonctionne pas et je ne sais pas pourquoi.

Merci de votre aide.

10
Some User

Comme indiqué par Gabriel Ble vous avez besoin d'un script de contenu pour interagir avec les pages Web à l'intérieur des onglets Chrome.

Voici ci-dessous un exemple de Chrome Extension où un script de contenu expose deux "commandes" à popup.js.

Voir les commentaires du code pour une explication.

manifest.json (similaire au vôtre)

{
  "name": "My ext",
  "version": "0.1",
  "description": "my desc",
  "permissions": [
    "activeTab",
    "<all_urls>"
  ],
  "icons": {
    "128": "icon-128.png"
  },
  "browser_action": {
      "default_title": "My ext",
      "default_icon": "icon.png",
      "default_popup": "popup.html"
  },
  "manifest_version": 2,
  "content_security_policy": "script-src 'self' https://ajax.googleapis.com object-src 'self'"
}

popup.html (similaire au vôtre sauf pour l'utilisation de jQuery pour une manipulation facile du DOM)

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script type="application/javascript" charset="utf-8" src="popup.js"></script>
</head>
<body class="body-popup">
    <button id="btn_check" class="btn btn-warning">check current tab</button>
    <hr>
    <div id="pg_url"></div>
    <hr>
    <div id="log"></div>
</body>
</html>

popup.js

$(function() {
    $('#btn_check').click(function() { checkCurrentTab(); });
});

function checkCurrentTab() {
    chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
        var url = tabs[0].url;
        console.log("checkCurrentTab: "+url);
        $(".pg_url").text(url);

        // request content_script to retrieve title element innerHTML from current tab
        chrome.tabs.sendMessage(tabs[0].id, "getHeadTitle", null, function(obj) {
            console.log("getHeadTitle.from content_script:", obj);
            log("from content_script:"+obj);
        });

    });
}

document.addEventListener('DOMContentLoaded', function () {
    chrome.windows.getCurrent(function (currentWindow) {
        chrome.tabs.query({active: true, windowId: currentWindow.id}, function(activeTabs) {
            // inject content_script to current tab
            chrome.tabs.executeScript(activeTabs[0].id, {file: 'content_script.js', allFrames: false});
        });
    });
});

function log(txt) {
    var h = $("#log").html();
    $("#log").html(h+"<br>"+txt);
}

content_script.js

// you will see this log in console log of current tab in Chrome when the script is injected
console.log("content_script.js");

chrome.runtime.onMessage.addListener(function(cmd, sender, sendResponse) {
    console.log("chrome.runtime.onMessage: "+cmd);
    switch(cmd) {
    case "getHtml":
        // retrieve document HTML and send to popup.js
        sendResponse({title: document.title, url: window.location.href, html: document.documentElement.innerHTML});
        break;
    case "getHeadTitle":
        // retrieve title HTML and send to popup.js
        sendResponse(document.getElementsByTagName("title")[0].innerHTML);
        break;      
    default:
        sendResponse(null);
    }
});

P.S.: évidemment jQuery n'est pas obligatoire

5
beaver

Si votre extension doit interagir avec des pages Web, 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 a été chargée 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).

https://developer.chrome.com/extensions/overview#contentScripts

2
Gabriel Bleu

Voici l'erreur que vous recevez:

Error in response to tabs.executeScript: TypeError: result.getElementsByTagName is not a function
at Object.chrome.tabs.executeScript [as callback] (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:15:32)
at HTMLDocument.document.addEventListener (chrome-extension://lmaefdnejmkjjmgalgfofdbobhapfmoh/popup.js:10:17)

Au lieu d'essayer d'obtenir le DOM de l'onglet actuel dans popup.js, je suggère d'utiliser un script de contenu pour effectuer la tâche et d'envoyer le résultat sous forme de message à la fenêtre contextuelle.

manifest.json

{
    "manifest_version": 2,
    "name": "Contact Form Friend",
    "description": "This extension gets contact form info.",
    "version": "1.0",

    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    },

    "permissions": [
        "activeTab",
        "<all_urls>"
    ],

    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["content.js"]
        }
    ]
}

Dans le fichier manifest.json , vous devez ajouter le script de contenu et définir les URL des sites dans lesquels vous souhaitez injecter le script.

popup.js

document.addEventListener('DOMContentLoaded', () => {
    const infoDisplay = document.getElementById('info');    

    window.addEventListener('DOMContentLoaded', function () {
        chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {}, function (result) {
                infoDisplay.innerHTML = result
            });
        });
    });

});

Dans popup.js envoyez une requête au script de contenu, pour obtenir le nombre de champs d'entrée et insérer la réponse dans le div.

content.js

chrome.runtime.onMessage.addListener(function (msg, sender, response) {
    var values = [];
    var inputFields = document.getElementsByTagName('input');
    var result = 'inputs: ' + inputFields.length;

    for (var i = 0; i < inputFields.length; i++) {
        values.Push(inputFields[i].value);
    }

    result += '<br />fields: ' + values.length;

    response(result)
});

Créez un nouveau fichier, nommé content.js. Ce fichier sera injecté dans la page Web et il écoute les messages du popup.js. Lorsqu'un message arrive, il calcule la réponse et la renvoie à popup.js.

Pour en savoir plus sur les scripts de contenu, consultez la documentation .

1
sc3w