Memperluas DevTools

Ringkasan

Ekstensi DevTools menambahkan fungsi ke Chrome DevTools. Alat ini dapat menambahkan panel UI dan sidebar baru, berinteraksi dengan halaman yang diperiksa, mendapatkan informasi tentang permintaan jaringan, dan lainnya. Lihat ekstensi DevTools unggulan. Ekstensi DevTools memiliki akses ke kumpulan tambahan API ekstensi khusus DevTools:

Ekstensi DevTools disusun seperti ekstensi lainnya: ekstensi ini dapat memiliki halaman latar belakang, skrip konten, dan item lainnya. Selain itu, setiap ekstensi DevTools memiliki halaman DevTools, yang memiliki akses ke DevTools API.

Diagram arsitektur yang menampilkan halaman DevTools yang berkomunikasi dengan
       jendela yang diperiksa dan halaman latar belakang. Halaman latar belakang ditampilkan
       berkomunikasi dengan skrip konten dan mengakses API ekstensi.
       Halaman DevTools memiliki akses ke DevTools API, misalnya, membuat panel.

Halaman DevTools

Instance halaman DevTools ekstensi dibuat setiap kali jendela DevTools terbuka. Halaman DevTools ada selama jendela DevTools aktif. Halaman DevTools memiliki akses ke DevTools API dan serangkaian API ekstensi terbatas. Secara khusus, halaman DevTools dapat:

  • Membuat dan berinteraksi dengan panel menggunakan devtools.panels API.
  • Dapatkan informasi tentang jendela yang diperiksa dan evaluasi kode di jendela yang diperiksa menggunakan API devtools.inspectedWindow.
  • Dapatkan informasi tentang permintaan jaringan menggunakan API devtools.network.

Halaman DevTools tidak dapat menggunakan sebagian besar API ekstensi secara langsung. API ini memiliki akses ke subset yang sama dari API extension dan runtime yang dapat diakses oleh skrip konten. Seperti skrip konten, halaman DevTools dapat berkomunikasi dengan halaman latar belakang menggunakan Penerusan Pesan. Sebagai contoh, lihat Memasukkan Skrip Konten.

Membuat ekstensi DevTools

Untuk membuat halaman DevTools untuk ekstensi Anda, tambahkan kolom devtools_page dalam manifes ekstensi:

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

Instance devtools_page yang ditentukan dalam manifes ekstensi Anda dibuat untuk setiap jendela DevTools yang dibuka. Halaman dapat menambahkan halaman ekstensi lain sebagai panel dan sidebar ke jendela DevTools menggunakan devtools.panels API.

Modul chrome.devtools.* API hanya tersedia untuk halaman yang dimuat dalam jendela DevTools. Skrip konten dan halaman ekstensi lainnya tidak memiliki API ini. Dengan demikian, API hanya tersedia selama masa aktif jendela DevTools.

Ada juga beberapa API DevTools yang masih bersifat eksperimental. Lihat chrome.experimental.* API untuk mengetahui daftar API eksperimental dan panduan cara menggunakannya.

Elemen UI DevTools: panel dan panel sidebar

Selain elemen UI ekstensi biasa, seperti tindakan browser, menu konteks, dan pop-up, ekstensi DevTools dapat menambahkan elemen UI ke jendela DevTools:

  • Panel adalah tab tingkat teratas, seperti panel Elemen, Sumber, dan Jaringan.
  • Panel sidebar menampilkan UI tambahan yang terkait dengan panel. Panel Gaya, Gaya yang Dikomputasi, dan Pemroses Peristiwa di panel Elemen adalah contoh panel sidebar. (Perhatikan bahwa tampilan panel sidebar mungkin tidak cocok dengan gambar, bergantung pada versi Chrome yang Anda gunakan, dan tempat jendela DevTools di-dock.)

Jendela DevTools yang menampilkan panel Elemen dan panel sidebar Gaya.

Setiap panel adalah file HTML-nya sendiri, yang dapat menyertakan resource lain (JavaScript, CSS, gambar, dan sebagainya). Membuat panel dasar terlihat seperti ini:

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

JavaScript yang dijalankan di panel atau panel sidebar memiliki akses ke API yang sama dengan halaman DevTools.

Membuat panel sidebar dasar untuk panel Elemen akan terlihat seperti ini:

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

Ada beberapa cara untuk menampilkan konten di panel sidebar:

  • Konten HTML. Panggil setPage untuk menentukan halaman HTML yang akan ditampilkan di panel.
  • Data JSON. Teruskan objek JSON ke setObject.
  • Ekspresi JavaScript. Teruskan ekspresi ke setExpression. DevTools mengevaluasi ekspresi dalam konteks halaman yang diperiksa, dan menampilkan nilai yang ditampilkan.

Untuk setObject dan setExpression, panel menampilkan nilai seperti yang akan muncul di konsol DevTools. Namun, setExpression memungkinkan Anda menampilkan elemen DOM dan objek JavaScript arbitrer, sedangkan setObject hanya mendukung objek JSON.

Berkomunikasi antarkomponen ekstensi

Bagian berikut menjelaskan beberapa skenario umum untuk berkomunikasi antar-komponen ekstensi DevTools yang berbeda.

Memasukkan skrip konten

Halaman DevTools tidak dapat memanggil tabs.executeScript secara langsung. Untuk memasukkan skrip konten dari halaman DevTools, Anda harus mengambil ID tab jendela yang diperiksa menggunakan properti inspectedWindow.tabId dan mengirim pesan ke halaman latar belakang. Dari halaman latar belakang, panggil tabs.executeScript untuk memasukkan skrip.

Cuplikan kode berikut menunjukkan cara memasukkan skrip konten menggunakan 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"
});

Kode untuk halaman latar belakang:

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

Mengevaluasi JavaScript di jendela yang diperiksa

Anda dapat menggunakan metode inspectedWindow.eval untuk menjalankan kode JavaScript dalam konteks halaman yang diperiksa. Anda dapat memanggil metode eval dari panel halaman, panel, atau sidebar DevTools.

Secara default, ekspresi dievaluasi dalam konteks frame utama halaman. Sekarang, Anda mungkin sudah terbiasa dengan fitur commandline API DevTools seperti inspeksi elemen (inspect(elem)), pemecahan fungsi (debug(fn)), penyalinan ke papan klip (copy()), dan lainnya. inspectedWindow.eval() menggunakan konteks dan opsi eksekusi skrip yang sama dengan kode yang diketik di konsol DevTools, yang memungkinkan akses ke API ini dalam eval. Misalnya, SOAK menggunakannya untuk memeriksa elemen:

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

Atau, gunakan opsi useContentScriptContext: true untuk inspectedWindow.eval() guna mengevaluasi ekspresi dalam konteks yang sama dengan skrip konten. Memanggil eval dengan useContentScriptContext: true tidak create konteks skrip konten, sehingga Anda harus memuat skrip konteks sebelum memanggil eval, baik dengan memanggil executeScript maupun dengan menentukan skrip konten dalam file manifest.json.

Setelah konteks skrip konteks ada, Anda dapat menggunakan opsi ini untuk memasukkan skrip konten tambahan.

Metode eval sangat efektif jika digunakan dalam konteks yang tepat dan berbahaya jika digunakan secara tidak tepat. Gunakan metode tabs.executeScript jika Anda tidak memerlukan akses ke konteks JavaScript halaman yang diperiksa. Untuk mengetahui peringatan mendetail dan perbandingan kedua metode tersebut, lihat inspectedWindow.

Meneruskan elemen yang dipilih ke skrip konten

Skrip konten tidak memiliki akses langsung ke elemen yang dipilih saat ini. Namun, kode apa pun yang Anda jalankan menggunakan inspectedWindow.eval memiliki akses ke konsol DevTools dan API command line. Misalnya, dalam kode yang dievaluasi, Anda dapat menggunakan $0 untuk mengakses elemen yang dipilih.

Untuk meneruskan elemen yang dipilih ke skrip konten:

  • Buat metode dalam skrip konten yang menggunakan elemen yang dipilih sebagai argumen.
  • Panggil metode dari halaman DevTools menggunakan inspectedWindow.eval dengan opsi useContentScriptContext: true.

Kode dalam skrip konten Anda mungkin terlihat seperti ini:

function setSelectedElement(el) {
    // do something with the selected element
}

Panggil metode dari halaman DevTools seperti ini:

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

Opsi useContentScriptContext: true menentukan bahwa ekspresi harus dievaluasi dalam konteks yang sama dengan skrip konten, sehingga dapat mengakses metode setSelectedElement.

Mendapatkan window panel referensi

Untuk postMessage dari panel devtools, Anda memerlukan referensi ke objek window-nya. Dapatkan jendela iframe panel dari pengendali peristiwa panel.onShown:

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

Pesan dari skrip konten ke halaman DevTools

Pesan antara halaman DevTools dan skrip konten bersifat tidak langsung, melalui halaman latar belakang.

Saat mengirim pesan ke skrip konten, halaman latar belakang dapat menggunakan metode tabs.sendMessage, yang mengarahkan pesan ke skrip konten di tab tertentu, seperti yang ditunjukkan dalam Memasukkan Skrip Konten.

Saat mengirim pesan dari skrip konten, tidak ada metode siap pakai untuk mengirimkan pesan ke instance halaman DevTools yang benar yang terkait dengan tab saat ini. Sebagai solusi, Anda dapat membuat halaman DevTools membuat koneksi yang tahan lama dengan halaman latar belakang, dan membuat halaman latar belakang menyimpan peta ID tab ke koneksi, sehingga dapat merutekan setiap pesan ke koneksi yang benar.

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

Halaman DevTools (atau panel atau panel sidebar) membuat koneksi seperti ini:

// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
    name: "panel"
});

backgroundPageConnection.postMessage({
    name: 'init',
    tabId: chrome.devtools.inspectedWindow.tabId
});

Pesan dari skrip yang dimasukkan ke halaman DevTools

Meskipun solusi di atas berfungsi untuk skrip konten, kode yang dimasukkan langsung ke halaman (misalnya, dengan menambahkan tag <script> atau melalui inspectedWindow.eval) memerlukan strategi yang berbeda. Dalam konteks ini, runtime.sendMessage tidak akan meneruskan pesan ke skrip latar belakang seperti yang diharapkan.

Sebagai solusi, Anda dapat menggabungkan skrip yang dimasukkan dengan skrip konten yang bertindak sebagai perantara. Untuk meneruskan pesan ke skrip konten, Anda dapat menggunakan window.postMessage API. Berikut adalah contoh, dengan asumsi skrip latar belakang dari bagian sebelumnya:

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

Pesan Anda kini akan mengalir dari skrip yang dimasukkan, ke skrip konten, ke skrip latar belakang, dan akhirnya ke halaman DevTools.

Anda juga dapat mempertimbangkan dua teknik penerusan pesan alternatif di sini.

Mendeteksi kapan DevTools terbuka dan tertutup

Jika ekstensi perlu melacak apakah jendela DevTools terbuka, Anda dapat menambahkan pemroses onConnect ke halaman latar belakang, dan memanggil connect dari halaman DevTools. Karena setiap tab dapat membuka jendela DevTools-nya sendiri, Anda mungkin menerima beberapa peristiwa koneksi. Untuk melacak apakah jendela DevTools terbuka, Anda perlu menghitung peristiwa koneksi dan pemutusan koneksi seperti yang ditunjukkan di bawah:

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

Halaman DevTools membuat koneksi seperti ini:

// devtools.js

// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
    name: "devtools-page"
});

Contoh ekstensi DevTools

Jelajahi sumber contoh ekstensi DevTools ini:

  • Ekstensi Devtools Polymer - menggunakan banyak helper yang berjalan di halaman host untuk mengkueri status DOM/JS untuk dikirim kembali ke panel kustom.
  • Ekstensi React DevTools - Menggunakan submodul Blink untuk menggunakan kembali komponen UI DevTools.
  • Ember Inspector - Inti ekstensi bersama dengan adaptor untuk Chrome dan Firefox.
  • Coquette-inspect - Ekstensi berbasis React yang bersih dengan agen proses debug yang dimasukkan ke dalam halaman host.
  • Galeri Ekstensi DevTools dan Contoh Ekstensi kami memiliki lebih banyak aplikasi yang bermanfaat untuk diinstal, dicoba, dan dipelajari.

Informasi selengkapnya

Untuk informasi tentang API standar yang dapat digunakan ekstensi, lihat chrome.* API dan API web.

Berikan masukan kepada kami. Komentar dan saran Anda membantu kami meningkatkan kualitas API.

Contoh

Anda dapat menemukan contoh yang menggunakan API DevTools di Contoh.