การขยายเครื่องมือสำหรับนักพัฒนาเว็บ

ภาพรวม

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

ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บมีโครงสร้างเหมือนกับส่วนขยายอื่นๆ โดยอาจมีหน้าพื้นหลัง เนื้อหา สคริปต์ และรายการอื่นๆ นอกจากนี้ ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บแต่ละรายการจะมีหน้าเครื่องมือสำหรับนักพัฒนาเว็บ ซึ่งสามารถเข้าถึง API ของเครื่องมือสำหรับนักพัฒนาเว็บ

แผนภาพสถาปัตยกรรมแสดงหน้าเครื่องมือสำหรับนักพัฒนาเว็บที่สื่อสารกับ
       หน้าต่างที่ตรวจสอบ และหน้าเว็บพื้นหลัง แสดงหน้าพื้นหลัง
       สื่อสารกับสคริปต์เนื้อหาและเข้าถึง API ส่วนขยาย
       หน้าเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึง API ของเครื่องมือสำหรับนักพัฒนาเว็บได้ เช่น การสร้างแผง

หน้าเครื่องมือสำหรับนักพัฒนาเว็บ

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

  • สร้างและโต้ตอบกับแผงโดยใช้ devtools.panels API
  • รับข้อมูลเกี่ยวกับหน้าต่างที่ตรวจสอบแล้วและประเมินโค้ดในหน้าต่างที่ตรวจสอบโดยใช้ devtools.inspectedWindow API
  • รับข้อมูลเกี่ยวกับคำขอเครือข่ายโดยใช้ devtools.network API

หน้าเครื่องมือสำหรับนักพัฒนาเว็บใช้ API ส่วนขยายส่วนใหญ่โดยตรงไม่ได้ มีสิทธิ์เข้าถึงส่วนย่อยเดียวกัน ของ API ของ extension และ runtime ที่สคริปต์เนื้อหามีสิทธิ์เข้าถึง กดชอบเนื้อหา หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะสื่อสารกับหน้าพื้นหลังโดยใช้ Message Passing ได้ สำหรับ ตัวอย่างเช่น โปรดดูการแทรกสคริปต์เนื้อหา

การสร้างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ

หากต้องการสร้างหน้าเครื่องมือสำหรับนักพัฒนาเว็บสำหรับส่วนขยาย ให้เพิ่มช่อง 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 เสริมที่เกี่ยวข้องกับแผง รูปแบบ รูปแบบที่คำนวณ และ แผง 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 ของเครื่องมือสำหรับนักพัฒนาเว็บ เช่น การตรวจสอบองค์ประกอบ (inspect(elem)) ทำลายฟังก์ชัน (debug(fn)) คัดลอกไปยังคลิปบอร์ด (copy()) และอื่นๆ inspectedWindow.eval() ใช้บริบทและตัวเลือกการเรียกใช้สคริปต์เหมือนกับโค้ดที่พิมพ์ที่ คอนโซลเครื่องมือสำหรับนักพัฒนาเว็บซึ่งอนุญาตการเข้าถึง API เหล่านี้ภายในระยะเวลาการประเมิน ตัวอย่างเช่น 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 อย่างที่นี่ก็ได้

การตรวจจับเมื่อมีการเปิดและปิดเครื่องมือสำหรับนักพัฒนาเว็บ

หากส่วนขยายต้องการติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณสามารถเพิ่ม onConnect Listener หน้าพื้นหลังและเรียกใช้ connect จากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ เนื่องจากแต่ละแท็บสามารถ มีหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่ คุณอาจได้รับเหตุการณ์การเชื่อมต่อหลายรายการ ในการติดตามว่ามี หน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่ คุณต้องนับเหตุการณ์การเชื่อมต่อและยกเลิกการเชื่อมต่อดังที่แสดงด้านล่าง

// 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"
});

ตัวอย่างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ

เลือกซอร์สของตัวอย่างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บเหล่านี้

ข้อมูลเพิ่มเติม

สำหรับข้อมูลเกี่ยวกับ API มาตรฐานที่ส่วนขยายสามารถใช้ได้ โปรดดู chrome* API และเว็บ API

แสดงความคิดเห็นให้เราทราบ ความคิดเห็นและคำแนะนำของคุณจะช่วยเราปรับปรุง API ให้ดียิ่งขึ้น

ตัวอย่าง

ดูตัวอย่างที่ใช้ API ของเครื่องมือสำหรับนักพัฒนาเว็บได้ในตัวอย่าง