گسترش DevTools

نمای کلی

یک برنامه افزودنی DevTools عملکردی را به Chrome DevTools اضافه می کند. می‌تواند پنل‌ها و نوارهای فرعی جدید رابط کاربری اضافه کند، با صفحه بازرسی شده تعامل داشته باشد، اطلاعاتی درباره درخواست‌های شبکه دریافت کند و موارد دیگر. برنامه های افزودنی DevTools را مشاهده کنید. برنامه‌های افزودنی DevTools به مجموعه دیگری از APIهای برنامه‌افزونه ویژه DevTools دسترسی دارند:

یک برنامه افزودنی DevTools مانند هر برنامه افزودنی دیگر ساختار یافته است: می تواند صفحه پس زمینه، اسکریپت های محتوا و موارد دیگر داشته باشد. علاوه بر این، هر افزونه DevTools دارای یک صفحه DevTools است که به API های DevTools دسترسی دارد.

نمودار معماری که صفحه DevTools را نشان می دهد که با پنجره بازرسی شده و صفحه پس زمینه ارتباط برقرار می کند. صفحه پس‌زمینه در ارتباط با اسکریپت‌های محتوا و دسترسی به APIهای افزونه نشان داده می‌شود.        صفحه DevTools به API های DevTools دسترسی دارد، به عنوان مثال، پانل ها را ایجاد می کند.

صفحه DevTools

هر بار که پنجره DevTools باز می شود، نمونه ای از صفحه DevTools برنامه افزودنی ایجاد می شود. صفحه DevTools برای طول عمر پنجره DevTools وجود دارد. صفحه DevTools به API های DevTools و مجموعه محدودی از برنامه های افزودنی API دسترسی دارد. به طور خاص، صفحه DevTools می تواند:

  • با استفاده از برنامه های کاربردی devtools.panels ، پنل ها را ایجاد کرده و با آنها تعامل داشته باشید.
  • اطلاعات مربوط به پنجره بازرسی شده را دریافت کنید و کد را در پنجره بازرسی شده با استفاده از APIs devtools.inspectedWindow ارزیابی کنید.
  • با استفاده از API devtools.network اطلاعاتی در مورد درخواست های شبکه دریافت کنید.

صفحه DevTools نمی‌تواند مستقیماً از بیشتر APIهای افزونه استفاده کند. به همان زیرمجموعه ای از برنامه های extension و runtime دسترسی دارد که یک اسکریپت محتوا به آن دسترسی دارد. مانند یک اسکریپت محتوا، یک صفحه DevTools می‌تواند با استفاده از ارسال پیام با صفحه پس‌زمینه ارتباط برقرار کند. برای مثال، تزریق یک اسکریپت محتوا را ببینید.

ایجاد یک افزونه DevTools

برای ایجاد یک صفحه DevTools برای برنامه افزودنی خود، فیلد devtools_page در مانیفست افزونه اضافه کنید:

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

نمونه ای از devtools_page مشخص شده در مانیفست برنامه افزودنی شما برای هر پنجره DevTools باز می شود. این صفحه ممکن است با استفاده از devtools.panels API صفحات افزونه دیگری را به عنوان پانل ها و نوارهای جانبی به پنجره DevTools اضافه کند.

ماژول‌های chrome.devtools.* فقط برای صفحاتی که در پنجره DevTools بارگذاری شده‌اند در دسترس هستند. اسکریپت های محتوا و سایر صفحات افزونه این API ها را ندارند. بنابراین، APIها فقط در طول عمر پنجره DevTools در دسترس هستند.

همچنین برخی از API های DevTools وجود دارند که هنوز آزمایشی هستند. برای فهرست APIهای آزمایشی و دستورالعمل‌های نحوه استفاده از آنها به chrome.experimental.* API مراجعه کنید.

عناصر DevTools UI: پانل ها و پنجره های نوار کناری

افزونه DevTools علاوه بر عناصر معمول رابط کاربری افزونه، مانند اقدامات مرورگر، منوهای زمینه و پنجره‌های بازشو، می‌تواند عناصر UI را به پنجره DevTools اضافه کند:

  • پانل یک برگه سطح بالا است، مانند پانل های عناصر، منابع و شبکه.
  • یک صفحه نوار کناری رابط کاربری تکمیلی مربوط به یک پانل را نشان می دهد. پنجره‌های Styles، Computed Styles و Event Listeners در پانل Elements نمونه‌هایی از پنجره‌های نوار کناری هستند. (توجه داشته باشید که ظاهر پنجره‌های نوار کناری ممکن است با تصویر مطابقت نداشته باشد، بسته به نسخه کروم که استفاده می‌کنید و جایی که پنجره DevTools در آن قرار دارد.)

پنجره DevTools که پنل Elements و پنجره نوار کناری Styles را نشان می دهد.

هر پنل فایل HTML مخصوص به خود است که می تواند شامل منابع دیگری (جاوا اسکریپت، CSS، تصاویر و غیره) باشد. ایجاد یک پنل پایه به شکل زیر است:

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

جاوا اسکریپت اجرا شده در یک پانل یا نوار کناری به همان APIهایی که صفحه DevTools هستند دسترسی دارد.

ایجاد یک پانل پایه کناری برای پنل Elements به شکل زیر است:

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 ارسال کنید.
  • عبارت جاوا اسکریپت یک عبارت را به setExpression ارسال کنید. DevTools عبارت را در متن صفحه بازرسی شده ارزیابی می کند و مقدار بازگشتی را نمایش می دهد.

هم برای setObject و هم setExpression ، صفحه مقدار را همانطور که در کنسول DevTools ظاهر می شود نمایش می دهد. با این حال، setExpression به شما امکان می دهد عناصر DOM و اشیاء دلخواه جاوا اسکریپت را نمایش دهید، در حالی که setObject فقط از اشیاء JSON پشتیبانی می کند.

برقراری ارتباط بین اجزای افزونه

بخش‌های زیر برخی از سناریوهای معمولی برای برقراری ارتباط بین اجزای مختلف یک برنامه افزودنی DevTools را توضیح می‌دهند.

تزریق اسکریپت محتوا

صفحه DevTools نمی‌تواند مستقیماً tabs.executeScript فراخوانی کند. برای تزریق یک اسکریپت محتوا از صفحه DevTools، باید شناسه برگه پنجره بازرسی شده را با استفاده از ویژگی 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);
    });
});

ارزیابی جاوا اسکریپت در پنجره بازرسی شده

می توانید از روش inspectedWindow.eval برای اجرای کد جاوا اسکریپت در متن صفحه بازرسی شده استفاده کنید. می‌توانید روش eval از یک صفحه DevTools، پانل یا نوار کناری فراخوانی کنید.

به طور پیش فرض، عبارت در زمینه چارچوب اصلی صفحه ارزیابی می شود. اکنون، ممکن است با ویژگی‌های 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 استفاده کنید. برای احتیاطات دقیق و مقایسه این دو روش، به inspectedWindow مراجعه کنید.

انتقال عنصر انتخاب شده به اسکریپت محتوا

اسکریپت محتوا دسترسی مستقیم به عنصر انتخابی فعلی ندارد. با این حال، هر کدی که با استفاده از inspectedWindow.eval اجرا می کنید، به کنسول DevTools و APIهای خط فرمان دسترسی دارد. به عنوان مثال، در کد ارزیابی شده می توانید از $0 برای دسترسی به عنصر انتخاب شده استفاده کنید.

برای ارسال عنصر انتخاب شده به اسکریپت محتوا:

  • یک متد در اسکریپت محتوا ایجاد کنید که عنصر انتخاب شده را به عنوان آرگومان دریافت کند.
  • متد را از صفحه DevTools با استفاده از inspectedWindow.eval با گزینه useContentScriptContext: true فراخوانی کنید.

کد موجود در اسکریپت محتوای شما ممکن است چیزی شبیه به این باشد:

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

متد را از صفحه DevTools به این صورت فراخوانی کنید:

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

ارسال پیام از اسکریپت های محتوا به صفحه DevTools

پیام رسانی بین صفحه DevTools و اسکریپت های محتوا غیرمستقیم از طریق صفحه پس زمینه است.

هنگام ارسال پیام به یک اسکریپت محتوا، صفحه پس‌زمینه می‌تواند از روش tabs.sendMessage استفاده کند، که پیامی را به اسکریپت‌های محتوا در یک برگه خاص هدایت می‌کند، همانطور که در Injecting a Content Script نشان داده شده است.

هنگام ارسال پیام از یک اسکریپت محتوا، هیچ روش آماده ای برای ارسال پیام به نمونه صحیح صفحه DevTools مرتبط با برگه فعلی وجود ندارد. به عنوان راه‌حل، می‌توانید از صفحه DevTools بخواهید یک ارتباط طولانی مدت با صفحه پس‌زمینه برقرار کند، و صفحه پس‌زمینه نقشه شناسه‌های برگه‌ها را برای اتصالات نگه دارد تا بتواند هر پیام را به اتصال صحیح هدایت کند.

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

صفحه DevTools (یا پانل یا پانل نوار کناری) اتصال را به این صورت برقرار می کند:

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

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

ارسال پیام از اسکریپت های تزریق شده به صفحه DevTools

در حالی که راه حل فوق برای اسکریپت های محتوا کار می کند، کدی که مستقیماً به صفحه تزریق می شود (مثلاً از طریق اضافه کردن یک تگ <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);
});

پیام شما اکنون از اسکریپت تزریق شده، به اسکریپت محتوا، به اسکریپت پس زمینه و در نهایت به صفحه DevTools منتقل می شود.

همچنین می توانید دو تکنیک جایگزین ارسال پیام را در اینجا در نظر بگیرید.

تشخیص زمان باز و بسته شدن DevTools

اگر برنامه افزودنی شما باید باز بودن پنجره DevTools را ردیابی کند، می‌توانید یک شنونده onConnect را به صفحه پس‌زمینه اضافه کنید و از صفحه DevTools با اتصال تماس بگیرید. از آنجایی که هر برگه می تواند پنجره DevTools خود را باز کند، ممکن است چندین رویداد اتصال را دریافت کنید. برای ردیابی باز بودن پنجره DevTools، باید رویدادهای اتصال و قطع اتصال را مانند شکل زیر بشمارید:

// 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 یک اتصال مانند زیر ایجاد می کند:

// devtools.js

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

نمونه های برنامه افزودنی DevTools

منبع این نمونه های افزونه DevTools را مرور کنید:

  • افزونه Polymer Devtools - از بسیاری از کمک‌کنندگان در حال اجرا در صفحه میزبان برای پرس‌وجو از وضعیت DOM/JS استفاده می‌کند تا به پنل سفارشی ارسال شود.
  • React DevTools Extension - از زیر ماژول Blink برای استفاده مجدد از اجزای DevTools UI استفاده می کند.
  • Ember Inspector - هسته برنامه افزودنی مشترک با آداپتورهای کروم و فایرفاکس.
  • Coquette-inspect - یک برنامه افزودنی تمیز مبتنی بر React با یک عامل اشکال زدایی که به صفحه میزبان تزریق شده است.
  • گالری برنامه افزودنی DevTools و برنامه‌های افزودنی نمونه برنامه‌های ارزشمندتری برای نصب، امتحان کردن و یادگیری از آن‌ها دارند.

اطلاعات بیشتر

برای اطلاعات در مورد APIهای استانداردی که برنامه‌های افزودنی می‌توانند استفاده کنند، به chrome مراجعه کنید.* APIها و Web API .

به ما بازخورد بدهید! نظرات و پیشنهادات شما به ما در بهبود API ها کمک می کند.

نمونه ها

می‌توانید نمونه‌هایی را پیدا کنید که از APIهای DevTools در Samples استفاده می‌کنند.