Mở rộng Công cụ cho nhà phát triển

Tiện ích DevTools thêm các tính năng vào Công cụ của Chrome cho nhà phát triển bằng cách truy cập vào các API tiện ích dành riêng cho DevTools thông qua một trang DevTools được thêm vào tiện ích.

Sơ đồ cấu trúc cho thấy trang Công cụ cho nhà phát triển giao tiếp với cửa sổ được kiểm tra và worker dịch vụ. Trình chạy dịch vụ được hiển thị khi giao tiếp với tập lệnh nội dung và truy cập vào API tiện ích.
         Trang Công cụ cho nhà phát triển có quyền truy cập vào các API Công cụ cho nhà phát triển, chẳng hạn như tạo bảng điều khiển.
Cấu trúc tiện ích DevTools.

Các API tiện ích dành riêng cho Công cụ cho nhà phát triển bao gồm:

Trang Công cụ cho nhà phát triển

Khi một cửa sổ Công cụ cho nhà phát triển mở ra, một tiện ích Công cụ cho nhà phát triển sẽ tạo một phiên bản của trang Công cụ cho nhà phát triển. Phiên bản này sẽ tồn tại cho đến khi cửa sổ đó mở. Trang này có quyền truy cập vào các API của Công cụ cho nhà phát triển và API tiện ích, đồng thời có thể làm những việc sau:

Trang Công cụ cho nhà phát triển có thể truy cập trực tiếp vào các API tiện ích. Điều này bao gồm cả việc có thể giao tiếp với trình chạy dịch vụ bằng cách sử dụng truyền thông báo.

Tạo một tiện ích cho Công cụ cho nhà phát triển

Để tạo một trang Công cụ cho nhà phát triển cho tiện ích, hãy thêm trường devtools_page vào tệp kê khai tiện ích:

{
  "name": ...
  "version": "1.0",
  "devtools_page": "devtools.html",
  ...
}

Trường devtools_page phải trỏ đến một trang HTML. Vì trang Công cụ cho nhà phát triển phải nằm trên máy của bạn, nên bạn nên chỉ định trang này bằng một URL tương đối.

Các thành phần của API chrome.devtools chỉ có sẵn cho những trang được tải trong cửa sổ Công cụ cho nhà phát triển khi cửa sổ đó đang mở. Tập lệnh nội dung và các trang tiện ích khác không có quyền truy cập vào các API này.

Không gian tên của trình duyệt và các tiện ích của Công cụ cho nhà phát triển

Trong Chrome phiên bản 152 trở lên, các tiện ích có trang Công cụ cho nhà phát triển có thể sử dụng không gian tên browser.

Trong các phiên bản Chrome cũ hơn 152, không gian tên browser đã bị tắt đối với các tiện ích khai báo devtools_page. Lựa chọn không tham gia được áp dụng cho toàn bộ tiện ích, chứ không chỉ riêng trang Công cụ cho nhà phát triển mà còn cho mọi ngữ cảnh tập lệnh nơi các API tiện ích chạy.

Lý do là do có một khoảng trống về khả năng tương thích với webextension-polyfill. Các API chrome.devtools.* trước Chrome 152 chỉ có lệnh gọi lại (không trả về Promises một cách tự nhiên), vì vậy, các tiện ích DevTools thường dựa vào polyfill để bao bọc các API này. Polyfill bỏ qua việc bao bọc bất cứ khi nào browser được xác định, giả sử máy chủ lưu trữ đã thực hiện công việc. Nếu Chrome đã bật browser cho các tiện ích này, thì polyfill sẽ không hoạt động và các lệnh gọi chrome.devtools.* sẽ ngừng trả về Lời hứa. Việc tắt browser khiến polyfill tiếp tục bao bọc.

Lựa chọn không sử dụng này cũng vô hiệu hoá các thay đổi khác về API nhắn tin của Chrome 148 cho những tiện ích này, bao gồm cả phản hồi Promise trong runtime.onMessage. Quy tắc hạn chế này đã được dỡ bỏ sau khi các API của Công cụ cho nhà phát triển hỗ trợ Promise một cách tự nhiên.

Các phần tử trên giao diện người dùng của Công cụ cho nhà phát triển: bảng điều khiển và ngăn bên

Ngoài các phần tử giao diện người dùng tiện ích thông thường, chẳng hạn như thao tác trên trình duyệt, trình đơn theo bối cảnh và cửa sổ bật lên, tiện ích DevTools có thể thêm các phần tử giao diện người dùng vào cửa sổ DevTools:

  • Bảng điều khiển là một thẻ cấp cao nhất, chẳng hạn như bảng điều khiển Phần tử, Nguồn và Mạng.
  • Ngăn bên trình bày giao diện người dùng bổ sung liên quan đến một bảng điều khiển. Các ngăn Kiểu, Kiểu đã tính toán và Trình nghe sự kiện trên bảng điều khiển Phần tử là ví dụ về các ngăn bên. Tuỳ thuộc vào phiên bản Chrome mà bạn đang dùng và vị trí gắn cửa sổ DevTools, các ngăn bên của bạn có thể trông giống như hình ảnh ví dụ sau:
Cửa sổ Công cụ cho nhà phát triển cho thấy bảng điều khiển Phần tử và ngăn bên Kiểu.
Cửa sổ Công cụ cho nhà phát triển cho thấy bảng điều khiển Phần tử và ngăn thanh bên Kiểu.

Mỗi bảng điều khiển là một tệp HTML riêng, có thể bao gồm các tài nguyên khác (JavaScript, CSS, hình ảnh, v.v.). Để tạo một bảng điều khiển cơ bản, hãy dùng mã sau:

chrome.devtools.panels.create("My Panel",
    "MyPanelIcon.png",
    "Panel.html",
    function(panel) {
      // code invoked on panel creation
    }
);

JavaScript được thực thi trong một bảng điều khiển hoặc ngăn bên có quyền truy cập vào cùng một API như trang Công cụ cho nhà phát triển.

Để tạo một ngăn bên cơ bản, hãy dùng mã sau:

chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
    function(sidebar) {
        // sidebar initialization code here
        sidebar.setObject({ some_data: "Some data to show" });
});

Có một số cách để hiển thị nội dung trong ngăn bên:

  • Nội dung HTML: Gọi setPage() để chỉ định một trang HTML cần hiển thị trong ngăn.
  • Dữ liệu JSON: Truyền một đối tượng JSON đến setObject().
  • Biểu thức JavaScript: Truyền một biểu thức đến setExpression(). DevTools đánh giá biểu thức trong bối cảnh của trang được kiểm tra, sau đó hiển thị giá trị trả về.

Đối với cả setObject()setExpression(), ngăn này sẽ hiển thị giá trị như trong bảng điều khiển Công cụ cho nhà phát triển. Tuy nhiên, setExpression() cho phép bạn hiển thị các phần tử DOM và các đối tượng JavaScript tuỳ ý, trong khi setObject() chỉ hỗ trợ các đối tượng JSON.

Giao tiếp giữa các thành phần của tiện ích

Các phần sau đây mô tả một số cách hữu ích để cho phép các thành phần của tiện ích DevTools giao tiếp với nhau.

Chèn tập lệnh nội dung

Để chèn một tập lệnh nội dung, hãy sử dụng scripting.executeScript():

// DevTools page -- devtools.js
chrome.scripting.executeScript({
  target: {
    tabId: chrome.devtools.inspectedWindow.tabId
  },
  files: ["content_script.js"]
});

Bạn có thể truy xuất mã nhận dạng thẻ của cửa sổ được kiểm tra bằng cách sử dụng thuộc tính inspectedWindow.tabId.

Nếu một tập lệnh nội dung đã được chèn, bạn có thể sử dụng các API nhắn tin để giao tiếp với tập lệnh đó.

Đánh giá JavaScript trong cửa sổ được kiểm tra

Bạn có thể sử dụng phương thức inspectedWindow.eval() để thực thi mã JavaScript trong bối cảnh của trang được kiểm tra. Bạn có thể gọi phương thức eval() từ một trang, bảng điều khiển hoặc ngăn bên của Công cụ cho nhà phát triển.

Theo mặc định, biểu thức được đánh giá trong bối cảnh của khung chính của trang. inspectedWindow.eval() sử dụng cùng một ngữ cảnh và các lựa chọn thực thi tập lệnh như mã đã nhập trong bảng điều khiển Công cụ cho nhà phát triển. Nhờ đó, bạn có thể truy cập vào các tính năng API Tiện ích bảng điều khiển của Công cụ cho nhà phát triển khi sử dụng eval(). Ví dụ: sử dụng nó để kiểm tra phần tử tập lệnh đầu tiên trong phần <head> của tài liệu HTML:

chrome.devtools.inspectedWindow.eval(
  "inspect($$('head script')[0])",
  function(result, isException) { }
);

Bạn cũng có thể đặt useContentScriptContext thành true khi gọi inspectedWindow.eval() để đánh giá biểu thức trong cùng một ngữ cảnh với tập lệnh nội dung. Để sử dụng lựa chọn này, hãy dùng khai báo tập lệnh nội dung tĩnh trước khi gọi eval(), bằng cách gọi executeScript() hoặc chỉ định một tập lệnh nội dung trong tệp manifest.json. Sau khi tải bối cảnh tập lệnh nội dung, bạn cũng có thể dùng lựa chọn này để chèn thêm tập lệnh nội dung.

Truyền phần tử đã chọn đến một tập lệnh nội dung

Tập lệnh nội dung không có quyền truy cập trực tiếp vào phần tử hiện được chọn. Tuy nhiên, mọi mã bạn thực thi bằng inspectedWindow.eval() đều có quyền truy cập vào bảng điều khiển DevTools và API Tiện ích bảng điều khiển. Ví dụ: trong mã được đánh giá, bạn có thể sử dụng $0 để truy cập vào phần tử đã chọn.

Cách truyền phần tử đã chọn đến một tập lệnh nội dung:

  1. Tạo một phương thức trong tập lệnh nội dung nhận phần tử đã chọn làm đối số.

    function setSelectedElement(el) {
        // do something with the selected element
    }
    
  2. Gọi phương thức từ trang Công cụ cho nhà phát triển bằng cách sử dụng inspectedWindow.eval() với lựa chọn useContentScriptContext: true.

    chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
        { useContentScriptContext: true });
    

Lựa chọn useContentScriptContext: true chỉ định rằng biểu thức phải được đánh giá trong cùng một ngữ cảnh với tập lệnh nội dung, vì vậy, biểu thức này có thể truy cập vào phương thức setSelectedElement.

Lấy window của một bảng điều khiển tham chiếu

Để gọi postMessage() từ một bảng điều khiển công cụ cho nhà phát triển, bạn cần có một tham chiếu đến đối tượng window của đối tượng đó. Lấy cửa sổ iframe của bảng điều khiển từ trình xử lý sự kiện panel.onShown:

extensionPanel.onShown.addListener(function (extPanelWindow) {
    extPanelWindow instanceof Window; // true
    extPanelWindow.postMessage( // …
});

Gửi thông báo từ tập lệnh được chèn đến trang Công cụ cho nhà phát triển

Mã được chèn trực tiếp vào trang mà không có tập lệnh nội dung, kể cả bằng cách nối thẻ <script> hoặc gọi inspectedWindow.eval(), không thể gửi thông báo đến trang Công cụ cho nhà phát triển bằng runtime.sendMessage(). Thay vào đó, bạn nên kết hợp tập lệnh được chèn với một tập lệnh nội dung có thể đóng vai trò là trung gian và sử dụng phương thức window.postMessage(). Ví dụ sau đây sử dụng tập lệnh nền trong phần trước:

// 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. Note that this is not foolproof
  // and the page can easily spoof messages if it wants to.
  if (typeof message !== 'object' || message === null ||
      message.source !== 'my-devtools-extension') {
    return;
  }

  chrome.runtime.sendMessage(message);
});

Bạn có thể tìm thấy các kỹ thuật truyền thông báo thay thế khác trên GitHub.

Phát hiện thời điểm Công cụ cho nhà phát triển mở và đóng

Để theo dõi xem cửa sổ Công cụ cho nhà phát triển có đang mở hay không, hãy thêm một trình nghe onConnect vào trình chạy dịch vụ và gọi connect() từ trang Công cụ cho nhà phát triển. Vì mỗi thẻ có thể mở cửa sổ Công cụ cho nhà phát triển riêng, nên bạn có thể nhận được nhiều sự kiện kết nối. Để theo dõi xem có cửa sổ Công cụ cho nhà phát triển nào đang mở hay không, hãy đếm các sự kiện kết nối và ngắt kết nối như minh hoạ trong ví dụ sau:

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

Trang Công cụ cho nhà phát triển sẽ tạo một kết nối như sau:

// devtools.js

// Create a connection to the service worker
const serviceWorkerConnection = chrome.runtime.connect({
    name: "devtools-page"
});

// Send a periodic heartbeat to keep the port open.
setInterval(() => {
  port.postMessage("heartbeat");
}, 15000);

Ví dụ về tiện ích Công cụ cho nhà phát triển

Các ví dụ trên trang này được lấy từ các trang sau:

  • Tiện ích Polymer Devtools – Sử dụng nhiều trình trợ giúp chạy trong trang lưu trữ để truy vấn trạng thái DOM/JS nhằm gửi lại cho bảng điều khiển tuỳ chỉnh.
  • Tiện ích React DevTools – Sử dụng một mô-đun con của trình kết xuất để sử dụng lại các thành phần giao diện người dùng DevTools.
  • Ember Inspector – Tiện ích dùng chung có các bộ chuyển đổi cho cả Chrome và Firefox.
  • Coquette-inspect – Một tiện ích dựa trên React gọn gàng với một tác nhân gỡ lỗi được chèn vào trang lưu trữ.
  • Tiện ích mẫu có nhiều tiện ích đáng cài đặt, dùng thử và tìm hiểu hơn.

Thông tin khác

Để biết thông tin về các API tiêu chuẩn mà tiện ích có thể sử dụng, hãy xem chrome.* APIAPI web.

Gửi ý kiến phản hồi cho chúng tôi! Ý kiến và đề xuất của bạn giúp chúng tôi cải thiện các API.

Ví dụ

Bạn có thể tìm thấy các ví dụ sử dụng API Công cụ cho nhà phát triển trong phần Mẫu.