โดยปกติจะใช้
<iframe>
องค์ประกอบเพื่อฝังทรัพยากรภายนอกภายในบริบทการเรียกดู
Iframe จะบังคับใช้นโยบายความปลอดภัยของเว็บโดยการแยกเนื้อหาที่ฝังแบบข้ามต้นทางออกจากหน้าโฮสต์และในทางกลับกัน แม้ว่าวิธีนี้จะช่วยเพิ่มความปลอดภัย
ด้วยการสร้างขอบเขตที่ปลอดภัยระหว่างต้นทาง แต่ก็จำกัดกรณีการใช้งานบางอย่าง ตัวอย่างเช่น ผู้ใช้อาจต้องโหลดและจัดการเนื้อหาจากแหล่งที่มาต่างๆ แบบไดนามิก เช่น ครูเรียกใช้เหตุการณ์การนำทางเพื่อแสดงหน้าเว็บบนหน้าจอห้องเรียน อย่างไรก็ตาม เว็บไซต์จำนวนมากบล็อกการฝังใน iframe อย่างชัดเจน
โดยใช้ส่วนหัวด้านความปลอดภัย เช่น X-Frame-Options และนโยบายรักษาความปลอดภัยเนื้อหา (CSP)
นอกจากนี้ ข้อจำกัดของ iframe ยังป้องกันไม่ให้หน้าเว็บที่ฝังจัดการการนำทางหรือลักษณะการทำงานของเนื้อหาที่ฝังโดยตรง
Controlled Frame API แก้ไขข้อจำกัดนี้โดยอนุญาตให้โหลด เนื้อหาเว็บใดก็ได้ แม้ว่าจะบังคับใช้นโยบายการฝังที่จำกัดก็ตาม API นี้พร้อมใช้งานเฉพาะภายใน Isolated Web Application (IWA) ซึ่งมี มาตรการรักษาความปลอดภัยเพิ่มเติมเพื่อปกป้องทั้งผู้ใช้และนักพัฒนาแอปจาก ความเสี่ยงที่อาจเกิดขึ้น
ใช้ Controlled Frame
ก่อนใช้เฟรมที่ควบคุม คุณจะต้องตั้งค่า IWA ที่ใช้งานได้ จากนั้นคุณจะผสานรวม เฟรมที่ควบคุมแล้วเข้ากับหน้าเว็บได้
เพิ่มนโยบายสิทธิ์
หากต้องการใช้เฟรมที่ควบคุมได้ ให้เปิดใช้สิทธิ์ที่เกี่ยวข้องโดยเพิ่มฟิลด์
permissions_policy
ที่มีค่า "controlled-frame"
ลงในไฟล์ Manifest ของ IWA
นอกจากนี้ ยังรวมถึงคีย์
cross-origin-isolated
ด้วย คีย์นี้ไม่ได้เจาะจงสำหรับเฟรมที่ควบคุม แต่จำเป็นสำหรับ IWA ทั้งหมด
และกำหนดว่าเอกสารจะเข้าถึง API ที่ต้องมีการแยกต้นทางข้ามได้หรือไม่
{
...
"permissions_policy": {
...
"controlled-frame": ["self"],
"cross-origin-isolated": ["self"]
...
}
...
}
คีย์ controlled-frame
ในไฟล์ Manifest ของ Isolated Web App (IWA) จะกำหนด
รายการที่อนุญาตของนโยบายสิทธิ์ ซึ่งระบุต้นทางที่ใช้ Controlled
Frame ได้ แม้ว่าไฟล์ Manifest จะรองรับไวยากรณ์นโยบายสิทธิ์ทั้งหมด ซึ่งอนุญาตค่าต่างๆ เช่น *
, ต้นทางที่เฉพาะเจาะจง หรือคีย์เวิร์ด เช่น self
และ src
แต่สิ่งสำคัญที่ควรทราบคือคุณไม่สามารถมอบสิทธิ์ API เฉพาะ IWA ให้กับต้นทางอื่นๆ ได้
แม้ว่ารายการที่อนุญาตจะมีไวลด์การ์ดหรือต้นทางภายนอก สิทธิ์เหล่านี้
จะไม่มีผลกับฟีเจอร์ IWA เช่น controlled-frame
IWA จะตั้งค่าเริ่มต้นของฟีเจอร์ที่ควบคุมด้วยนโยบายเป็น "ไม่มี" ซึ่งต่างจากเว็บแอปมาตรฐาน
และต้องมีการประกาศอย่างชัดเจน สำหรับฟีเจอร์เฉพาะของ IWA หมายความว่าเฉพาะค่าอย่าง self
(ต้นทางของ IWA เอง) หรือ src
(ต้นทางของเฟรมที่ฝัง) เท่านั้นที่
มีผลในเชิงฟังก์ชัน
เพิ่มองค์ประกอบ Controlled Frame
แทรกองค์ประกอบ <controlledframe>
ลงใน HTML เพื่อฝังเนื้อหาของบุคคลที่สาม
ภายใน IWA
<controlledframe id="controlledframe_1" src="https://example.com">
</controlledframe>
แอตทริบิวต์ partition
ที่ไม่บังคับจะกำหนดค่าการแบ่งพาร์ติชันพื้นที่เก็บข้อมูลสำหรับเนื้อหาที่ฝังไว้
ซึ่งช่วยให้คุณแยกข้อมูล เช่น คุกกี้และพื้นที่เก็บข้อมูลในเครื่อง เพื่อคงข้อมูลไว้
ในเซสชันต่างๆ
ตัวอย่าง: พาร์ติชันพื้นที่เก็บข้อมูลในหน่วยความจำ
สร้างเฟรมที่ควบคุมโดยใช้พาร์ติชันที่เก็บข้อมูลในหน่วยความจำชื่อ
"session1"
ระบบจะล้างข้อมูลที่จัดเก็บไว้ในพาร์ติชันนี้ (เช่น คุกกี้และ
localStorage) เมื่อเฟรมถูกทำลายหรือเซสชันแอปพลิเคชัน
สิ้นสุดลง
<controlledframe id="controlledframe_1" src="https://example.com">
</controlledframe>
ตัวอย่าง: พาร์ติชันพื้นที่เก็บข้อมูลถาวร
สร้างเฟรมที่ควบคุมโดยใช้พาร์ติชันพื้นที่เก็บข้อมูลแบบถาวรชื่อ
"user_data"
คำนำหน้า "persist:"
ช่วยให้มั่นใจได้ว่าระบบจะบันทึกข้อมูลที่จัดเก็บไว้ในพาร์ติชันนี้ลงในดิสก์ และจะพร้อมใช้งานในเซสชันแอปพลิเคชันต่างๆ
<controlledframe id="frame_2" src="..." partition="persist:user_data">
</controlledframe>
รับการอ้างอิงองค์ประกอบ
รับการอ้างอิงถึงองค์ประกอบ <controlledframe>
เพื่อให้คุณโต้ตอบกับองค์ประกอบดังกล่าวได้เหมือนกับองค์ประกอบ HTML มาตรฐาน
const controlledframe = document.getElementById('controlledframe_1');
สถานการณ์และกรณีการใช้งานที่พบบ่อย
โดยทั่วไปแล้ว ให้เลือกเทคโนโลยีที่ดีที่สุดเพื่อตอบสนองความต้องการของคุณในขณะที่หลีกเลี่ยง
ความซับซ้อนที่ไม่จำเป็น ในช่วงไม่กี่ปีที่ผ่านมา Progressive Web App
(PWA) ได้ลด
ช่องว่างกับแอปที่มาพร้อมเครื่อง ทำให้เกิดประสบการณ์การใช้งานเว็บที่ทรงพลัง
หากเว็บแอปพลิเคชันจำเป็นต้องฝังเนื้อหาของบุคคลที่สาม เราขอแนะนำให้ลองใช้<iframe>
วิธีปกติก่อน หากข้อกำหนด
เกินความสามารถของ iframe เฟรมที่ควบคุมใน IWA อาจเป็นทางเลือกที่ดีที่สุด
กรณีการใช้งานที่พบบ่อยจะอธิบายไว้ในส่วนต่อไปนี้
การฝังเนื้อหาเว็บของบุคคลที่สาม
แอปพลิเคชันจำนวนมากจำเป็นต้องโหลดและแสดงเนื้อหาของบุคคลที่สามภายในอินเทอร์เฟซผู้ใช้ อย่างไรก็ตาม เมื่อมีเจ้าของเว็บแอปหลายรายเข้ามาเกี่ยวข้อง (ซึ่งเป็นสถานการณ์ที่พบบ่อยในแอปพลิเคชันแบบฝัง) การกำหนดนโยบายแบบครบวงจรที่สอดคล้องกันจะทำได้ยากขึ้น
เช่น การตั้งค่าความปลอดภัยอาจ
ป้องกันไม่ให้ <iframe>
แบบเดิมฝังเนื้อหาบางประเภท แม้ว่า
ธุรกิจจะมีเหตุผลที่ถูกต้องตามกฎหมายที่ต้องทำเช่นนั้นก็ตาม เฟรมที่ควบคุมได้ได้รับการออกแบบมาให้ข้ามข้อจำกัดเหล่านี้ ซึ่งต่างจากองค์ประกอบ <iframe>
จึงทำให้แอปพลิเคชันโหลดและแสดงเนื้อหาได้แม้ว่าเนื้อหานั้นจะห้าม
การฝังมาตรฐานอย่างชัดเจนก็ตาม
กรณีการใช้งาน
- งานนำเสนอใน Classroom: ครูใช้หน้าจอสัมผัสในชั้นเรียนเพื่อ สลับไปมาระหว่างแหล่งข้อมูลเพื่อการศึกษาที่ปกติจะบล็อกการฝัง iframe
- ป้ายดิจิทัลในร้านค้าปลีกหรือห้างสรรพสินค้า: คีออสก์ในห้างสรรพสินค้าจะแสดงเว็บไซต์จากร้านค้าต่างๆ สลับกันไป เฟรมที่ควบคุมจะช่วยให้หน้าเว็บเหล่านี้โหลดได้อย่างถูกต้อง แม้ว่าจะมีการจํากัดการฝังก็ตาม
ตัวอย่างโค้ด
Controlled Frame API ต่อไปนี้มีประโยชน์ในการจัดการเนื้อหาที่ฝัง
การนำทาง: Controlled Frame มีหลายวิธีในการจัดการและควบคุมการนำทางและประวัติการนำทางของเนื้อหาที่ฝังไว้โดยใช้โปรแกรม
แอตทริบิวต์ src
จะรับหรือตั้งค่า URL ของเนื้อหาที่แสดงในเฟรม
ซึ่งทำงานในลักษณะเดียวกับแอตทริบิวต์ HTML
controlledframe.src = "https://example.com";
เมธอด back()
จะย้อนกลับไป 1 ขั้นในประวัติของเฟรม Promise ที่ส่งคืนจะเปลี่ยนเป็นบูลีนที่ระบุว่าการนำทางสำเร็จหรือไม่
document.getElementById('backBtn').addEventListener('click', () => {
controlledframe.back().then((success) => {
console.log(`Back navigation ${success ? 'succeeded' : 'failed'}`); }).catch((error) => {
console.error('Error during back navigation:', error);
});
});
เมธอด forward()
จะไปยังขั้นตอนถัดไปในประวัติของเฟรม Promise ที่ส่งคืนจะเปลี่ยนเป็นบูลีนที่ระบุว่าการนำทางสำเร็จหรือไม่
document.getElementById('forwardBtn').addEventListener('click', () => {
controlledframe.forward().then((success) => {
console.log(`Forward navigation ${success ? 'succeeded' : 'failed'}`);
}).catch((error) => {
console.error('Error during forward navigation:', error);
});
});
เมธอด reload()
จะโหลดหน้าปัจจุบันในเฟรมซ้ำ
document.getElementById('reloadBtn').addEventListener('click', () => {
controlledframe.reload();
});
นอกจากนี้ เฟรมที่ควบคุมยังให้เหตุการณ์ที่ช่วยให้คุณติดตามวงจรทั้งหมดของคำขอการนำทางได้ ตั้งแต่การเริ่มต้นและการเปลี่ยนเส้นทางไปจนถึงการโหลดเนื้อหา การดำเนินการเสร็จสมบูรณ์ หรือการยกเลิก
loadstart
: เริ่มทำงานเมื่อการนำทางในเฟรมเริ่มต้นขึ้นloadcommit
: ทริกเกอร์เมื่อประมวลผลคำขอการนำทางแล้ว และเนื้อหาเอกสารหลักเริ่มโหลดcontentload
: ทริกเกอร์เมื่อเอกสารหลักและทรัพยากรที่จำเป็นโหลดเสร็จแล้ว (คล้ายกับ DOMContentLoaded)loadstop
: เริ่มทำงานเมื่อทรัพยากรทั้งหมดสำหรับหน้าเว็บ (รวมถึงเฟรมย่อย รูปภาพ) โหลดเสร็จแล้วloadabort
: ทริกเกอร์หากมีการยกเลิกการนำทาง (เช่น โดยการดำเนินการของผู้ใช้ หรือการนำทางอื่นที่เริ่มต้น)loadredirect
: เรียกใช้เมื่อมีการเปลี่ยนเส้นทางฝั่งเซิร์ฟเวอร์ในระหว่างการนำทาง
controlledframe.addEventListener('loadstart', (event) => {
console.log('Navigation started:', event.url);
// Example: Show loading indicator
});
controlledframe.addEventListener('loadcommit', (event) => {
console.log('Navigation committed:', event.url);
});
controlledframe.addEventListener('contentload', (event) => {
console.log('Content loaded for:', controlledframe.src);
// Example: Hide loading indicator, maybe run initial script
});
controlledframe.addEventListener('loadstop', (event) => {
console.log('All resources loaded for:', controlledframe.src);
});
controlledframe.addEventListener('loadabort', (event) => {
console.warn(`Navigation aborted: ${event.url}, Reason: ${event.detail.reason}`);
});
controlledframe.addEventListener('loadredirect', (event) => {
console.log(`Redirect detected: ${event.oldUrl} -> ${event.newUrl}`);
});
นอกจากนี้ คุณยังตรวจสอบและอาจสกัดกั้นการโต้ตอบหรือคำขอที่เฉพาะเจาะจง ซึ่งเริ่มต้นโดยเนื้อหาที่โหลดภายในเฟรมที่ควบคุมได้ เช่น ความพยายามที่จะ เปิดกล่องโต้ตอบ ขอสิทธิ์ หรือเปิดหน้าต่างใหม่
dialog
: ทริกเกอร์เมื่อเนื้อหาที่ฝังพยายามเปิดกล่องโต้ตอบ (alert, confirm, prompt) คุณจะได้รับรายละเอียดและตอบกลับได้consolemessage
: เรียกใช้เมื่อมีการบันทึกข้อความไปยังคอนโซลภายใน เฟรมpermissionrequest
: ทริกเกอร์เมื่อเนื้อหาที่ฝังไว้ขอสิทธิ์ (เช่น ข้อมูลตำแหน่งทางภูมิศาสตร์และการแจ้งเตือน) คุณจะได้รับรายละเอียดและสามารถ อนุญาตหรือปฏิเสธคำขอได้newwindow
: ทริกเกอร์เมื่อเนื้อหาที่ฝังพยายามเปิดหน้าต่างหรือแท็บใหม่ (เช่น ด้วย window.open หรือลิงก์ที่มีtarget="_blank"
) คุณจะได้รับรายละเอียดและสามารถจัดการหรือบล็อกการดำเนินการได้
controlledframe.addEventListener('dialog', (event) => {
console.log(Dialog opened: Type=${event.messageType}, Message=${event.messageText});
// You will need to respond, e.g., event.dialog.ok() or .cancel()
});
controlledframe.addEventListener('consolemessage', (event) => {
console.log(Frame Console [${event.level}]: ${event.message});
});
controlledframe.addEventListener('permissionrequest', (event) => {
console.log(Permission requested: Type=${event.permission});
// You must respond, e.g., event.request.allow() or .deny()
console.warn('Permission request needs handling - Denying by default');
if (event.request && event.request.deny) {
event.request.deny();
}
});
controlledframe.addEventListener('newwindow', (event) => {
console.log(New window requested: URL=${event.targetUrl}, Name=${event.name});
// Decide how to handle this, e.g., open in a new controlled frame and call event.window.attach(), ignore, or block
console.warn('New window request needs handling - Blocking by default');
});
นอกจากนี้ ยังมีเหตุการณ์การเปลี่ยนสถานะที่จะแจ้งให้คุณทราบเกี่ยวกับการเปลี่ยนแปลงที่เกี่ยวข้องกับสถานะการแสดงผลของเฟรมที่ควบคุมเอง เช่น การแก้ไขขนาดหรือระดับการซูม
sizechanged
: เรียกใช้เมื่อขนาดของเนื้อหาในเฟรมเปลี่ยนแปลงzoomchange
: เรียกใช้เมื่อระดับการซูมของเนื้อหาในเฟรมเปลี่ยนแปลง
controlledframe.addEventListener('sizechanged', (event) => {
console.log(Frame size changed: Width=${event.width}, Height=${event.height});
});
controlledframe.addEventListener('zoomchange', (event) => {
console.log(Frame zoom changed: Factor=${event.newZoomFactor});
});
วิธีการจัดเก็บข้อมูล: เฟรมที่ควบคุมได้มี API สำหรับการจัดการข้อมูลที่จัดเก็บ ไว้ในการแบ่งพาร์ติชันของเฟรม
ใช้ clearData()
เพื่อนำข้อมูลที่จัดเก็บไว้ทั้งหมดออก ซึ่งมีประโยชน์อย่างยิ่งสำหรับ
การรีเซ็ตเฟรมหลังจากเซสชันของผู้ใช้หรือการตรวจสอบสถานะที่สะอาด เมธอด
จะแสดงผล Promise ที่จะทำงานเมื่อการดำเนินการเสร็จสมบูรณ์ นอกจากนี้ คุณยังระบุตัวเลือกการกำหนดค่าต่อไปนี้ได้ด้วย (ไม่บังคับ)
types
: อาร์เรย์ของสตริงที่ระบุประเภทข้อมูลที่จะล้าง (เช่น['cookies', 'localStorage', 'indexedDB']
) หากไม่ระบุ โดยปกติแล้วระบบจะล้างข้อมูลประเภทที่เกี่ยวข้องทั้งหมดoptions
: ควบคุมกระบวนการล้าง เช่น การระบุช่วงเวลา โดยใช้พร็อพเพอร์ตี้ since (การประทับเวลาเป็นมิลลิวินาทีนับตั้งแต่ Epoch) เพื่อล้างเฉพาะ ข้อมูลที่สร้างขึ้นหลังจากเวลานั้น
ตัวอย่าง: ล้างพื้นที่เก็บข้อมูลทั้งหมดที่เชื่อมโยงกับเฟรมที่ควบคุม
function clearAllPartitionData() {
console.log('Clearing all data for partition:', controlledframe.partition);
controlledframe.clearData()
.then(() => {
console.log('Partition data cleared successfully.');
})
.catch((error) => {
console.error('Error clearing partition data:', error);
});
}
ตัวอย่าง: ล้างเฉพาะคุกกี้และ localStorage ที่สร้างขึ้นในชั่วโมงที่ผ่านมา
function clearRecentCookiesAndStorage() {
const oneHourAgo = Date.now() - (60 * 60 * 1000);
const dataTypesArray = ['cookies', 'localStorage'];
const dataTypesToClearObject = {};
for (const type of dataTypesArray) {
dataTypesToClearObject[type] = true;
}
const clearOptions = { since: oneHourAgo };
console.log(`Clearing ${dataTypesArray.join(', ')} since ${new Date(oneHourAgo).toISOString()}`); controlledframe.clearData(clearOptions, dataTypesToClearObject) .then(() => {
console.log('Specified partition data cleared successfully.');
}).catch((error) => {
console.error('Error clearing specified partition data:', error);
});
}
ขยายหรือดัดแปลงแอปพลิเคชันของบุคคลที่สาม
นอกเหนือจากการฝังแบบง่ายๆ แล้ว Controlled Frame ยังมีกลไกสำหรับ การฝัง IWA เพื่อควบคุมเนื้อหาเว็บของบุคคลที่สามที่ฝังไว้ คุณ สามารถเรียกใช้สคริปต์ภายในเนื้อหาที่ฝังไว้ สกัดกั้นคำขอของเครือข่าย และ ลบล้างเมนูตามบริบทเริ่มต้นได้ ทั้งหมดนี้อยู่ในสภาพแวดล้อมที่ปลอดภัยและแยกต่างหาก
กรณีการใช้งาน
- บังคับใช้การสร้างแบรนด์ในเว็บไซต์ของบุคคลที่สาม: แทรก CSS และ JavaScript ที่กำหนดเองลงในเว็บไซต์ที่ฝังไว้เพื่อใช้ธีมภาพที่สอดคล้องกัน
- จำกัดลักษณะการทำงานของการนำทางและลิงก์: สกัดกั้นหรือปิดใช้ลักษณะการทำงานของแท็กบางอย่าง
<a>
ด้วยการแทรกสคริปต์ - กู้คืนโดยอัตโนมัติหลังจากเกิดข้อขัดข้องหรือไม่มีการใช้งาน: ตรวจสอบเนื้อหาที่ฝังอยู่ เพื่อดูสถานะที่ล้มเหลว (เช่น หน้าจอว่าง ข้อผิดพลาดของสคริปต์) และ โหลดซ้ำหรือรีเซ็ตเซสชันโดยอัตโนมัติหลังจากหมดเวลา
ตัวอย่างโค้ด
การแทรกสคริปต์: ใช้ executeScript()
เพื่อแทรก JavaScript ลงในเฟรมที่ควบคุม ซึ่งจะช่วยให้คุณปรับแต่งลักษณะการทำงาน เพิ่มภาพซ้อนทับ หรือดึงข้อมูลจากหน้าเว็บของบุคคลที่สามที่ฝังไว้ได้ คุณระบุโค้ดแบบอินไลน์เป็นสตริง
หรืออ้างอิงไฟล์สคริปต์อย่างน้อย 1 ไฟล์ (ใช้เส้นทางที่เกี่ยวข้องภายในแพ็กเกจ IWA
) ได้ เมธอดจะแสดงผลลัพธ์เป็น Promise ที่จะเปลี่ยนเป็นผลลัพธ์ของการ
เรียกใช้สคริปต์ ซึ่งโดยปกติแล้วจะเป็นค่าของคำสั่งสุดท้าย
document.getElementById('scriptBtn').addEventListener('click', () => {
controlledframe.executeScript({
code: `document.body.style.backgroundColor = 'lightblue';
document.querySelectorAll('a').forEach(link => link.style.pointerEvents = 'none');
document.title; // Return a value
`,
// You can also inject files:
// files: ['./injected_script.js'],
}) .then((result) => {
// The result of the last statement in the script is usually returned.
console.log('Script execution successful. Result (e.g., page title):', result); }).catch((error) => {
console.error('Script execution failed:', error);
});
});
การแทรกสไตล์: ใช้ insertCSS()
เพื่อใช้สไตล์ที่กำหนดเองกับหน้าที่โหลด
ภายในเฟรมที่ควบคุม
document.getElementById('cssBtn').addEventListener('click', () => {
controlledframe.insertCSS({
code: `body { font-family: monospace; }`
// You can also inject files:
// files: ['./injected_styles.css']
})
.then(() => {
console.log('CSS injection successful.');
})
.catch((error) => {
console.error('CSS injection failed:', error);
});
});
การสกัดกั้นคำขอเครือข่าย: ใช้ WebRequest API เพื่อสังเกตและอาจแก้ไขคำขอเครือข่ายจากหน้าเว็บที่ฝังไว้ เช่น การบล็อกคำขอ การแก้ไขส่วนหัว หรือการบันทึกการใช้งาน
// Get the request object
const webRequest = controlledframe.request;
// Create an interceptor for a specific URL pattern
const interceptor = webRequest.createWebRequestInterceptor({
urlPatterns: ["*://evil.com/*"],
blocking: true,
includeHeaders: "all"
});
// Add a listener to block the request
interceptor.addEventListener("beforerequest", (event) => {
console.log('Blocking request to:', event.url);
event.preventDefault();
});
// Add a listener to modify request headers
interceptor.addEventListener("beforesendheaders", (event) => {
console.log('Modifying headers for:', event.url);
const newHeaders = new Headers(event.headers);
newHeaders.append('X-Custom-Header', 'MyValue');
event.setRequestHeaders(newHeaders);
});
การเพิ่มเมนูบริบทที่กำหนดเอง: ใช้ contextMenus
API เพื่อเพิ่ม นำออก และ
จัดการเมนูคลิกขวาที่กำหนดเองภายในเฟรมที่ฝัง ตัวอย่างนี้แสดงวิธีเพิ่มเมนู "คัดลอกข้อความที่เลือก" ที่กำหนดเองภายในเฟรมที่ควบคุม เมื่อเลือกข้อความ
และผู้ใช้คลิกขวา เมนูจะปรากฏขึ้น การคลิกปุ่มนี้จะคัดลอกข้อความที่เลือกไปยังคลิปบอร์ด ซึ่งช่วยให้โต้ตอบกับเนื้อหาที่ฝังได้ง่ายและเป็นมิตรกับผู้ใช้
const menuItemProperties = {
id: "copy-selection",
title: "Copy selection",
contexts: ["selection"],
documentURLPatterns: [new URLPattern({ hostname: '*.example.com'})]
};
// Create the context menu item using a promise
try {
await controlledframe.contextMenus.create(menuItemProperties);
console.log(`Context menu item "${menuItemProperties.id}" created successfully.`);
} catch (error) {
console.error(`Failed to create context menu item:`, error);
}
// Add a standard event listener for the 'click' event
controlledframe.contextMenus.addEventListener('click', (event) => {
if (event.menuItemId === "copy-selection" && event.selectionText) {
navigator.clipboard.writeText(event.selectionText)
.then(() => console.log("Text copied to clipboard."))
.catch(err => console.error("Failed to copy text:", err));
}
});
สาธิต
ดูภาพรวมของวิธีการของ Controlled Frame ได้ที่เดโม Controlled Frame
หรือคุณจะใช้ IWA Kitchen Sink ซึ่งเป็นแอปที่มีหลายแท็บ โดยแต่ละแท็บจะสาธิต IWA API ที่แตกต่างกัน เช่น เฟรมที่ควบคุม, Direct Sockets และอื่นๆ
บทสรุป
Controlled Frame เป็นวิธีที่มีประสิทธิภาพและปลอดภัยในการฝัง ขยาย และโต้ตอบ
กับเนื้อหาเว็บของบุคคลที่สามใน Isolated Web App (IWA) การเอาชนะข้อจำกัดของ iframe ทำให้เกิดความสามารถใหม่ๆ เช่น การเรียกใช้สคริปต์ภายในเนื้อหาที่ฝังไว้ การสกัดกั้นคำขอของเครือข่าย และการใช้เมนูบริบทที่กำหนดเอง ทั้งหมดนี้ยังคงขอบเขตการแยกที่เข้มงวดไว้ อย่างไรก็ตาม เนื่องจาก API เหล่านี้ให้การควบคุมเนื้อหาที่ฝังไว้อย่างละเอียด จึงมีข้อจำกัดด้านความปลอดภัยเพิ่มเติมและพร้อมใช้งานภายใน IWA เท่านั้น ซึ่งออกแบบมาเพื่อรับประกันที่แข็งแกร่งยิ่งขึ้นสำหรับทั้งผู้ใช้และนักพัฒนาแอป สำหรับกรณีการใช้งานส่วนใหญ่ นักพัฒนาแอปควรพิจารณาใช้<iframe>
องค์ประกอบมาตรฐาน
ก่อน ซึ่งมีความเรียบง่ายและเพียงพอในหลายๆ สถานการณ์ ควรประเมินเฟรมที่ควบคุมเมื่อโซลูชันที่อิงตาม iframe ถูกบล็อกโดยข้อจำกัดในการฝังหรือไม่มีความสามารถในการควบคุมและการโต้ตอบที่จำเป็น
ไม่ว่าคุณจะสร้างประสบการณ์การใช้งานคีออสก์ ผสานรวมเครื่องมือของบุคคลที่สาม หรือออกแบบระบบปลั๊กอินแบบโมดูลาร์ เฟรมที่ควบคุมได้จะช่วยให้คุณควบคุมได้อย่างละเอียดในสภาพแวดล้อมที่มีโครงสร้าง ได้รับสิทธิ์ และปลอดภัย ซึ่งทำให้เป็นเครื่องมือสำคัญในเว็บแอปพลิเคชันขั้นสูงรุ่นถัดไป