Conteúdo externo

O modelo de segurança de apps do Chrome não permite conteúdo externo em iframes e o uso de scripts in-line e eval(). É possível modificar essas restrições, mas o conteúdo externo precisa ser isolado do app.

O conteúdo isolado não pode acessar diretamente os dados do app ou as APIs. Use XMLHttpRequests e mensagens pós-mensagens de origem cruzada para estabelecer a comunicação entre a página do evento e o conteúdo no sandbox e acessar as APIs indiretamente.

Referência a recursos externos

A Política de Segurança de Conteúdo usada pelos apps proíbe o uso de vários tipos de URLs remotos. Portanto, não é possível fazer referência direta a imagens, folhas de estilo ou fontes externas de uma página do app. Em vez disso, use XMLHttpRequests de origem cruzada para buscar esses recursos e exibi-los por URLs blob:.

Requisito do manifesto

Para fazer XMLHttpRequests de origem cruzada, adicione uma permissão para o host do URL remoto:

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

XMLHttpRequest de origem cruzada

Busque o URL remoto no app e exiba o conteúdo dele como um 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();

Salve esses recursos localmente para que eles fiquem disponíveis off-line.

Incorporar páginas da Web externas

A tag webview permite incorporar conteúdo da Web externo no seu app, por exemplo, uma página da Web. Ela substitui iframes que apontam para URLs remotos, desativados nos apps do Chrome. Ao contrário dos iframes, a tag webview é executada em um processo separado. Isso significa que um exploit dentro dele ainda vai estar isolado e não poderá receber privilégios elevados. Além disso, como o armazenamento (cookies etc.) é isolado do app, o conteúdo da Web não pode acessar nenhum dado do app.

Adicionar elemento do WebView

Seu elemento webview precisa incluir o URL do conteúdo de origem e especificar as dimensões dele.

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

Atualizar propriedades

Para mudar dinamicamente as propriedades src, width e height de uma tag webview, defina essas propriedades diretamente no objeto JavaScript ou use a função DOM setAttribute.

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

Conteúdo local do sandbox

O sandbox permite que páginas especificadas sejam veiculadas em uma origem única e em sandbox. Essas páginas ficam, então, isentas da Política de Segurança de Conteúdo. As páginas no modo sandbox podem usar iframes, scripts in-line e eval(). Confira a descrição do campo do manifesto do sandbox.

No entanto, a desvantagem é que páginas no modo sandbox não podem usar o Chrome.* APIs Se você precisar realizar ações como eval(), siga este caminho para se isentar da CSP, mas não será possível usar os novos recursos interessantes.

Usar scripts in-line no sandbox

Este é um exemplo de página no modo sandbox que usa um script in-line e eval():

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

Incluir sandbox no manifesto

É necessário incluir o campo sandbox no manifesto e listar as páginas do app que vão ser exibidas em um sandbox:

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

Como abrir uma página no modo sandbox em uma janela

Assim como em qualquer outra página de aplicativo, você pode criar uma janela que a página no modo sandbox seja aberta. Veja um exemplo que cria duas janelas, uma para a janela principal do app que não está no sandbox e outra para a página no modo 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
    }
  });
});

Como incorporar uma página no sandbox a uma página de um app

As páginas no modo sandbox também podem ser incorporadas a outra página de app usando um 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>

Enviar mensagens para páginas no modo sandbox

O envio de uma mensagem tem duas partes: você precisa postar uma mensagem na página/janela do remetente e ouvir as mensagens na página/janela de recebimento.

Postar mensagem

Você pode usar postMessage para a comunicação entre o app e o conteúdo no sandbox. Veja um exemplo de script em segundo plano que publica uma mensagem na página no modo sandbox que é aberta:

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

De modo geral na Web, é recomendado especificar a origem exata de onde a mensagem é enviada. Os apps do Chrome não têm acesso à origem exclusiva do conteúdo no sandbox. Portanto, só é possível colocar todas as origens na lista de permissões como origens aceitáveis ("*"). Na extremidade de recebimento, geralmente convém verificar a origem, mas, como o conteúdo dos apps do Chrome está contido, isso não é necessário. Para saber mais, consulte window.postMessage (link em inglês).

Ouvir mensagem e responder

Veja um exemplo de destinatário de mensagem que é adicionado à sua página no modo 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);

Para mais detalhes, confira o exemplo de sandbox.