ภาพรวม
ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บจะเพิ่มฟังก์ชันการทำงานให้กับเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome โดยสามารถเพิ่มแผงและแถบด้านข้าง UI ใหม่ๆ โต้ตอบกับหน้าที่ตรวจสอบ รับข้อมูลเกี่ยวกับคำขอเครือข่าย และอื่นๆ ดู ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บที่แนะนำ ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึงชุด API ส่วนขยายเฉพาะของเครื่องมือสำหรับนักพัฒนาเว็บเพิ่มเติม ดังนี้
ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บมีโครงสร้างเหมือนกับส่วนขยายอื่นๆ โดยอาจมีหน้าพื้นหลัง สคริปต์เนื้อหา และรายการอื่นๆ นอกจากนี้ ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บแต่ละรายการยังมีหน้าเครื่องมือสำหรับนักพัฒนาเว็บ ซึ่งมีสิทธิ์เข้าถึง API เครื่องมือสำหรับนักพัฒนาเว็บ

หน้าเครื่องมือสำหรับนักพัฒนาเว็บ
ระบบจะสร้างอินสแตนซ์ของหน้าเครื่องมือสำหรับนักพัฒนาเว็บของส่วนขยายทุกครั้งที่เปิดหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บ หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะคงอยู่ตลอดอายุการใช้งานของหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บ หน้าเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึง API เครื่องมือสำหรับนักพัฒนาเว็บและ API ส่วนขยายบางรายการ โดยเฉพาะอย่างยิ่ง หน้าเครื่องมือสำหรับนักพัฒนาเว็บสามารถทำสิ่งต่อไปนี้ได้
- สร้างและโต้ตอบกับแผงโดยใช้
devtools.panelsAPI - รับข้อมูลเกี่ยวกับหน้าต่างที่ตรวจสอบและประเมินโค้ดในหน้าต่างที่ตรวจสอบโดยใช้
devtools.inspectedWindowAPI - รับข้อมูลเกี่ยวกับคำขอเครือข่ายโดยใช้
devtools.networkAPI
หน้าเครื่องมือสำหรับนักพัฒนาเว็บไม่สามารถใช้ API ส่วนขยายส่วนใหญ่ได้โดยตรง แต่มีสิทธิ์เข้าถึง API extension และ runtime ชุดย่อยเดียวกัน
กับที่สคริปต์เนื้อหามีสิทธิ์เข้าถึง หน้าเครื่องมือสำหรับนักพัฒนาเว็บสามารถสื่อสารกับหน้าพื้นหลังได้โดยใช้การส่งข้อความ เช่นเดียวกับสคริปต์เนื้อหา
ดูตัวอย่างได้ที่
การแทรกสคริปต์เนื้อหา
การสร้างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ
หากต้องการสร้างหน้าเครื่องมือสำหรับนักพัฒนาเว็บสำหรับส่วนขยาย ให้เพิ่มช่อง devtools_page ในไฟล์ Manifest ของส่วนขยาย
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
ระบบจะสร้างอินสแตนซ์ของ devtools_page ที่ระบุไว้ในไฟล์ Manifest ของส่วนขยายสำหรับหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บทุกหน้าต่างที่เปิดขึ้น หน้าเว็บอาจเพิ่มหน้าส่วนขยายอื่นๆ เป็นแผงและแถบด้านข้างลงใน
หน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บโดยใช้ devtools.panels API
โมดูล API chrome.devtools.* ใช้ได้เฉพาะกับหน้าที่โหลดภายในหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเท่านั้น สคริปต์เนื้อหาและหน้าส่วนขยายอื่นๆ จะไม่มี API เหล่านี้ ดังนั้น API จึงใช้ได้เฉพาะในช่วงเวลาที่หน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่เท่านั้น
นอกจากนี้ยังมี API เครื่องมือสำหรับนักพัฒนาเว็บบางรายการที่ยังอยู่ในช่วงทดลอง โปรดดู chrome.experimental.* API สำหรับรายการ API ทดลองและหลักเกณฑ์เกี่ยวกับวิธีใช้
องค์ประกอบ UI ของเครื่องมือสำหรับนักพัฒนาเว็บ: แผงและบานหน้าต่างแถบด้านข้าง
นอกเหนือจากองค์ประกอบ UI ของส่วนขยายทั่วไป เช่น การทำงานของเบราว์เซอร์ เมนูตามบริบท และป๊อปอัปแล้ว ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บยังเพิ่มองค์ประกอบ UI ลงในหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บได้ด้วย ดังนี้
- แผง คือแท็บระดับบนสุด เช่น แผงองค์ประกอบ แหล่งที่มา และเครือข่าย
- บานหน้าต่างแถบด้านข้าง จะแสดง UI เสริมที่เกี่ยวข้องกับแผง บานหน้าต่างรูปแบบ รูปแบบที่คำนวณแล้ว และตัวจัดการเหตุการณ์ในแผงองค์ประกอบเป็นตัวอย่างของบานหน้าต่างแถบด้านข้าง (โปรดทราบว่าลักษณะที่ปรากฏของบานหน้าต่างแถบด้านข้างอาจไม่ตรงกับรูปภาพ ทั้งนี้ขึ้นอยู่กับเวอร์ชันของ Chrome ที่คุณใช้และตำแหน่งที่หน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บถูกตรึงไว้)

แผงแต่ละแผงเป็นไฟล์ HTML ของตัวเอง ซึ่งอาจมีทรัพยากรอื่นๆ (JavaScript, CSS, รูปภาพ และอื่นๆ) การสร้างแผงพื้นฐานจะมีลักษณะดังนี้
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
JavaScript ที่ดำเนินการในแผงหรือบานหน้าต่างแถบด้านข้างมีสิทธิ์เข้าถึง API เดียวกันกับหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
การสร้างบานหน้าต่างแถบด้านข้างพื้นฐานสำหรับแผงองค์ประกอบจะมีลักษณะดังนี้
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
function(sidebar) {
// sidebar initialization code here
sidebar.setObject({ some_data: "Some data to show" });
});
คุณแสดงเนื้อหาในบานหน้าต่างแถบด้านข้างได้หลายวิธี ดังนี้
- เนื้อหา HTML เรียก
setPageเพื่อระบุหน้า HTML ที่จะแสดงในบานหน้าต่าง - ข้อมูล JSON ส่งออบเจ็กต์ JSON ไปยัง
setObject - นิพจน์ JavaScript ส่งนิพจน์ไปยัง
setExpression. เครื่องมือสำหรับนักพัฒนาเว็บจะประเมินนิพจน์ในบริบทของหน้าที่ตรวจสอบและแสดงค่าที่ส่งคืน
สำหรับทั้ง setObject และ setExpression บานหน้าต่างจะแสดงค่าตามที่ปรากฏในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ อย่างไรก็ตาม setExpression ช่วยให้คุณแสดงองค์ประกอบ DOM และออบเจ็กต์ JavaScript ที่กำหนดเองได้ ในขณะที่ setObject รองรับเฉพาะออบเจ็กต์ JSON
การสื่อสารระหว่างคอมโพเนนต์ส่วนขยาย
ส่วนต่อไปนี้จะอธิบายสถานการณ์ทั่วไปบางอย่างสำหรับการสื่อสารระหว่างคอมโพเนนต์ต่างๆ ของส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ
การแทรกสคริปต์เนื้อหา
หน้าเครื่องมือสำหรับนักพัฒนาเว็บไม่สามารถเรียก tabs.executeScript ได้โดยตรง หากต้องการแทรกสคริปต์เนื้อหาจาก
หน้าเครื่องมือสำหรับนักพัฒนาเว็บ คุณต้องดึงข้อมูลรหัสของแท็บหน้าต่างที่ตรวจสอบโดยใช้พร็อพเพอร์ตี้
inspectedWindow.tabId แล้วส่งข้อความไปยังหน้าพื้นหลัง จากหน้าพื้นหลัง ให้เรียก tabs.executeScript เพื่อแทรกสคริปต์
ข้อมูลโค้ดต่อไปนี้แสดงวิธีแทรกสคริปต์เนื้อหาโดยใช้ executeScript
// DevTools page -- devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Handle responses from the background page, if any
});
// Relay the tab ID to the background page
chrome.runtime.sendMessage({
tabId: chrome.devtools.inspectedWindow.tabId,
scriptToInject: "content_script.js"
});
โค้ดสำหรับหน้าพื้นหลัง
// Background page -- background.js
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
// assign the listener function to a variable so we can remove it later
var devToolsListener = function(message, sender, sendResponse) {
// Inject a content script into the identified tab
chrome.tabs.executeScript(message.tabId,
{ file: message.scriptToInject });
}
// add the listener
devToolsConnection.onMessage.addListener(devToolsListener);
devToolsConnection.onDisconnect.addListener(function() {
devToolsConnection.onMessage.removeListener(devToolsListener);
});
});
การประเมิน JavaScript ในหน้าต่างที่ตรวจสอบ
คุณสามารถใช้วิธี inspectedWindow.eval เพื่อดำเนินการโค้ด JavaScript ในบริบทของ
หน้าที่ตรวจสอบ คุณสามารถเรียกใช้วิธี eval จากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ แผง หรือบานหน้าต่างแถบด้านข้าง
โดยค่าเริ่มต้น ระบบจะประเมินนิพจน์ในบริบทของเฟรมหลักของหน้า ตอนนี้คุณอาจ
คุ้นเคยกับฟีเจอร์ API บรรทัดคำสั่งของเครื่องมือสำหรับนักพัฒนาเว็บ เช่น การตรวจสอบองค์ประกอบ
(inspect(elem)) การหยุดชั่วคราวในฟังก์ชัน (debug(fn)) การคัดลอกไปยังคลิปบอร์ด (copy()) และอื่นๆ
inspectedWindow.eval() ใช้บริบทและตัวเลือกการดำเนินการสคริปต์เดียวกันกับโค้ดที่พิมพ์ในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ ซึ่งช่วยให้เข้าถึง API เหล่านี้ได้ภายใน eval ตัวอย่างเช่น SOAK ใช้ฟีเจอร์นี้
เพื่อตรวจสอบองค์ประกอบ
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
หรือใช้ตัวเลือก useContentScriptContext: true สำหรับ inspectedWindow.eval() เพื่อประเมินนิพจน์ในบริบทเดียวกับสคริปต์เนื้อหา การเรียก eval ด้วย useContentScriptContext: true จะไม่ สร้าง บริบทสคริปต์เนื้อหา ดังนั้นคุณต้องโหลดสคริปต์บริบทก่อนที่จะเรียก eval โดยการเรียก executeScript หรือระบุสคริปต์เนื้อหาในไฟล์ manifest.json
เมื่อมีบริบทสคริปต์เนื้อหาแล้ว คุณจะใช้ตัวเลือกนี้เพื่อแทรกสคริปต์เนื้อหาเพิ่มเติมได้
วิธี eval มีประสิทธิภาพเมื่อใช้ในบริบทที่เหมาะสมและเป็นอันตรายเมื่อใช้ไม่ถูกต้อง ใช้วิธี tabs.executeScript หากคุณไม่จำเป็นต้องเข้าถึง
บริบท JavaScript ของหน้าที่ตรวจสอบ ดูข้อควรระวังโดยละเอียดและการเปรียบเทียบวิธีการทั้ง 2 วิธีได้ที่
ดู inspectedWindow
การส่งองค์ประกอบที่เลือกไปยังสคริปต์เนื้อหา
สคริปต์เนื้อหาไม่มีสิทธิ์เข้าถึงองค์ประกอบที่เลือกในปัจจุบันโดยตรง อย่างไรก็ตาม โค้ดที่คุณ
ดำเนินการโดยใช้ inspectedWindow.eval มีสิทธิ์เข้าถึงคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บและ API บรรทัดคำสั่ง
ตัวอย่างเช่น ในโค้ดที่ประเมินแล้ว คุณสามารถใช้ $0 เพื่อเข้าถึงองค์ประกอบที่เลือก
วิธีส่งองค์ประกอบที่เลือกไปยังสคริปต์เนื้อหา
- สร้างเมธอดในสคริปต์เนื้อหาที่รับองค์ประกอบที่เลือกเป็นอาร์กิวเมนต์
- เรียกเมธอดจากหน้าเครื่องมือสำหรับนักพัฒนาเว็บโดยใช้
inspectedWindow.evalพร้อมตัวเลือกuseContentScriptContext: true
โค้ดในสคริปต์เนื้อหาอาจมีลักษณะดังนี้
function setSelectedElement(el) {
// do something with the selected element
}
เรียกเมธอดจากหน้าเครื่องมือสำหรับนักพัฒนาเว็บดังนี้
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
ตัวเลือก useContentScriptContext: true ระบุว่าต้องประเมินนิพจน์ในบริบทเดียวกับสคริปต์เนื้อหา จึงจะเข้าถึงเมธอด setSelectedElement ได้
การรับ window ของแผงอ้างอิง
หากต้องการ postMessage จากแผงเครื่องมือสำหรับนักพัฒนาเว็บ คุณจะต้องมีการอ้างอิงไปยังออบเจ็กต์ window ของแผงนั้น
รับหน้าต่าง iframe ของแผงจากตัวจัดการเหตุการณ์ panel.onShown ดังนี้
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
การส่งข้อความจากสคริปต์เนื้อหาไปยังหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
การส่งข้อความระหว่างหน้าเครื่องมือสำหรับนักพัฒนาเว็บและสคริปต์เนื้อหาเป็นการส่งแบบอ้อมผ่านหน้าพื้นหลัง
เมื่อส่งข้อความ ไปยัง สคริปต์เนื้อหา หน้าพื้นหลังสามารถใช้วิธี
tabs.sendMessage ซึ่งจะส่งข้อความไปยังสคริปต์เนื้อหาในแท็บที่เฉพาะเจาะจง
ดังที่แสดงใน การแทรกสคริปต์เนื้อหา
เมื่อส่งข้อความ จาก สคริปต์เนื้อหา จะไม่มีวิธีสำเร็จรูปในการส่งข้อความไปยังอินสแตนซ์หน้าเครื่องมือสำหรับนักพัฒนาเว็บที่ถูกต้องซึ่งเชื่อมโยงกับแท็บปัจจุบัน วิธีแก้ปัญหาคือ คุณสามารถให้หน้าเครื่องมือสำหรับนักพัฒนาเว็บสร้างการเชื่อมต่อระยะยาวกับหน้าพื้นหลัง และให้หน้าพื้นหลังเก็บแผนที่ของรหัสแท็บไปยังการเชื่อมต่อ เพื่อให้สามารถกำหนดเส้นทางข้อความแต่ละข้อความไปยังการเชื่อมต่อที่ถูกต้องได้
// background.js
var connections = {};
chrome.runtime.onConnect.addListener(function (port) {
var extensionListener = function (message, sender, sendResponse) {
// The original connection event doesn't include the tab ID of the
// DevTools page, so we need to send it explicitly.
if (message.name == "init") {
connections[message.tabId] = port;
return;
}
// other message handling
}
// Listen to messages sent from the DevTools page
port.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
port.onMessage.removeListener(extensionListener);
var tabs = Object.keys(connections);
for (var i=0, len=tabs.length; i < len; i++) {
if (connections[tabs[i]] == port) {
delete connections[tabs[i]]
break;
}
}
});
});
// Receive message from content script and relay to the devTools page for the
// current tab
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// Messages from content scripts should have sender.tab set
if (sender.tab) {
var tabId = sender.tab.id;
if (tabId in connections) {
connections[tabId].postMessage(request);
} else {
console.log("Tab not found in connection list.");
}
} else {
console.log("sender.tab not defined.");
}
return true;
});
หน้าเครื่องมือสำหรับนักพัฒนาเว็บ (หรือแผงหรือบานหน้าต่างแถบด้านข้าง) จะสร้างการเชื่อมต่อดังนี้
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
การส่งข้อความจากสคริปต์ที่แทรกไปยังหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
แม้ว่าโซลูชันข้างต้นจะใช้ได้กับสคริปต์เนื้อหา แต่โค้ดที่แทรกลงในหน้าโดยตรง
(เช่น ผ่านการเพิ่มแท็ก <script> หรือผ่าน inspectedWindow.eval) ต้องใช้กลยุทธ์อื่น
ในบริบทนี้ runtime.sendMessage จะไม่ส่งข้อความไปยัง
สคริปต์พื้นหลังตามที่คาดไว้
วิธีแก้ปัญหาคือ คุณสามารถรวมสคริปต์ที่แทรกกับสคริปต์เนื้อหาที่ทำหน้าที่เป็นตัวกลาง หากต้องการส่งข้อความไปยังสคริปต์เนื้อหา คุณสามารถใช้ window.postMessage
API ตัวอย่างเช่น สมมติว่าสคริปต์พื้นหลังมาจากส่วนก่อนหน้า
// injected-script.js
window.postMessage({
greeting: 'hello there!',
source: 'my-devtools-extension'
}, '*');
// content-script.js
window.addEventListener('message', function(event) {
// Only accept messages from the same frame
if (event.source !== window) {
return;
}
var message = event.data;
// Only accept messages that we know are ours
if (typeof message !== 'object' || message === null ||
!message.source === 'my-devtools-extension') {
return;
}
chrome.runtime.sendMessage(message);
});
ตอนนี้ข้อความจะไหลจากสคริปต์ที่แทรก ไปยังสคริปต์เนื้อหา ไปยังสคริปต์พื้นหลัง และสุดท้ายไปยังหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
นอกจากนี้ คุณยังพิจารณาเทคนิคการส่งข้อความทางเลือก 2 วิธีได้ที่นี่
การตรวจหาเมื่อเครื่องมือสำหรับนักพัฒนาเว็บเปิดและปิด
หากส่วนขยายต้องติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณสามารถเพิ่ม Listener onConnect ลงในหน้าพื้นหลัง แล้วเรียก connect จากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ เนื่องจากแต่ละแท็บสามารถเปิดหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บของตัวเองได้ คุณจึงอาจได้รับเหตุการณ์ connect หลายรายการ หากต้องการติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณต้องนับเหตุการณ์ connect และ disconnect ดังที่แสดงด้านล่าง
// background.js
var openCount = 0;
chrome.runtime.onConnect.addListener(function (port) {
if (port.name == "devtools-page") {
if (openCount == 0) {
alert("DevTools window opening.");
}
openCount++;
port.onDisconnect.addListener(function(port) {
openCount--;
if (openCount == 0) {
alert("Last DevTools window closing.");
}
});
}
});
หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะสร้างการเชื่อมต่อดังนี้
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
ตัวอย่างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ
เรียกดูแหล่งที่มาของตัวอย่างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บเหล่านี้
- ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บของ Polymer - ใช้ผู้ช่วยจำนวนมากที่ทำงานในหน้าโฮสต์เพื่อค้นหาสถานะ DOM/JS เพื่อส่งกลับไปยังแผงที่กำหนดเอง
- ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บของ React - ใช้โมดูลย่อยของ Blink เพื่อนำคอมโพเนนต์ UI ของเครื่องมือสำหรับนักพัฒนาเว็บกลับมาใช้ใหม่
- Ember Inspector - แชร์คอร์ส่วนขยายกับอะแดปเตอร์สำหรับทั้ง Chrome และ Firefox
- Coquette-inspect - ส่วนขยายที่สะอาดตาซึ่งใช้ React และมีเอเจนต์การแก้ไขข้อบกพร่องที่แทรกลงใน หน้าโฮสต์
- แกลเลอรีส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บและส่วนขยายตัวอย่างมีแอปที่คุ้มค่าให้ ติดตั้ง ลองใช้ และเรียนรู้เพิ่มเติม
ข้อมูลเพิ่มเติม
ดูข้อมูลเกี่ยวกับ API มาตรฐานที่ส่วนขยายใช้ได้ที่ chrome.* API และ Web API
ส่งความคิดเห็นถึงเรา ความคิดเห็นและคำแนะนำของคุณจะช่วยเราปรับปรุง API
ตัวอย่าง
ดูตัวอย่างที่ใช้ API เครื่องมือสำหรับนักพัฒนาเว็บได้ใน ตัวอย่าง