Conteúdo externo

O modelo de segurança dos apps do Chrome não permite o uso de conteúdo externo em iframes e o uso de inline scripting e eval(). É possível substituir essas restrições, mas o conteúdo externo precisa ser isolados do app.

O conteúdo isolado não pode acessar diretamente os dados do app ou as APIs. Usar origem cruzada XMLHttpRequests e pós-mensagem para 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. não podem fazer referência direta a imagens, folhas de estilo ou fontes externas da página de um aplicativo. Em vez disso, você pode use XMLHttpRequests de origem cruzada para buscar esses recursos e, em seguida, disponibilizá-los por meio de URLs blob:.

Requisito do manifesto

Para fazer XMLHttpRequests de origem cruzada, você precisará adicionar uma permissão para o URL remoto host:

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

É recomendável salvar esses recursos localmente para que fiquem disponíveis off-line.

Incorporar páginas da Web externas

Com a tag webview, você pode incorporar conteúdo externo da Web no seu app, como uma página da Web página. Ela substitui iframes que apontam para URLs remotos, que são desativados nos apps do Chrome. Não gostei iframes, a tag webview é executada em um processo separado. Isso significa que uma exploração dentro dele ficará isolado e não poderá receber privilégios elevados. Além disso, como seu armazenamento (cookies, etc.) é isolado do aplicativo, não há como o conteúdo da Web acessar nenhum dos dados do app.

Adicionar elemento WebView

Seu elemento webview precisa incluir o URL para o 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, faça o seguinte: 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 de sandbox

O sandbox permite que páginas especificadas sejam veiculadas em uma origem exclusiva e em sandbox. Essas páginas são então isentos da própria Política de Segurança de Conteúdo. As páginas no sandbox podem usar iframes, scripts inline e eval(): Confira a descrição do campo do manifesto do sandbox.

Mas há uma desvantagem: páginas no sandbox não podem usar o Chrome.* APIs Se você precisar fazer coisas como eval(), siga este caminho para ficar isento da CSP, mas você não poderá usar os recursos novos e legais.

Usar scripts inline no sandbox

Confira 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 a serem exibidas em um sandbox:

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

Abrir uma página no modo sandbox em uma janela

Assim como qualquer outra página do app, você pode criar uma janela na qual a página no modo sandbox é aberta. Confira 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 em sandbox a uma página de aplicativo

As páginas no sandbox também podem ser incorporadas a outro 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>

Como enviar mensagens para páginas no sandbox

O envio de uma mensagem tem duas partes: é necessário postar uma mensagem pela página/janela do remetente, e detectar mensagens na página/janela de recebimento.

Postar mensagem

É possível usar postMessage para a comunicação entre o app e o conteúdo no sandbox. Aqui está um exemplo script em segundo plano que publica uma mensagem na página no 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, o recomendado é especificar a origem exata de onde a mensagem é enviada. Como os apps do Chrome não têm acesso à origem exclusiva do conteúdo no sandbox, você só pode autorizar todos origens aceitáveis ('*'). No receptor, verifique a origem. mas como o conteúdo dos Aplicativos do Google Chrome está incluído, isso não é necessário. Para saber mais, consulte window.postMessage.

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 do sandbox.