web-dev-qa-db-fra.com

Extension Chrome - Récupération d'une variable globale à partir d'une page Web

Je travaille sur une extension pour Chrome. Je souhaite analyser le contenu du message "original" de Gmail (le message actuellement affiché).

J'ai essayé d'utiliser le jQuery.load () comme suit

$(windows).load(function() { alert(GLOBALS); });

et placez-le au script de contenu, mais cela ne fonctionne pas non plus. J'utilise les outils de développement de Chrome, ce qui renvoie l'erreur suivante lors de l'appel de la fonction alert(GLOBALS);.

Uncaught ReferenceError: GLOBALS n'est pas défini

Bien que, lorsque vous utilisez la console des outils de développement, taper dans la console GLOBALS renvoie un tableau. 

Avez-vous une idée de la manière d’accéder aux GLOBALS à partir du script de contenu?

37
MrRoth

Les scripts de contenu s'exécutent dans un environnement isolé. Pour accéder aux propriétés globales (de la window de la page), vous devez soit injecter un nouvel élément <script>, soit utiliser des écouteurs d'événement pour la transmission de données.

Voir cette réponse par exemple sur l’injection d’un élément <script> dans le contexte de la page.

Exemple

contentscript.js ("run_at": "document_end" dans le manifeste):

var s = document.createElement('script');
s.src = chrome.extension.getURL('script.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
    s.remove();
};

// Event listener
document.addEventListener('RW759_connectExtension', function(e) {
    // e.detail contains the transferred data (can be anything, ranging
    // from JavaScript objects to strings).
    // Do something, for example:
    alert(e.detail);
});

script.js - Situé dans le répertoire de l'extension, il sera injecté dans la page elle-même:

setTimeout(function() {
    /* Example: Send data from the page to your Chrome extension */
    document.dispatchEvent(new CustomEvent('RW759_connectExtension', {
        detail: GLOBALS // Some variable from Gmail.
    }));
}, 0);

Comme ce fichier est chargé via une extension chrome: URL depuis le DOM, vous devez ajouter "script.js" à la section web_accessible_resources du fichier manifeste. Sinon, Chrome refusera de charger le fichier de script.

Vous devez exécuter le moins de logique possible dans la page Web et gérer l'essentiel de votre logique dans le script de contenu. Cela a plusieurs raisons. Tout d'abord, tout script injecté dans la page s'exécute dans le même contexte que la page Web. Ainsi, la page Web peut (délibérément ou par inadvertance) modifier les méthodes JavaScript/DOM de telle sorte que votre extension cesse de fonctionner. Deuxièmement, les scripts de contenu ont accès à des fonctionnalités supplémentaires, telles qu'un sous-ensemble limité de chrome. * API et aux requêtes réseau cross-Origin (à condition que l'extension dispose d'autorisations déclarées pour celles-ci). 

81
Rob W

Une solution plus moderne pour la communication entre une extension chrome content_script et le javascript de la page serait d'utiliser l'API html5 postMessage. Tous les messages envoyés à "window" sont visibles à partir du code javascript de la page Web et du contenu_script de l'extension.

L'extension content_script.js:

window.addEventListener('message', function(event) {
    console.log('content_script.js got message:', event);
    // check event.type and event.data
});

setTimeout(function () {
    console.log('cs sending message');
    window.postMessage({ type: 'content_script_type',
                         text: 'Hello from content_script.js!'},
                       '*' /* targetOrigin: any */ );
}, 1000);

Le javascript en cours d'exécution sur la page Web:

window.addEventListener('message', function(event) {
    console.log('page javascript got message:', event);
});

setTimeout(function() {
    console.log('page javascript sending message');
    window.postMessage({ type: 'page_js_type',
                         text: "Hello from the page's javascript!"},
                       '*' /* targetOrigin: any */);
}, 2000);

Voir aussi http://developer.chrome.com/extensions/content_scripts.html#Host-page-communication

18
Alex

Il existe une nouvelle API permettant aux pages Web de communiquer en toute sécurité et sans aucun effet secondaire (window.postMessage peut avoir d'autres écouteurs!) Avec le script de contenu.

"Depuis la page Web, utilisez les API runtime.sendMessage ou runtime.connect pour envoyer un message à une application ou à une extension spécifique"

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
  function(response) {
    if (!response.success)
    handleError(url);
});

"Depuis votre application ou votre extension, vous pouvez écouter des messages de pages Web via les API runtime.onMessageExternal ou runtime.onConnectExternal, similaires à la messagerie inter-extensions. Seule la page Web peut établir une connexion. [...]"

(à partir de http://developer.chrome.com/extensions/messaging.html ) Il n’est disponible que dans le canal de développement de chrome, mais il semble que ce sera dans la prochaine version.

Ne me demandez pas comment cela fonctionne, cela semble très déroutant. Comment est-ce que chrome.runtime est défini sur la page Web? Que se passe-t-il si le script a déjà défini cette variable pour une raison quelconque? Je ne pouvais pas non plus trouver le rapport de bogue sur le chrome pour consulter l'historique du développement de cette fonctionnalité.

3
kzahel