การย้ายข้อมูลไปยังโหมด IFRAME Sandbox

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 การสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์