ภาพรวม
ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บจะเพิ่มฟังก์ชันการทำงานให้กับเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome โดยสามารถเพิ่มแผง UI และแถบด้านข้างใหม่ โต้ตอบกับหน้าเว็บที่ตรวจสอบ ดูข้อมูลเกี่ยวกับคำขอเครือข่าย และอื่นๆ ดูส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บที่โดดเด่น ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึงชุด API ส่วนขยายสำหรับ DevTools เพิ่มเติมโดยเฉพาะ ดังนี้
ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บมีโครงสร้างเหมือนกับส่วนขยายอื่นๆ คืออาจมีหน้าพื้นหลัง สคริปต์เนื้อหา และรายการอื่นๆ นอกจากนี้ ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บแต่ละรายการยังมีหน้าเครื่องมือสำหรับนักพัฒนาเว็บที่มีสิทธิ์เข้าถึง API เครื่องมือสำหรับนักพัฒนาเว็บ
หน้าเครื่องมือสำหรับนักพัฒนาเว็บ
อินสแตนซ์ของหน้าเครื่องมือสำหรับนักพัฒนาเว็บของส่วนขยายจะสร้างขึ้นทุกครั้งที่หน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดขึ้น หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะทำงานตลอดอายุการใช้งานของหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บ หน้าเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึง API ของ DevTools และชุด API ส่วนขยายที่จำกัด กล่าวอย่างเจาะจงก็คือ หน้าเครื่องมือสำหรับนักพัฒนาเว็บดำเนินการต่อไปนี้ได้
- สร้างและโต้ตอบกับแผงโดยใช้ API ของ
devtools.panels
- รับข้อมูลเกี่ยวกับหน้าต่างที่ตรวจสอบและประเมินโค้ดในหน้าต่างที่ตรวจสอบโดยใช้ API ของ
devtools.inspectedWindow
- ดูข้อมูลเกี่ยวกับคำขอเครือข่ายโดยใช้
devtools.network
API
หน้าเครื่องมือสำหรับนักพัฒนาเว็บใช้ 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 ของส่วนขยายตามปกติ เช่น การทำงานของเบราว์เซอร์ เมนูตามบริบท และป๊อปอัปแล้ว ส่วนขยาย DevTools ยังสามารถเพิ่มองค์ประกอบ UI ลงในหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บได้ดังนี้
- แผงคือแท็บระดับบนสุด เช่น แผงองค์ประกอบ แหล่งที่มา และเครือข่าย
- แผงแถบด้านข้างจะแสดง UI เสริมที่เกี่ยวข้องกับแผง แผงรูปแบบ รูปแบบที่คำนวณ และ Listener เหตุการณ์ในแผงองค์ประกอบคือตัวอย่างของแผงแถบด้านข้าง (โปรดทราบว่าหน้าตาของแผงแถบด้านข้างอาจไม่ตรงกับภาพ ทั้งนี้ขึ้นอยู่กับเวอร์ชันของ 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
จากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ แผง หรือแผงแถบด้านข้าง
โดยค่าเริ่มต้น ระบบจะประเมินนิพจน์ในบริบทของเฟรมหลักของหน้า ตอนนี้ คุณอาจ
คุ้นเคยกับฟีเจอร์ของ commandline API สำหรับ DevTools เช่น การตรวจสอบองค์ประกอบ
(inspect(elem)
), การแบ่งฟังก์ชัน (debug(fn)
), การคัดลอกไปยังคลิปบอร์ด (copy()
) และอื่นๆ
inspectedWindow.eval()
ใช้บริบทและตัวเลือกการเรียกใช้สคริปต์แบบเดียวกับโค้ดที่พิมพ์ในคอนโซล DevTools ซึ่งอนุญาตให้เข้าถึง 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
จากแผง devtools คุณจะต้องอ้างอิงไปยังออบเจ็กต์ 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 แบบได้ที่นี่
ตรวจจับการเปิดและปิดเครื่องมือสำหรับนักพัฒนาเว็บ
หากส่วนขยายต้องการติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณสามารถเพิ่มโปรแกรมฟัง onConnect ไปยังหน้าเบื้องหลัง และเรียกใช้เชื่อมต่อจากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ เนื่องจากแต่ละแท็บสามารถเปิดหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บของตัวเองได้ คุณจึงอาจได้รับเหตุการณ์การเชื่อมต่อหลายเหตุการณ์ หากต้องการติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณต้องนับเหตุการณ์การเชื่อมต่อและยกเลิกการเชื่อมต่อดังที่แสดงด้านล่าง
// 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 Devtools - ใช้ตัวช่วยเหลือจำนวนมากที่ทำงานในหน้าโฮสต์เพื่อสืบค้นสถานะ DOM/JS เพื่อส่งกลับไปยังแผงที่กำหนดเอง
- React DevTools Extension - ใช้โมดูลย่อยของ Blink เพื่อนำคอมโพเนนต์ UI ของ DevTools มาใช้ซ้ำ
- Ember Inspector - ส่วนขยายหลักที่ใช้ร่วมกันพร้อมด้วยอะแดปเตอร์สำหรับทั้ง Chrome และ Firefox
- Coquette-inspect - ส่วนขยายที่อิงตาม React ที่ชัดเจนซึ่งมีการแทรก Agent การแก้ไขข้อบกพร่องในหน้าโฮสต์
- แกลเลอรีส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บและส่วนขยายตัวอย่างของเรามีแอปที่คุ้มค่ามากกว่าในการติดตั้ง ลองใช้ และเรียนรู้
ข้อมูลเพิ่มเติม
ดูข้อมูลเกี่ยวกับ API มาตรฐานที่ส่วนขยายใช้ได้ที่หัวข้อ chrome* API และ API บนเว็บ
ส่งความคิดเห็นถึงเรา ความคิดเห็นและคำแนะนำของคุณจะช่วยเราปรับปรุง API ได้
ตัวอย่าง
คุณดูตัวอย่างที่ใช้ DevTools API ได้ในตัวอย่าง