Chrome 应用安全模型既禁止在 iframe 中使用外部内容,也禁止使用内嵌内容
脚本和 eval()
。你可以覆盖这些限制,但外部内容必须
与应用隔离开来
隔离的内容无法直接访问应用的数据或任何 API。使用跨源 以及通过 XMLHttpRequests 和后消息在事件页面和沙盒化内容之间进行通信 间接访问 API
引用外部资源
应用使用的内容安全政策禁止使用多种远程网址,因此
无法直接引用应用页面中的外来图片、样式表或字体。相反,您可以
使用跨源 XMLHttpRequest 获取这些资源,然后通过 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
标记,您可以在应用中嵌入外部 Web 内容,例如 Web
页面。它取代了指向远程网址的 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。*API。如果您需要执行诸如
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);
如需了解详情,请参阅沙盒示例。