Contenu externe

Le modèle de sécurité des applications Chrome interdit le contenu externe dans les cadres iFrame ainsi que l'utilisation des scripts intégrés et des eval(). Vous pouvez ignorer ces restrictions, mais votre contenu externe doit être isolé de l'application.

Le contenu isolé ne peut pas accéder directement aux données de l'application ni à aucune API. Utilisez des requêtes XMLHttpRequest multi-origines et des messages post-message pour communiquer entre la page d'événement et le contenu en bac à sable, et accéder indirectement aux API.

Référencer des ressources externes

La Content Security Policy utilisée par les applications interdit l'utilisation de nombreux types d'URL distantes. Vous ne pouvez donc pas référencer directement des images, des feuilles de style ou des polices externes à partir de la page d'une application. À la place, vous pouvez utiliser des requêtes XMLHttpRequest multi-origines pour récupérer ces ressources, puis les diffuser via des URL blob:.

Exigence du fichier manifeste

Pour pouvoir effectuer des requêtes XMLHttpRequest multi-origines, vous devez ajouter une autorisation pour l'hôte de l'URL distante:

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

XMLHttpRequest multi-origine

Récupérez l'URL distante dans l'application et diffusez son contenu en tant qu'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();

Vous pouvez enregistrer ces ressources localement, afin qu'elles soient disponibles hors connexion.

Intégrer des pages Web externes

La balise webview vous permet d'intégrer du contenu Web externe dans votre application, par exemple une page Web. Elle remplace les cadres iFrame qui pointent vers des URL distantes, qui sont désactivés dans les applications Chrome. Contrairement aux cadres iFrame, la balise webview s'exécute dans un processus distinct. Cela signifie qu'un exploit qu'il contient restera isolé et ne pourra pas obtenir de privilèges élevés. De plus, comme son stockage (cookies, etc.) est isolé de l'application, le contenu Web n'a aucun moyen d'accéder aux données de l'application.

Ajouter un élément WebView

Votre élément webview doit inclure l'URL du contenu source et spécifier ses dimensions.

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

Mettre à jour les propriétés

Pour modifier de manière dynamique les propriétés src, width et height d'un tag webview, vous pouvez définir ces propriétés directement dans l'objet JavaScript ou utiliser la fonction DOM setAttribute.

document.querySelector('#mywebview').src =
    'http://blog.chromium.org/';
// or
document.querySelector('#mywebview').setAttribute(
    'src', 'http://blog.chromium.org/');

Contenu local dans le bac à sable

Le système de bac à sable permet de diffuser des pages spécifiées dans une origine unique en bac à sable. Ces pages sont alors exemptées de Content Security Policy. Les pages en bac à sable peuvent utiliser des iFrames, des scripts intégrés et eval(). Consultez la description du champ "Manifest" pour sandbox.

Toutefois, c'est un compromis: les pages en bac à sable ne peuvent pas utiliser Chrome*. API Si vous devez effectuer des opérations comme eval(), utilisez cette route pour être exempt de CSP, mais vous ne pourrez pas utiliser ces nouvelles fonctionnalités.

Utiliser des scripts intégrés dans un environnement de bac à sable

Voici un exemple de page en bac à sable qui utilise un script intégré et eval():

<html>
  <body>
    <h1>Woot</h1>
    <script>
      eval('console.log(\'I am an eval-ed inline script.\')');
    </script>
  </body>
</html>

Inclure le bac à sable dans le fichier manifeste

Vous devez inclure le champ sandbox dans le fichier manifeste et répertorier les pages de l'application à diffuser dans un bac à sable:

"sandbox": {
  "pages": ["sandboxed.html"]
}

Ouverture d'une page en bac à sable dans une fenêtre

Comme pour les autres pages d'une application, vous pouvez créer une fenêtre dans laquelle s'ouvre la page en bac à sable. Voici un exemple qui crée deux fenêtres, l'une pour la fenêtre principale de l'application qui n'est pas en bac à sable et l'autre pour la page en bac à sable:

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
    }
  });
});

Intégrer une page en bac à sable à la page d'une application

Les pages en bac à sable peuvent également être intégrées à une autre page d'application à l'aide d'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>

Envoyer des messages vers des pages en bac à sable

L'envoi d'un message se fait en deux étapes: vous devez publier un message à partir de la page ou de la fenêtre de l'expéditeur et l'écouter sur la page ou la fenêtre de réception.

Publier le message

Vous pouvez utiliser postMessage pour communiquer entre votre application et le contenu en bac à sable. Voici un exemple de script d'arrière-plan qui publie un message sur la page en bac à sable qu'il ouvre:

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.', '*');
     });
});

Sur le Web, il est généralement préférable de spécifier l'origine exacte du message. Les applications Chrome n'ont pas accès à l'origine unique du contenu en bac à sable. Vous pouvez donc uniquement ajouter toutes les origines en tant qu'origines acceptables ("*"). Du côté de la réception, vous souhaitez généralement vérifier l'origine. Toutefois, comme le contenu des applications Chrome est contenu, cela n'est pas nécessaire. Pour en savoir plus, consultez window.postMessage.

Écouter le message et y répondre

Voici un exemple de destinataire de message ajouté à votre page en bac à sable:

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);

Pour en savoir plus, consultez l'exemple sandbox.