2013-06-22 7 views
26

Penso che le estensioni di Chrome siano nel complesso abbastanza semplici e molto potenti, ma una cosa che mi confonde sempre è cercare di comunicare tra i vari script in cui il codice può essere eseguito. Esiste il codice che viene eseguito quando fa riferimento alla pagina "default_popup" del azione del browser, il codice nella proprietà "script" di "background" e gli script di contenuto.Contesti e metodi per la comunicazione tra l'azione del browser, gli script in background e gli script di contenuto delle estensioni chrome?

In quale contesto vengono eseguiti gli script in queste categorie e in che modo ciascuno può comunicare con gli altri?

+0

Correlati: [Spiega la comunicazione in background con Google Chrome Extensions] (http://stackoverflow.com/questions/4743540/please-explain-background-communication-with-google-chrome-extensions) –

risposta

62

Tre diversi contesti

Come uno sviluppatore di estensioni di Chrome, puoi distinguere tre diversi ambienti.

  1. codice di estensione, viene eseguito nel processo della vostra estensione Chrome
  2. Content scripts, in esecuzione nel processo della scheda.
  3. Codice non interno in esecuzione nel processo della scheda (injected by content scripts).

noti che quando una pagina non estensione incorpora <iframe src="chrome-extension://EXTENSIONID/page.htm">, quindi page.htm non è visto come una parte della proroga, in quanto tutti i fotogrammi in una quota di scheda lo stesso processo, in questo caso un processo non estensione Chrome is a multi-process application.

Accesso all'oggetto window all'interno di un processo di estensione

Poiché tutto il codice di estensione viene eseguito nello stesso processo, possono accedere reciprocamente window oggetto globale. Questa funzione non è ben nota, ma consente di manipolare direttamente oggetti JavaScript e DOM all'interno della stessa procedura di estensione. In genere è preferibile non utilizzare questo metodo, ma utilizzare le API message passing.

// To access the `window` of a background page, use 
var bgWindowObject = chrome.extension.getBackgroundPage() ; 
// To access the `window` of an event or background page, use: 
chrome.runtime.getBackgroundPage (function(bgWindowObject) { 
    // Do something with `bgWindow` if you want 
}); 

// To access the `window` of the badge's popup page (only if it's open!!!), use 
var popupWindowObject = chrome.extension.getViews({type:'popup'})[0] ; 

// To access the `window` of the options page (called /options.html), use 
var allWindowObjects = chrome.extension.getViews({type:'tab'}) ; 
var popupWindowObjects = allWindowObjects.filter(function(windowObject) { 
    return windowObject.location.pathname == '/options.html'; 
}); 
// Example: Get the `window` object of the first options page: 
var popupWindowObject = popupWindowObjects[0]; 

Per mantenere questo breve tratto, ho volutamente limitato l'esempio di codice per una dimostrazione di accedere ad altre window oggetti globali. È possibile utilizzare questi metodi per definire un metodo globale, impostare una variabile globale, chiamare una funzione globale, ecc.
... a condizione che la pagina sia aperta. Qualcuno thought che il popup del window sia sempre disponibile. Questo non è vero, quando il popup è chiuso, l'oggetto globale è eliminato!

Comunicazione message passing

Un canale di messaggio ha sempre due estremità: Il mittente e un ricevitore.
Per diventare un ricevitore, associare un listener di eventi utilizzando il metodo chrome.runtime.onMessage.addListener. Questo può essere fatto dal codice di estensione e dagli script di contenuto.

Per passare i messaggi all'interno dell'estensione, utilizzare chrome.runtime.sendMessage. Se si desidera inviare un messaggio a un'altra scheda, chiamare chrome.tabs.sendMessage. La scheda obiettivo viene specificata includendo un numero intero (tabId) come primo argomento. Si noti che una pagina di sfondo può solo inviare un messaggio a una scheda. Per raggiungere tutte le schede, è necessario chiamare il metodo per ogni scheda. Per esempio:

chrome.tabs.query ({}, function(tabs) { 
    for (var i=0; i<tabs.length; i++) { 
     chrome.tabs.sendMessage (tabs[i].id, "some message"); 
    } 
});

script contenuti possono chiamare solo chrome.runtime.sendMessage per inviare un messaggio a codice di estensione. Se si desidera inviare un messaggio da uno script di contenuto a un altro script di contenuto, è necessaria una pagina di sfondo/evento, che accetta un messaggio e lo invia alla scheda desiderata.Vedere this answer per un esempio.

I metodi sendMessage accettano una funzione opzionale, che viene ricevuta come terzo argomento per l'evento onMessage.

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 
    if (message === 'message') sendResponse('the response'); 
}); 
chrome.runtime.sendMessage('message', function(response) { 
    console('sendResponse was called with: ' + response); 
}); 

L'esempio precedente mostra un comportamento evidente. Le cose diventano più complicate quando si desidera inviare una risposta in modo asincrono, ad esempio se si desidera eseguire una richiesta AJAX per recuperare alcuni dati. Quando la funzione onMessage ritorna senza aver chiamato sendResponse, Chrome invierà immediatamente sendResponse. Dal momento che sendResponse può essere chiamato solo una volta, verrà visualizzato il seguente errore:

Could not send response: The chrome.runtime.onMessage listener must return true if you want to send a response after the listener returns (message was sent by extension EXTENSION ID HERE)

Do come l'errore suggerisce, aggiunge return true; all'interno del vostro onMessage listener di eventi:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { 
    setTimeout(function() { // Example: asynchronous invocation of sendResponse 
     sendResponse('async response'); 
    }, 200); 
    return true; 
}); 

ho spiegato l'applicazione pratica di un semplice messaggio di una volta che passa in questa sezione. Se vuoi saperne di più sui canali dei messaggi a lunga durata o sulla messaggistica inter-estesa, leggi lo tutorial from the official documentation.

L'API di passaggio del messaggio ha subito diverse modifiche al nome. Tienilo a mente se leggi vecchi esempi. La storia e le note di compatibilità possono essere trovate here.

comunicazione tra uno script contenuti e la pagina

E 'possibile comunicare con la pagina. Apsillers ha creato una risposta eccellente che spiega come impostare un canale di comunicazione tra una pagina (non di estensione) e uno script di contenuto. Leggi la sua risposta allo Can a site invoke a browser extension?.

Il vantaggio del metodo di apsiller su one from the documentation è che viene utilizzato un evento personalizzato. La documentazione utilizza window.postMessage per inviare un messaggio alla pagina, ma ciò potrebbe causare conflitti con pagine mal codificate che non si aspettano eventi del messaggio.

+4

Oh Man questa risposta merita accettazione e molto più upvotes..Molto bene spiegato. – sachinjain024

-1

È passato un po 'di tempo da quando ho avuto a che fare con le estensioni di Chrome. Ricordo che fu una vera lotta prima di capire come funzionavano le cose. Affinché la tua estensione comunichi con il browser, è facile usare il file javascript/background e per comunicare con la pagina web è necessario utilizzare chrome.tabs.executeScript ma è davvero complicato e può essere un vero rompicapo. Ti suggerisco di prendere lo google's tour on extensions e di dare alla loro api un bel belvedere, è tutto lì dentro! Ti auguro buona fortuna e spero che questa risposta ti abbia aiutato! : P

3

La documentazione di Google ha tutto, ma è difficile riunire tutte le informazioni. Esistono due tipi principali di script:
1. Gli script in background hanno pieno accesso alle API di Chrome, ma non possono interagire con la pagina Web di destinazione.
2. Gli script di contenuto possono interagire tra loro e con il DOM della pagina Web (ma non i suoi script, da cui è isolato), ma hanno solo un accesso limitato alle API di Chrome.
Entrambi vengono eseguiti ogni volta che si carica una nuova pagina (a meno che non siano state utilizzate "corrispondenze" per limitare la posizione in cui viene eseguito lo script del contenuto).

È possibile comunicare tra i due tramite message passing. Questo è più facile da script di contenuto che da script di sfondo perché è necessario conoscere l'ID della scheda per quest'ultimo.

Altri script (browserAction.js, pageAction.js, optionsPage.js) solo eseguire quando il loro pagina html corrispondente viene aperto (come se si sta aprendo la pagina web nella finestra del browser, che è quello che stai facendo veramente). Sono simili agli script di background in restrizioni e abilità.

Cercare di evitare la necessità di interagire con gli script di una pagina. Il modo migliore che conosco è di interagire attraverso il DOM condiviso (scrivendo letteralmente il codice javascript all'interno dei commenti html). Ma l'obiettivo della tua estensione non è progettato per questo, quindi dovrai includere il tuo script che lo fa nella pagina web. Utilizzare uno script contenuti di scrivere la sceneggiatura elemento nel documento (la sua src è
chrome.extension.getURL("myscript.js"),
e avrete bisogno di
"web_accessible_resources": ["myscript.js"]
nel vostro manifesto.

Problemi correlati