外部內容

Chrome 應用程式安全性模型禁止 iframe 中的外部內容,並且使用內嵌指令碼和 eval()。您可以覆寫這些限制,但您的外部內容必須從應用程式隔離。

隔離的內容無法直接存取應用程式的資料或任何 API。使用跨來源 XMLHttpRequests 和訊息後傳遞,在事件頁面和沙箱內容之間進行通訊,並間接存取 API。

參照外部資源

應用程式使用的內容安全政策禁止使用多種遠端網址,因此您無法直接參照應用程式頁面上的外部圖片、樣式表或字型。請改用跨來源 XMLHttpRequests 擷取這些資源,然後透過 blob: 網址提供。

資訊清單規定

如要執行跨來源 XMLHttpRequests 操作,您必須新增遠端網址主機的權限:

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

跨來源 XMLHttpRequest

在應用程式中擷取遠端網址,並以 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();

建議您將這些資源儲存至本機,以便離線使用。

嵌入外部網頁

webview 標記可讓您在應用程式 (例如網頁) 中嵌入外部網頁內容。它會取代指向遠端網址的 iframe,後者已在 Chrome 應用程式中停用。與 iframe 不同,webview 代碼會在獨立程序中執行。也就是說,漏洞內部的漏洞會遭到隔離,而且無法獲得進階權限。此外,由於其儲存空間 (Cookie 等) 與應用程式隔離,因此網頁內容無法存取應用程式的任何資料。

新增 WebView 元素

webview 元素必須包含來源內容的網址並指定其尺寸。

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

更新房源

如要動態變更 webview 標記的 srcwidthheight 屬性,您可以直接在 JavaScript 物件上設定這些屬性,或使用 setAttribute DOM 函式。

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

沙箱本機內容

沙箱功能可讓指定網頁在沙箱專屬來源中提供。如此一來,這些網頁 就不受其《內容安全政策》規範。沙箱頁面可以使用 iframe、內嵌指令碼和 eval()。請查看 sandbox 的資訊清單欄位說明。

不過,權衡利弊:採用沙箱機制的網頁無法使用 Chrome*。相互整合如果您需要執行 eval() 等操作,請將這個路徑從 CSP 中排除,但您將無法使用酷炫的新內容。

在沙箱中使用內嵌指令碼

以下是使用內嵌指令碼和 eval() 的沙箱網頁範例:

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

在資訊清單中加入沙箱

您必須在資訊清單中加入 sandbox 欄位,並列出要在沙箱中提供的應用程式頁面:

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

在視窗中開啟沙箱頁面

就像任何其他應用程式頁面一樣,您可以建立一個視窗,用來開啟沙箱頁面。以下範例會建立兩個視窗,一個用於未採用沙箱機制的主要應用程式視窗,另一個則用於沙箱頁面:

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

在應用程式頁面中嵌入沙箱頁面

您也可以使用 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>

傳送訊息給沙箱頁面

傳送訊息的程序分為兩個部分:您需要從寄件者頁面/視窗張貼訊息,並在接收頁面/視窗中監聽訊息。

張貼訊息

您可以使用 postMessage 在應用程式和沙箱內容之間進行通訊。以下的背景指令碼範例可將訊息張貼至沙箱開啟的網頁:

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

一般來說,當您在網路上想指定訊息的傳送來源時,會想指定確切的傳送來源。Chrome 應用程式無法存取沙箱內容的唯一來源,因此您只能將所有來源加入許可清單為可接受的來源 (「*」)。在接收端時,一般會想要檢查來源,但由於 Chrome 應用程式已包含,因此不一定要這麼做。詳情請參閱 window.postMessage

聽取訊息及回覆

以下是新增至沙箱頁面的訊息接收器範例:

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

詳情請參閱sandbox範例。