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
標記的 src
、width
和 height
屬性,您可以直接在 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範例。