โมเดลความปลอดภัยของแอป Chrome ไม่อนุญาตให้แสดงเนื้อหาภายนอกใน iframe รวมถึงการใช้สคริปต์ในหน้าและ eval()
คุณลบล้างข้อจำกัดเหล่านี้ได้ แต่ต้องแยกเนื้อหาภายนอกออกจากแอป
เนื้อหาที่แยกไม่สามารถเข้าถึงข้อมูลของแอปหรือ API ใดๆ ได้โดยตรง ใช้ XMLHttpRequests แบบข้ามต้นทางและหลังการรับส่งข้อความเพื่อสื่อสารระหว่างหน้าเหตุการณ์และเนื้อหาที่ทำแซนด์บ็อกซ์ รวมถึงเข้าถึง API โดยอ้อม
การอ้างอิงแหล่งข้อมูลภายนอก
นโยบายรักษาความปลอดภัยเนื้อหาที่แอปใช้ไม่อนุญาตให้ใช้ URL ระยะไกลหลายประเภท คุณจึงไม่สามารถอ้างอิงรูปภาพภายนอก สไตล์ชีต หรือแบบอักษรจากหน้าแอปได้โดยตรง แต่คุณสามารถใช้ XMLHttpRequests แบบข้ามต้นทางเพื่อดึงทรัพยากรเหล่านี้ แล้วแสดงผ่าน URL blob:
แทนได้
ข้อกำหนดเกี่ยวกับไฟล์ Manifest
หากต้องการทำ XMLHttpRequests แบบข้ามต้นทางได้ คุณจะต้องเพิ่มสิทธิ์สำหรับโฮสต์ของ URL ระยะไกล ดังนี้
"permissions": [
"...",
"https://supersweetdomainbutnotcspfriendly.com/"
]
XMLHttpRequest แบบข้ามต้นทาง
ดึงข้อมูล URL ระยะไกลลงในแอปและแสดงเนื้อหาเป็น 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();
คุณอาจต้องบันทึกทรัพยากรเหล่านี้ไว้ในเครื่องเพื่อให้ใช้งานแบบออฟไลน์ได้
ฝังหน้าเว็บภายนอก
แท็ก webview
ช่วยให้คุณฝังเนื้อหาเว็บภายนอกในแอป เช่น หน้าเว็บ ได้ จะแทนที่ iframe ที่ชี้ไปยัง URL ระยะไกล และปิดใช้ภายในแอป Chrome แท็ก webview
ทำงานในกระบวนการที่แยกต่างหาก ซึ่งต่างจาก iframe ซึ่งหมายความว่าการเจาะช่องโหว่ภายในเนื้อหาดังกล่าวจะยังคงถูกแยกออก
และจะไม่ได้รับสิทธิ์ในระดับสูงขึ้น นอกจากนี้ เนื่องจากพื้นที่เก็บข้อมูล (คุกกี้ ฯลฯ) จะแยกออกจากแอป เนื้อหาเว็บจะไม่สามารถเข้าถึงข้อมูลของแอปได้
เพิ่มองค์ประกอบ WebView
องค์ประกอบ webview
ต้องมี URL ไปยังเนื้อหาแหล่งที่มาและระบุขนาด
<webview src="http://news.google.com/" width="640" height="480"></webview>
อัปเดตที่พัก
หากต้องการเปลี่ยนพร็อพเพอร์ตี้ src
, width
และ height
ของแท็ก webview
แบบไดนามิก คุณจะตั้งค่าพร็อพเพอร์ตี้เหล่านั้นโดยตรงในออบเจ็กต์ JavaScript หรือใช้ฟังก์ชัน setAttribute
DOM ก็ได้
document.querySelector('#mywebview').src =
'http://blog.chromium.org/';
// or
document.querySelector('#mywebview').setAttribute(
'src', 'http://blog.chromium.org/');
เนื้อหาในเครื่องแซนด์บ็อกซ์
แซนด์บ็อกซ์ช่วยให้หน้าที่ระบุแสดงในต้นทางที่ไม่ซ้ำกันและมีแซนด์บ็อกซ์ จากนั้นหน้าเหล่านี้จะได้รับการยกเว้นจากนโยบายรักษาความปลอดภัยเนื้อหา หน้าแซนด์บ็อกซ์จะใช้ iframe, การเขียนสคริปต์ในหน้า และ eval()
ได้ ดูคำอธิบายช่องไฟล์ Manifest ของ 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>
รวมแซนด์บ็อกซ์ในไฟล์ Manifest
คุณต้องใส่ช่อง sandbox
ในไฟล์ Manifest และระบุรายการหน้าแอปที่จะแสดงในแซนด์บ็อกซ์
"sandbox": {
"pages": ["sandboxed.html"]
}
การเปิดหน้าเว็บที่แซนด์บ็อกซ์ในหน้าต่าง
เช่นเดียวกับหน้าแอปอื่นๆ คุณสามารถสร้างหน้าต่างสำหรับเปิดหน้าแซนด์บ็อกซ์ ตัวอย่างที่จะสร้างหน้าต่าง 2 บาน ได้แก่ หน้าต่างหนึ่งสำหรับหน้าต่างแอปหลักที่ไม่ได้ใช้แซนด์บ็อกซ์ และอีกหน้าต่างสำหรับหน้าที่ทำแซนด์บ็อกซ์
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>
การส่งข้อความไปยังหน้าที่ทำแซนด์บ็อกซ์
การส่งข้อความประกอบด้วย 2 ส่วน ได้แก่ คุณต้องโพสต์ข้อความจากหน้า/หน้าต่างของผู้ส่ง และฟังข้อความในหน้า/หน้าต่างที่เป็นผู้รับ
โพสต์ข้อความ
คุณใช้ 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