Apps Script ใช้แซนด์บ็อกซ์ความปลอดภัยเพื่อมอบการแยกการป้องกันสำหรับ Google Workspaceแอปพลิเคชันในบางสถานการณ์ เราเลิกใช้โหมดแซนด์บ็อกซ์ทั้งหมดแล้ว ยกเว้น IFRAME
ตอนนี้แอปที่ใช้โหมดแซนด์บ็อกซ์รุ่นเก่าจะใช้โหมด IFRAME
ที่ใหม่กว่าโดยอัตโนมัติ
แอปที่ใช้โหมดที่เก่ากว่าเหล่านี้กับบริการ HTML ก่อนหน้านี้อาจต้องทำการเปลี่ยนแปลงสำหรับโหมด IFRAME
เพื่อจัดการกับความแตกต่างต่อไปนี้
- ตอนนี้คุณต้องลบล้างแอตทริบิวต์
target
ของลิงก์โดยใช้target="_top"
หรือtarget="_blank"
- ไฟล์ HTML ที่แสดงผลโดยบริการ HTML ต้องมีแท็ก <!DOCTYPE html>, <html> และ <body>
- ไลบรารีตัวโหลดเนทีฟของ Google
api.js
ไม่โหลดโดยอัตโนมัติในโหมดIFRAME
- ผู้ใช้เครื่องมือเลือกจะต้องเรียกใช้
setOrigin()
เนื่องจากเนื้อหาจะแสดงจากโดเมนใหม่ - เบราว์เซอร์รุ่นเก่าบางเบราว์เซอร์ รวมถึง IE9 ไม่ได้รับการสนับสนุน
- ตอนนี้ทรัพยากรที่นำเข้าต้องใช้ HTTPS
- ระบบไม่ได้ป้องกันการส่งแบบฟอร์มโดยค่าเริ่มต้นแล้ว
ความแตกต่างเหล่านี้จะอธิบายรายละเอียดในส่วนต่อไปนี้
การตั้งค่าแอตทริบิวต์เป้าหมายของลิงก์
ในโหมด IFRAME
คุณต้องตั้งค่าแอตทริบิวต์เป้าหมายของลิงก์เป็น _top
หรือ _blank
ดังนี้
Code.js
function doGet() {
var template = HtmlService.createTemplateFromFile('top');
return template.evaluate();
}
top.html
<!DOCTYPE html>
<html>
<body>
<div>
<a href="http://google.com" target="_top">Click Me!</a>
</div>
</body>
</html>
คุณยังสามารถลบล้างแอตทริบิวต์นี้ได้โดยใช้แท็ก <base> ภายในส่วนหัวของหน้าเว็บที่ล้อมรอบอยู่
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div>
<a href="http://google.com">Click Me!</a>
</div>
</body>
</html>
แท็ก HTML ระดับบนสุด
ในโหมดแซนด์บ็อกซ์ NATIVE
(และ EMULATED
) ระบบจะเพิ่มแท็ก HTML บางรายการลงในไฟล์ .html ของ Apps Script โดยอัตโนมัติ แต่กรณีนี้จะไม่เกิดขึ้นเมื่อใช้โหมด IFRAME
รวมเนื้อหาหน้าเว็บไว้ในแท็กระดับบนสุดต่อไปนี้เพื่อให้หน้าโปรเจ็กต์แสดงอย่างถูกต้องโดยใช้ IFRAME
<!DOCTYPE html>
<html>
<body>
<!-- Add your HTML content here -->
</body>
</html>
ต้องโหลดไลบรารีตัวโหลด JavaScript แบบเนทีฟอย่างชัดเจน
ต้องเปลี่ยนสคริปต์ที่อาศัยการโหลดอัตโนมัติของไลบรารีตัวโหลดเนทีฟ api.js
เพื่อโหลดไลบรารีนี้อย่างชัดเจน ตามตัวอย่างต่อไปนี้
<script src="https://apis.google.com/js/api.js?onload=onApiLoad">
</script>
การเปลี่ยน Google Picker API
เมื่อใช้ Google Picker API คุณจะต้องเรียกใช้ setOrigin()
เมื่อสร้าง PickerBuilder และส่งในต้นทาง google.script.host.origin
ดังที่แสดงในตัวอย่างต่อไปนี้
function createPicker(oauthToken) {
var picker = new google.picker.PickerBuilder()
.addView(google.picker.ViewId.SPREADSHEETS) // Or a different ViewId
.setOAuthToken(oauthToken)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.setOrigin(google.script.host.origin) // Note the setOrigin
.build();
picker.setVisible(true);
}
ดูตัวอย่างที่ใช้งานได้ทั้งหมดได้ที่กล่องโต้ตอบการเปิดไฟล์
การสนับสนุนเบราว์เซอร์
โหมดแซนด์บ็อกซ์ IFRAME
อิงตามฟีเจอร์แซนด์บ็อกซ์ของ iframe ใน HTML5
เบราว์เซอร์รุ่นเก่าบางรุ่นไม่มีการสนับสนุน เช่น Internet Explorer 9 ปัญหานี้อาจเกิดขึ้นหากโปรเจ็กต์ Apps Script ของคุณมีทั้ง 2 อย่างดังนี้
- ใช้
HtmlService
และ - ใช้การแซนด์บ็อกซ์
EMULATED
หรือNATIVE
ก่อนหน้านี้
การย้ายข้อมูลแอปเหล่านี้ไปยังโหมดแซนด์บ็อกซ์ IFRAME
หมายความว่าแอปอาจไม่ทำงานในเบราว์เซอร์รุ่นเก่าบางเบราว์เซอร์ (โดยเฉพาะ IE9 และรุ่นก่อนหน้า) ที่ไม่รองรับฟีเจอร์แซนด์บ็อกซ์ด้วย iframe ของ HTML5 อีกต่อไป
แอปที่ขอโหมด IFRAME
อยู่แล้วหรือไม่ได้ใช้ HtmlService
เลยจะไม่ได้รับผลกระทบจากปัญหานี้
ตอนนี้ต้องใช้ HTTPS สำหรับทรัพยากรที่นำเข้า
แอปพลิเคชันก่อนหน้านี้ซึ่งนำเข้าทรัพยากรโดยใช้ HTTP ต้องเปลี่ยนไปใช้ HTTPS แทน
ระบบไม่ได้ป้องกันการส่งแบบฟอร์มโดยค่าเริ่มต้นแล้ว
ในส่วน NATIVE
แบบฟอร์ม HTML แซนด์บ็อกซ์ ไม่สามารถส่งและไปยังส่วนต่างๆ ของหน้าเว็บได้จริง นักพัฒนาซอฟต์แวร์จึงสามารถเพิ่มแฮนเดิล onclick
ลงในปุ่มส่งได้ง่ายๆ โดยไม่ต้องกังวลว่าจะเกิดอะไรขึ้นหลังจากนั้น
เมื่อใช้โหมด IFRAME
ระบบจะอนุญาตให้ส่งแบบฟอร์ม HTML ได้ และหากองค์ประกอบแบบฟอร์มไม่ได้ระบุแอตทริบิวต์ action
ไว้ ระบบจะส่งข้อมูลไปยังหน้าว่าง
ที่แย่กว่านั้นคือ iframe ภายในจะเปลี่ยนเส้นทางไปยังหน้าว่างก่อนที่แฮนเดิล onclick
จะมีโอกาสดำเนินการจนเสร็จ
วิธีแก้ไขคือให้เพิ่มโค้ด JavaScript ลงในหน้าเว็บเพื่อป้องกันไม่ให้องค์ประกอบแบบฟอร์มส่งจริงๆ เพื่อให้เครื่องจัดการการคลิกมีเวลาทำงาน ดังนี้
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
</script>
ดูตัวอย่างที่สมบูรณ์ได้ในคู่มือ HtmlService การสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์