Il modello di sicurezza delle app di Chrome non consente i contenuti esterni negli iframe e l'utilizzo di
e eval()
. Puoi ignorare queste restrizioni, ma i tuoi contenuti esterni devono essere
isolato dall'app.
I contenuti isolati non possono accedere direttamente ai dati dell'app o a nessuna delle API. Utilizza multiorigine XMLHttpRequests e post-messaggistica per la comunicazione tra la pagina dell'evento e i contenuti con sandbox e accedere indirettamente alle API.
Fare riferimento a risorse esterne
Il Criterio di sicurezza del contenuto usato dalle app non consente l'utilizzo di molti tipi di URL remoti, quindi
non possono fare riferimento direttamente a immagini, fogli di stile o caratteri esterni dalla pagina di un'app. Puoi invece
utilizza XMLHttpRequests multiorigine per recuperare queste risorse e poi pubblicarle tramite URL blob:
.
Requisito del file manifest
Per poter eseguire XMLHttpRequests multiorigine, devi aggiungere un'autorizzazione per l'URL remoto host:
"permissions": [
"...",
"https://supersweetdomainbutnotcspfriendly.com/"
]
XMLHttpRequest multiorigine
Recupera l'URL remoto nell'app e pubblica i suoi contenuti come URL blob:
:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
var img = document.createElement('img');
img.src = window.URL.createObjectURL(this.response);
document.body.appendChild(img);
};
xhr.send();
Ti consigliamo di salvare queste risorse localmente, in modo che siano disponibili offline.
Incorporare pagine web esterne
Il tag webview
ti consente di incorporare nell'app contenuti web esterni, ad esempio una pagina
. Sostituisce gli iframe che puntano a URL remoti, che sono disattivati all'interno delle app di Chrome. Non mi piace
iframe, il tag webview
viene eseguito in un processo separato. Ciò significa che un exploit al suo interno
saranno ancora isolati e non potranno ottenere privilegi elevati. Inoltre, poiché la sua archiviazione
(cookie e così via) sia isolato dall'app, per i contenuti web non è in alcun modo possibile accedere ai
i dati dell'app.
Aggiungi elemento WebView
L'elemento webview
deve includere l'URL dei contenuti di origine e specificarne le dimensioni.
<webview src="http://news.google.com/" width="640" height="480"></webview>
Aggiorna proprietà
Per modificare dinamicamente le proprietà src
, width
e height
di un tag webview
, puoi
Impostare queste proprietà direttamente sull'oggetto JavaScript, oppure utilizzare la funzione DOM setAttribute
.
document.querySelector('#mywebview').src =
'http://blog.chromium.org/';
// or
document.querySelector('#mywebview').setAttribute(
'src', 'http://blog.chromium.org/');
Sandbox contenuti locali
La limitazione tramite sandbox consente di pubblicare pagine specifiche in un'origine unica e protetta tramite sandbox. Queste pagine vengono quindi
dai criteri di sicurezza del contenuto. Le pagine con sandbox possono utilizzare iframe, scripting incorporato e
eval()
. Controlla la descrizione del campo manifest per sandbox.
Tuttavia, c'è un compromesso: le pagine con sandbox non possono utilizzare Chrome.* API Se devi svolgere operazioni come
eval()
, percorri questa strada per essere esente da CSP, ma non potrai usare le cose nuove e interessanti.
Utilizza script incorporati nella sandbox
Di seguito è riportato un esempio di pagina con sandbox che utilizza uno script incorporato e eval()
:
<html>
<body>
<h1>Woot</h1>
<script>
eval('console.log(\'I am an eval-ed inline script.\')');
</script>
</body>
</html>
Includi sandbox nel file manifest
Devi includere il campo sandbox
nel file manifest ed elencare le pagine dell'app da pubblicare in una
sandbox:
"sandbox": {
"pages": ["sandboxed.html"]
}
Apertura di una pagina con sandbox in una finestra
Come per qualsiasi altra pagina dell'app, puoi creare una finestra in cui aprire la pagina con sandbox. Ecco un esempio che crea due finestre, una per la finestra principale dell'app senza sandbox e una per pagina con sandbox:
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('window.html', {
'bounds': {
'width': 400,
'height': 400,
'left': 0,
'top': 0
}
});
chrome.app.window.create('sandboxed.html', {
'bounds': {
'width': 400,
'height': 400,
'left': 400,
'top': 0
}
});
});
Incorporare una pagina con sandbox nella pagina di un'app
Le pagine con sandbox possono anche essere incorporate in un'altra pagina dell'app utilizzando un iframe
:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>I am normal app window.</p>
<iframe src="sandboxed.html" width="300" height="200"></iframe>
</body>
</html>
Invio di messaggi a pagine con sandbox
L'invio di un messaggio è composto da due parti: la pubblicazione del messaggio dalla pagina/finestra del mittente, e ascoltare i messaggi sulla pagina/finestra di destinazione.
Pubblica messaggio
Puoi utilizzare postMessage
per comunicare tra la tua app e i contenuti con sandbox. Ecco un esempio
script in background che pubblica un messaggio nella pagina con sandbox che si apre:
var myWin = null;
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('sandboxed.html', {
'bounds': {
'width': 400,
'height': 400
}
}, function(win) {
myWin = win;
myWin.contentWindow.postMessage('Just wanted to say hey.', '*');
});
});
In generale, sul web, è necessario specificare l'origine esatta da cui viene inviato il messaggio. Le app di Chrome non hanno accesso all'origine univoca dei contenuti sottoposti a sandbox, quindi puoi inserire nella lista consentita solo tutti come origini accettabili ("*"). Sul lato ricevente, in genere si vuole controllare l'origine; ma poiché i contenuti delle app di Chrome sono inclusi, non è necessario. Per saperne di più, vedi window.postMessage.
Ascolta il messaggio e rispondi
Ecco un esempio di destinatario di messaggi che viene aggiunto alla tua pagina con sandbox:
var messageHandler = function(event) {
console.log('Background script says hello.', event.data);
// Send a reply
event.source.postMessage(
{'reply': 'Sandbox received: ' + event.data}, event.origin);
};
window.addEventListener('message', messageHandler);
Per ulteriori dettagli, dai un'occhiata all'esempio della sandbox.