Contenuti esterni

Il modello di sicurezza delle app di Chrome non consente i contenuti esterni negli iframe e l'uso di scripting incorporato e eval(). Puoi eseguire l'override di queste restrizioni, ma i contenuti esterni devono essere isolati dall'app.

I contenuti isolati non possono accedere direttamente ai dati dell'app o alle API. Utilizza XMLHttpRequests tra origini e post-messaggistica per comunicare tra la pagina dell'evento e i contenuti con sandbox e accedere indirettamente alle API.

Riferimento a risorse esterne

I Criteri di sicurezza del contenuto utilizzati dalle app non consentono l'uso di molti tipi di URL remoti, quindi non puoi fare riferimento direttamente a immagini esterne, fogli di stile o caratteri dalla pagina di un'app. Puoi invece utilizzare XMLHttpRequests multiorigine per recuperare queste risorse e pubblicarle tramite URL blob:.

Requisito del file manifest

Per poter eseguire XMLHttpRequests multiorigine, devi aggiungere un'autorizzazione per l'host dell'URL remoto:

"permissions": [
    "...",
    "https://supersweetdomainbutnotcspfriendly.com/"
  ]

XMLHttpRequest multiorigine

Recupera l'URL remoto nell'app e pubblica i relativi 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();

Puoi salvare queste risorse localmente in modo che siano disponibili offline.

Incorporare pagine web esterne

Il tag webview ti consente di incorporare contenuti web esterni nella tua app, ad esempio una pagina web. Sostituisce iframe che rimandano a URL remoti, che sono disattivati all'interno delle app di Chrome. A differenza degli iframe, il tag webview viene eseguito in un processo separato. Ciò significa che un exploit al suo interno verrà comunque isolato e non potrà ottenere privilegi elevati. Inoltre, poiché il suo spazio di archiviazione (cookie e così via) è isolato dall'app, i contenuti web non possono accedere ai dati dell'app.

Aggiungi elemento WebView

L'elemento webview deve includere l'URL ai contenuti di origine e specificarne le dimensioni.

<webview src="http://news.google.com/" width="640" height="480"></webview>

Aggiorna proprietà

Per modificare in modo dinamico le proprietà src, width e height di un tag webview, puoi impostarle direttamente nell'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/');

Contenuti sandbox locali

La limitazione tramite sandbox consente di pubblicare pagine specifiche in un'origine univoca con sandbox. Queste pagine vengono quindi esenti dai rispettivi criteri di sicurezza del contenuto. Le pagine con sandbox possono utilizzare iframe, scripting incorporato e eval(). Consulta la descrizione del campo manifest per sandbox.

Tuttavia, si tratta di un compromesso: le pagine con sandbox non possono utilizzare Chrome.* API Se devi svolgere operazioni come eval(), segui questa procedura per essere esente da CSP, ma non potrai utilizzare le novità straordinarie.

Utilizzare gli script incorporati nella sandbox

Ecco una pagina di esempio 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 la sandbox nel file manifest

Devi includere il campo sandbox nel 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 si apre la pagina con sandbox. Di seguito è riportato un esempio che crea due finestre, una per la finestra principale dell'app senza sandbox e una per la 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 in una pagina dell'app

Le pagine con sandbox possono essere incorporate anche all'interno di 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 è suddiviso in due parti: devi pubblicare un messaggio dalla pagina/finestra del mittente e attendere i messaggi nella pagina/finestra di ricezione.

Messaggio post

Puoi utilizzare postMessage per comunicare tra la tua app e i contenuti sandbox. Ecco uno script in background di esempio che pubblica un messaggio nella pagina con sandbox che viene aperta:

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, è preferibile specificare l'origine esatta da cui viene inviato il messaggio. Le app di Chrome non hanno accesso all'origine univoca dei contenuti con sandbox, quindi puoi inserire nella lista consentita tutte le origini solo come origini accettabili ("*"). Sull'estremità ricevente in genere vuoi controllare l'origine, ma poiché sono contenuti i contenuti delle app di Chrome, non è necessario. Per scoprire di più, consulta window.postMessage.

Ascolta il messaggio e rispondi

Di seguito è riportato un esempio di destinatario di messaggi che viene aggiunto alla 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, consulta l'esempio di sandbox.