คำอธิบาย
ใช้ chrome.scripting
API เพื่อเรียกใช้สคริปต์ในบริบทต่างๆ
สิทธิ์
scripting
ความพร้อมใช้งาน
ไฟล์ Manifest
หากต้องการใช้ chrome.scripting
API ให้ประกาศสิทธิ์ "scripting"
ใน manifest รวมถึงสิทธิ์โฮสต์สำหรับหน้าเว็บที่จะแทรกสคริปต์ ใช้คีย์ "host_permissions"
หรือสิทธิ์ "activeTab"
ซึ่งจะให้สิทธิ์ของโฮสต์ชั่วคราว ตัวอย่างต่อไปนี้ใช้สิทธิ์ activeTab
{ "name": "Scripting Extension", "manifest_version": 3, "permissions": ["scripting", "activeTab"], ... }
แนวคิดและการใช้งาน
คุณใช้ chrome.scripting
API เพื่อแทรก JavaScript และ CSS ลงใน เว็บไซต์ได้ ซึ่งคล้ายกับสิ่งที่คุณทำได้ด้วยContent Scripts แต่การใช้เนมสเปซ chrome.scripting
จะช่วยให้ส่วนขยาย ตัดสินใจได้ในขณะรันไทม์
เป้าหมายการฉีด
คุณใช้พารามิเตอร์ target
เพื่อระบุเป้าหมายที่จะแทรก JavaScript หรือ CSS ได้
ช่องเดียวที่ต้องกรอกคือ tabId
โดยค่าเริ่มต้น การแทรกจะทำงานใน เฟรมหลักของแท็บที่ระบุ
function getTabId() { ... } chrome.scripting .executeScript({ target : {tabId : getTabId()}, files : [ "script.js" ], }) .then(() => console.log("script injected"));
หากต้องการเรียกใช้ในเฟรมทั้งหมดของแท็บที่ระบุ คุณสามารถตั้งค่า allFrames
boolean เป็น true
ได้
function getTabId() { ... } chrome.scripting .executeScript({ target : {tabId : getTabId(), allFrames : true}, files : [ "script.js" ], }) .then(() => console.log("script injected in all frames"));
นอกจากนี้ คุณยังแทรกในเฟรมที่เฉพาะเจาะจงของแท็บได้ด้วยการระบุรหัสเฟรมแต่ละรายการ ดูข้อมูลเพิ่มเติมเกี่ยวกับรหัสเฟรมได้ที่ chrome.webNavigation
API
function getTabId() { ... } chrome.scripting .executeScript({ target : {tabId : getTabId(), frameIds : [ frameId1, frameId2 ]}, files : [ "script.js" ], }) .then(() => console.log("script injected on target frames"));
โค้ดที่แทรก
ส่วนขยายสามารถระบุโค้ดที่จะแทรกผ่านไฟล์ภายนอกหรือตัวแปร รันไทม์
ไฟล์
ไฟล์จะระบุเป็นสตริงที่เป็นเส้นทางที่เกี่ยวข้องกับไดเรกทอรีรากของส่วนขยาย โค้ดต่อไปนี้จะแทรกไฟล์ script.js
ลงในเฟรมหลัก ของแท็บ
function getTabId() { ... } chrome.scripting .executeScript({ target : {tabId : getTabId()}, files : [ "script.js" ], }) .then(() => console.log("injected script file"));
ฟังก์ชันรันไทม์
เมื่อแทรก JavaScript ด้วย scripting.executeScript()
คุณจะระบุฟังก์ชันที่จะเรียกใช้แทนไฟล์ได้ ฟังก์ชันนี้ควรเป็นฟังก์ชัน ตัวแปรที่พร้อมใช้งานในบริบทของส่วนขยายปัจจุบัน
function getTabId() { ... } function getTitle() { return document.title; } chrome.scripting .executeScript({ target : {tabId : getTabId()}, func : getTitle, }) .then(() => console.log("injected a function"));
function getTabId() { ... } function getUserColor() { ... } function changeBackgroundColor() { document.body.style.backgroundColor = getUserColor(); } chrome.scripting .executeScript({ target : {tabId : getTabId()}, func : changeBackgroundColor, }) .then(() => console.log("injected a function"));
คุณแก้ไขปัญหานี้ได้โดยใช้พร็อพเพอร์ตี้ args
ดังนี้
function getTabId() { ... } function getUserColor() { ... } function changeBackgroundColor(backgroundColor) { document.body.style.backgroundColor = backgroundColor; } chrome.scripting .executeScript({ target : {tabId : getTabId()}, func : changeBackgroundColor, args : [ getUserColor() ], }) .then(() => console.log("injected a function"));
สตริงรันไทม์
หากแทรก CSS ภายในหน้าเว็บ คุณยังระบุสตริงที่จะใช้ในพร็อพเพอร์ตี้ css
ได้ด้วย ตัวเลือกนี้ใช้ได้กับ scripting.insertCSS()
เท่านั้น คุณจะรันสตริงโดยใช้ scripting.executeScript()
ไม่ได้
function getTabId() { ... } const css = "body { background-color: red; }"; chrome.scripting .insertCSS({ target : {tabId : getTabId()}, css : css, }) .then(() => console.log("CSS injected"));
จัดการผลลัพธ์
ระบบจะส่งผลลัพธ์ของการเรียกใช้ JavaScript ไปยังส่วนขยาย รวมผลลัพธ์เดียว ต่อเฟรม รับประกันว่าเฟรมหลักจะเป็นดัชนีแรกในอาร์เรย์ที่ได้ ส่วนเฟรมอื่นๆ ทั้งหมดจะอยู่ในลำดับที่ไม่แน่นอน
function getTabId() { ... } function getTitle() { return document.title; } chrome.scripting .executeScript({ target : {tabId : getTabId(), allFrames : true}, func : getTitle, }) .then(injectionResults => { for (const {frameId, result} of injectionResults) { console.log(`Frame ${frameId} result:`, result); } });
scripting.insertCSS()
ไม่แสดงผลลัพธ์ใดๆ
Promise
หากค่าที่ได้จากการเรียกใช้สคริปต์เป็น Promise Chrome จะรอให้ Promise เสร็จสมบูรณ์และแสดงผลค่าที่ได้
function getTabId() { ... } async function addIframe() { const iframe = document.createElement("iframe"); const loadComplete = new Promise(resolve => iframe.addEventListener("load", resolve)); iframe.src = "https://example.com"; document.body.appendChild(iframe); await loadComplete; return iframe.contentWindow.document.title; } chrome.scripting .executeScript({ target : {tabId : getTabId(), allFrames : true}, func : addIframe, }) .then(injectionResults => { for (const frameResult of injectionResults) { const {frameId, result} = frameResult; console.log(`Frame ${frameId} result:`, result); } });
ตัวอย่าง
ยกเลิกการลงทะเบียนสคริปต์เนื้อหาแบบไดนามิกทั้งหมด
ข้อมูลโค้ดต่อไปนี้มีฟังก์ชันที่ยกเลิกการลงทะเบียนสคริปต์เนื้อหาแบบไดนามิกทั้งหมด ที่ส่วนขยายได้ลงทะเบียนไว้ก่อนหน้านี้
async function unregisterAllDynamicContentScripts() { try { const scripts = await chrome.scripting.getRegisteredContentScripts(); const scriptIds = scripts.map(script => script.id); return chrome.scripting.unregisterContentScripts({ ids: scriptIds }); } catch (error) { const message = [ "An unexpected error occurred while", "unregistering dynamic content scripts.", ].join(" "); throw new Error(message, {cause : error}); } }
หากต้องการลองใช้ chrome.scripting
API ให้ติดตั้งตัวอย่างสคริปต์จากที่เก็บตัวอย่างส่วนขยาย Chrome
ประเภท
ContentScriptFilter
พร็อพเพอร์ตี้
- รหัส
string[] ไม่บังคับ
หากระบุไว้
getRegisteredContentScripts
จะแสดงเฉพาะสคริปต์ที่มีรหัสที่ระบุในรายการนี้
CSSInjection
พร็อพเพอร์ตี้
- CSS
สตริง ไม่บังคับ
สตริงที่มี CSS ที่จะแทรก ต้องระบุ
files
และcss
อย่างใดอย่างหนึ่งเท่านั้น - ไฟล์
string[] ไม่บังคับ
เส้นทางของไฟล์ CSS ที่จะแทรก ซึ่งสัมพันธ์กับไดเรกทอรีรากของส่วนขยาย ต้องระบุ
files
และcss
อย่างใดอย่างหนึ่งเท่านั้น - origin
StyleOrigin ไม่บังคับ
แหล่งที่มาของสไตล์สำหรับการแทรก ค่าเริ่มต้นคือ
'AUTHOR'
- เป้าหมาย
รายละเอียดที่ระบุเป้าหมายที่จะแทรก CSS
ExecutionWorld
โลกของ JavaScript สำหรับสคริปต์ที่จะดำเนินการภายใน
ค่าแจกแจง
"ISOLATED"
ระบุโลกที่แยกจากกัน ซึ่งเป็นสภาพแวดล้อมการดำเนินการเฉพาะสำหรับส่วนขยายนี้
"MAIN"
ระบุโลกหลักของ DOM ซึ่งเป็นสภาพแวดล้อมการดำเนินการที่แชร์กับ JavaScript ของหน้าโฮสต์
InjectionResult
พร็อพเพอร์ตี้
- documentId
สตริง
Chrome 106 ขึ้นไปเอกสารที่เชื่อมโยงกับการแทรก
- frameId
ตัวเลข
Chrome 90 ขึ้นไปเฟรมที่เชื่อมโยงกับการแทรก
- ผลลัพธ์
ไม่บังคับ
ผลลัพธ์ของการเรียกใช้สคริปต์
InjectionTarget
พร็อพเพอร์ตี้
- allFrames
บูลีน ไม่บังคับ
เลือกว่าสคริปต์ควรแทรกในเฟรมทั้งหมดภายในแท็บหรือไม่ ค่าเริ่มต้นคือ false ค่านี้ต้องเป็นเท็จหากมีการระบุ
frameIds
- documentIds
string[] ไม่บังคับ
Chrome 106 ขึ้นไปรหัสของ documentId ที่เฉพาะเจาะจงที่จะแทรก ห้ามตั้งค่านี้หากตั้งค่า
frameIds
ไว้ - frameIds
number[] ไม่บังคับ
รหัสของเฟรมที่เฉพาะเจาะจงที่จะแทรก
- tabId
ตัวเลข
รหัสของแท็บที่จะแทรก
RegisteredContentScript
พร็อพเพอร์ตี้
- allFrames
บูลีน ไม่บังคับ
หากระบุเป็นจริง ระบบจะแทรกลงในทุกเฟรม แม้ว่าเฟรมจะไม่ใช่เฟรมบนสุดในแท็บก็ตาม แต่ละเฟรมจะได้รับการตรวจสอบแยกกันตามข้อกำหนดของ URL และจะไม่แทรกลงในเฟรมย่อยหากไม่เป็นไปตามข้อกำหนดของ URL ค่าเริ่มต้นเป็น false ซึ่งหมายความว่าจะมีการจับคู่เฉพาะเฟรมบนสุด
- CSS
string[] ไม่บังคับ
รายการไฟล์ CSS ที่จะแทรกลงในหน้าเว็บที่ตรงกัน ระบบจะแทรกข้อมูลเหล่านี้ตามลำดับที่ปรากฏในอาร์เรย์นี้ ก่อนที่จะสร้างหรือแสดง DOM ใดๆ สำหรับหน้าเว็บ
- excludeMatches
string[] ไม่บังคับ
ยกเว้นหน้าเว็บที่สคริปต์เนื้อหานี้จะแทรกเข้าไป ดูรายละเอียดเพิ่มเติมเกี่ยวกับไวยากรณ์ของสตริงเหล่านี้ได้ที่รูปแบบการจับคู่
- id
สตริง
รหัสของ Content Script ที่ระบุในการเรียก API ต้องไม่ขึ้นต้นด้วย "_" เนื่องจากสงวนไว้เป็นคำนำหน้าสำหรับรหัสสคริปต์ที่สร้างขึ้น
- js
string[] ไม่บังคับ
รายการไฟล์ JavaScript ที่จะแทรกลงในหน้าเว็บที่ตรงกัน โดยจะแทรกตามลำดับที่ปรากฏในอาร์เรย์นี้
- matchOriginAsFallback
บูลีน ไม่บังคับ
Chrome 119 ขึ้นไประบุว่าจะแทรกสคริปลงในเฟรมที่ URL มีรูปแบบที่ไม่รองรับได้หรือไม่ ซึ่งได้แก่ about:, data:, blob: หรือ filesystem: ในกรณีเหล่านี้ ระบบจะตรวจสอบต้นทางของ URL เพื่อพิจารณาว่าควรแทรกสคริปต์หรือไม่ หากต้นทางคือ
null
(เช่นเดียวกับ URL ของข้อมูล) ต้นทางที่ใช้จะเป็นเฟรมที่สร้างเฟรมปัจจุบัน หรือเฟรมที่เริ่มการนำทางไปยังเฟรมนี้ โปรดทราบว่านี่อาจไม่ใช่เฟรมระดับบน - ตรงกับ
string[] ไม่บังคับ
ระบุหน้าเว็บที่จะแทรก Content Script นี้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับไวยากรณ์ของสตริงเหล่านี้ได้ที่รูปแบบการจับคู่ ต้องระบุสำหรับ
registerContentScripts
- persistAcrossSessions
บูลีน ไม่บังคับ
ระบุว่า Content Script นี้จะยังคงอยู่ในเซสชันในอนาคตหรือไม่ ค่าเริ่มต้นคือ True
- runAt
RunAt ไม่บังคับ
ระบุเวลาที่แทรกไฟล์ JavaScript ลงในหน้าเว็บ ค่าที่ต้องการและค่าเริ่มต้นคือ
document_idle
- โลก
ExecutionWorld ไม่บังคับ
Chrome 102 ขึ้นไป"โลก" ของ JavaScript ที่จะใช้เรียกใช้สคริปต์ ค่าเริ่มต้นคือ
ISOLATED
ScriptInjection
พร็อพเพอร์ตี้
- args
any[] ไม่บังคับ
Chrome 92 ขึ้นไปอาร์กิวเมนต์ที่จะส่งไปยังฟังก์ชันที่ระบุ ซึ่งจะใช้ได้ก็ต่อเมื่อระบุพารามิเตอร์
func
อาร์กิวเมนต์เหล่านี้ต้องแปลงเป็น JSON ได้ - ไฟล์
string[] ไม่บังคับ
เส้นทางของไฟล์ JS หรือ CSS ที่จะแทรก ซึ่งสัมพันธ์กับไดเรกทอรีรากของส่วนขยาย ต้องระบุ
files
หรือfunc
อย่างใดอย่างหนึ่งเท่านั้น - injectImmediately
บูลีน ไม่บังคับ
Chrome 102 ขึ้นไปควรกระตุ้นการแทรกในเป้าหมายโดยเร็วที่สุดหรือไม่ โปรดทราบว่าการดำเนินการนี้ไม่ได้รับประกันว่าจะมีการแทรกก่อนที่หน้าเว็บจะโหลด เนื่องจากหน้าเว็บอาจโหลดเสร็จแล้วเมื่อสคริปต์ไปถึงเป้าหมาย
- เป้าหมาย
รายละเอียดที่ระบุเป้าหมายที่จะแทรกสคริปต์
- โลก
ExecutionWorld ไม่บังคับ
Chrome 95 ขึ้นไป"โลก" ของ JavaScript ที่จะใช้เรียกใช้สคริปต์ ค่าเริ่มต้นคือ
ISOLATED
- func
void optional
Chrome 92 ขึ้นไปฟังก์ชัน JavaScript ที่จะแทรก ระบบจะแปลงฟังก์ชันนี้เป็นอนุกรม แล้วจึงแปลงเป็นดีซีเรียลไลซ์เพื่อการแทรก ซึ่งหมายความว่าพารามิเตอร์ที่เชื่อมโยงและบริบทการดำเนินการจะหายไป ต้องระบุ
files
หรือfunc
อย่างใดอย่างหนึ่งเท่านั้นฟังก์ชัน
func
มีลักษณะดังนี้() => {...}
StyleOrigin
แหล่งที่มาของการเปลี่ยนแปลงสไตล์ ดูข้อมูลเพิ่มเติมได้ที่แหล่งที่มาของสไตล์
ค่าแจกแจง
"AUTHOR"
"USER"
เมธอด
executeScript()
chrome.scripting.executeScript(
injection: ScriptInjection,
): Promise<InjectionResult[]>
แทรกสคริปต์ลงในบริบทเป้าหมาย โดยค่าเริ่มต้น สคริปต์จะทำงานที่ document_idle
หรือทันทีหากหน้าเว็บโหลดแล้ว หากตั้งค่าพร็อพเพอร์ตี้ injectImmediately
ไว้ สคริปต์จะแทรกโดยไม่ต้องรอ แม้ว่าหน้าจะโหลดไม่เสร็จก็ตาม หากสคริปต์ประเมินเป็น Promise เบราว์เซอร์จะรอให้ Promise เสร็จสมบูรณ์และแสดงผลค่าที่ได้
พารามิเตอร์
- การแทรก
รายละเอียดของสคริปต์ที่จะแทรก
การคืนสินค้า
-
Promise<InjectionResult[]>
Chrome 90 ขึ้นไป
getRegisteredContentScripts()
chrome.scripting.getRegisteredContentScripts(
filter?: ContentScriptFilter,
): Promise<RegisteredContentScript[]>
แสดงผลสคริปต์เนื้อหาที่ลงทะเบียนแบบไดนามิกทั้งหมดสำหรับส่วนขยายนี้ซึ่งตรงกับตัวกรองที่ระบุ
พารามิเตอร์
- ตัวกรอง
ContentScriptFilter ไม่บังคับ
ออบเจ็กต์เพื่อกรองสคริปต์ที่ลงทะเบียนแบบไดนามิกของส่วนขยาย
การคืนสินค้า
-
Promise<RegisteredContentScript[]>
insertCSS()
chrome.scripting.insertCSS(
injection: CSSInjection,
): Promise<void>
แทรกสไตล์ชีต CSS ลงในบริบทเป้าหมาย หากระบุเฟรมหลายรายการ ระบบจะละเว้นการแทรกที่ไม่สำเร็จ
พารามิเตอร์
- การแทรก
รายละเอียดของสไตล์ที่จะแทรก
การคืนสินค้า
-
Promise<void>
Chrome 90 ขึ้นไป
registerContentScripts()
chrome.scripting.registerContentScripts(
scripts: RegisteredContentScript[],
): Promise<void>
ลงทะเบียนสคริปต์เนื้อหาอย่างน้อย 1 รายการสำหรับส่วนขยายนี้
พารามิเตอร์
- สคริปต์
มีรายการสคริปต์ที่จะลงทะเบียน หากมีข้อผิดพลาดระหว่างการแยกวิเคราะห์สคริปต์/การตรวจสอบไฟล์ หรือหากมีรหัสที่ระบุอยู่แล้ว ระบบจะไม่ลงทะเบียนสคริปต์
การคืนสินค้า
-
Promise<void>
removeCSS()
chrome.scripting.removeCSS(
injection: CSSInjection,
): Promise<void>
นำสไตล์ชีต CSS ที่ส่วนขยายนี้แทรกไว้ก่อนหน้านี้ออกจากบริบทเป้าหมาย
พารามิเตอร์
- การแทรก
รายละเอียดของสไตล์ที่จะนำออก โปรดทราบว่าพร็อพเพอร์ตี้
css
,files
และorigin
ต้องตรงกับชีตสไตล์ที่แทรกผ่านinsertCSS
ทุกประการ การพยายามนำสไตล์ชีตที่ไม่มีอยู่ออกจะไม่มีผล
การคืนสินค้า
-
Promise<void>
unregisterContentScripts()
chrome.scripting.unregisterContentScripts(
filter?: ContentScriptFilter,
): Promise<void>
ยกเลิกการลงทะเบียนสคริปต์เนื้อหาสำหรับส่วนขยายนี้
พารามิเตอร์
- ตัวกรอง
ContentScriptFilter ไม่บังคับ
หากระบุ ระบบจะยกเลิกการลงทะเบียนสคริปต์เนื้อหาแบบไดนามิกที่ตรงกับตัวกรองเท่านั้น มิเช่นนั้น ระบบจะยกเลิกการลงทะเบียนสคริปต์เนื้อหาแบบไดนามิกทั้งหมดของส่วนขยาย
การคืนสินค้า
-
Promise<void>
updateContentScripts()
chrome.scripting.updateContentScripts(
scripts: RegisteredContentScript[],
): Promise<void>
อัปเดตสคริปต์เนื้อหาอย่างน้อย 1 รายการสำหรับส่วนขยายนี้
พารามิเตอร์
- สคริปต์
มีรายการสคริปต์ที่จะอัปเดต ระบบจะอัปเดตพร็อพเพอร์ตี้สำหรับสคริปต์ที่มีอยู่ก็ต่อเมื่อมีการระบุในออบเจ็กต์นี้ หากมีข้อผิดพลาดระหว่างการแยกวิเคราะห์สคริปต์/การตรวจสอบไฟล์ หรือหากรหัสที่ระบุไม่ตรงกับสคริปต์ที่ลงทะเบียนอย่างสมบูรณ์ ระบบจะไม่ทำการอัปเดตสคริปต์
การคืนสินค้า
-
Promise<void>