توسيع نطاق أدوات مطوّري البرامج

نظرة عامة

تضيف إضافات "أدوات مطوّري البرامج" وظائف إلى "أدوات مطوّري البرامج في Chrome". ويمكنها إضافة لوحات وأشرطة جانبية جديدة لواجهة المستخدم، والتفاعل مع الصفحة التي يتم فحصها، والحصول على معلومات حول طلبات الشبكة، وغير ذلك. عرض إضافات "أدوات مطوّري البرامج" المميّزة. يمكن لإضافات "أدوات مطوّري البرامج" الوصول إلى مجموعة إضافية من واجهات برمجة التطبيقات الخاصة بأدوات مطوّري البرامج:

تتم هيكلة إضافات "أدوات مطوّري البرامج" مثل أي إضافة أخرى: يمكن أن تحتوي على صفحة في الخلفية ونصوص برمجية للمحتوى وعناصر أخرى. بالإضافة إلى ذلك، تحتوي كل إضافة من إضافات "أدوات مطوّري البرامج" على صفحة "أدوات مطوّري البرامج" التي يمكنها الوصول إلى واجهات برمجة التطبيقات الخاصة بأدوات مطوّري البرامج.

مخطّط هندسي يعرض صفحة "أدوات مطوّري البرامج" وهي تتواصل مع النافذة التي تم فحصها وصفحة الخلفية تظهر صفحة الخلفية وهي تتواصل مع نصوص المحتوى البرمجية وتصل إلى واجهات برمجة التطبيقات الخاصة بالإضافة.
       يمكن لصفحة "أدوات مطوّري البرامج" الوصول إلى واجهات برمجة التطبيقات الخاصة بها، مثل إنشاء اللوحات.

صفحة "أدوات مطوّري البرامج"

يتم إنشاء مثيل لصفحة "أدوات مطوّري البرامج" الخاصة بالإضافة في كل مرة يتم فيها فتح نافذة "أدوات مطوّري البرامج". وتظل صفحة "أدوات مطوّري البرامج" متاحة طوال فترة بقاء نافذة "أدوات مطوّري البرامج". يمكن لصفحة "أدوات مطوّري البرامج" الوصول إلى واجهات برمجة التطبيقات الخاصة بأدوات مطوّري البرامج ومجموعة محدودة من واجهات برمجة التطبيقات الخاصة بالإضافات. على وجه التحديد، يمكن لصفحة "أدوات مطوّري البرامج" إجراء ما يلي:

  • إنشاء لوحات والتفاعل معها باستخدام واجهات برمجة التطبيقات devtools.panels
  • الحصول على معلومات حول النافذة التي يتم فحصها وتقييم الرمز في النافذة التي يتم فحصها باستخدام devtools.inspectedWindow واجهات برمجة التطبيقات
  • الحصول على معلومات حول طلبات الشبكة باستخدام واجهات برمجة التطبيقات devtools.network

لا يمكن لصفحة "أدوات مطوّري البرامج" استخدام معظم واجهات برمجة التطبيقات الخاصة بالإضافات مباشرةً. يمكنها الوصول إلى المجموعة الفرعية نفسها من واجهات برمجة التطبيقات extension وruntime التي يمكن للنص البرمجي للمحتوى الوصول إليها. على غرار النص البرمجي للمحتوى ، يمكن لصفحة "أدوات مطوّري البرامج" التواصل مع صفحة الخلفية باستخدام ميزة تمرير الرسائل. للاطّلاع على مثال، يُرجى مراجعة مقالة إدخال نص برمجي للمحتوى.

إنشاء إضافة "أدوات مطوّري البرامج"

لإنشاء صفحة "أدوات مطوّري البرامج" للإضافة، أضِف الحقل devtools_page في بيان الإضافة:

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

يتم إنشاء مثيل لـ devtools_page المحدّدة في بيان الإضافة لكل نافذة من نوافذ "أدوات مطوّري البرامج" يتم فتحها. يمكن للصفحة إضافة صفحات أخرى من صفحات الإضافة كلوحات وأشرطة جانبية إلى نافذة "أدوات مطوّري البرامج" باستخدام واجهة برمجة التطبيقات devtools.panels.

لا تتوفّر وحدات برمجة التطبيقات chrome.devtools.* إلا للصفحات التي يتم تحميلها داخل نافذة "أدوات مطوّري البرامج". لا تتوفّر واجهات برمجة التطبيقات هذه للنصوص البرمجية للمحتوى وصفحات الإضافة الأخرى. وبالتالي، لا تتوفّر واجهات برمجة التطبيقات إلا طوال فترة بقاء نافذة "أدوات مطوّري البرامج".

هناك أيضًا بعض واجهات برمجة التطبيقات الخاصة بأدوات مطوّري البرامج التي لا تزال تجريبية. يُرجى الرجوع إلى مقالة chrome.experimental.* واجهات برمجة التطبيقات للاطّلاع على قائمة واجهات برمجة التطبيقات التجريبية والإرشادات حول كيفية استخدامها.

عناصر واجهة مستخدم "أدوات مطوّري البرامج": اللوحات والأشرطة الجانبية

بالإضافة إلى عناصر واجهة المستخدم العادية للإضافة، مثل إجراءات المتصفّح وقوائم السياق والنوافذ المنبثقة، يمكن لإضافة "أدوات مطوّري البرامج" إضافة عناصر واجهة مستخدم إلى نافذة "أدوات مطوّري البرامج":

  • اللوحة هي علامة تبويب على المستوى الأعلى، مثل لوحات "العناصر" و"المصادر" و"الشبكة".
  • الشريط الجانبي يعرض واجهة مستخدم تكميلية ذات صلة بلوحة. تُعدّ الأشرطة الجانبية "الأنماط" و"الأنماط المحتسَبة" و"مستمعو الأحداث" في لوحة "العناصر" أمثلة على الأشرطة الجانبية. (يُرجى العِلم أنّ مظهر الأشرطة الجانبية قد لا يتطابق مع الصورة، وذلك حسب إصدار Chrome الذي تستخدمه ومكان تثبيت نافذة "أدوات مطوّري البرامج").

نافذة "أدوات مطوّري البرامج" تعرض لوحة "العناصر" ولوحة الشريط الجانبي "الأنماط".

كل لوحة هي ملف HTML خاص بها، ويمكن أن تتضمّن موارد أخرى (JavaScript وCSS والصور وما إلى ذلك). يبدو إنشاء لوحة أساسية على النحو التالي:

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

يمكن لرمز JavaScript الذي يتم تنفيذه في لوحة أو شريط جانبي الوصول إلى واجهات برمجة التطبيقات نفسها التي يمكن لصفحة "أدوات مطوّري البرامج" الوصول إليها.

يبدو إنشاء شريط جانبي أساسي للوحة "العناصر" على النحو التالي:

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 من صفحة "أدوات مطوّري البرامج" أو لوحة أو شريط جانبي.

يتم تلقائيًا تقييم التعبير في سياق الإطار الرئيسي للصفحة. قد تكون على دراية الآن بميزات واجهة برمجة التطبيقات لسطر الأوامر في "أدوات مطوّري البرامج" ، مثل فحص العناصر (inspect(elem))، والتوقف عند الدوال (debug(fn))، والنسخ إلى الحافظة (copy()) وغير ذلك. تستخدِم inspectedWindow.eval() سياق تنفيذ النص البرمجي والخيارات نفسها التي يستخدمها الرمز الذي يتم إدخاله في وحدة تحكّم "أدوات مطوّري البرامج"، ما يتيح الوصول إلى واجهات برمجة التطبيقات هذه ضمن `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 للصفحة التي يتم فحصها. للاطّلاع على التحذيرات التفصيلية ومقارنة الطريقتَين، يُرجى مراجعة inspectedWindow.

تمرير العنصر المحدّد إلى نص برمجي للمحتوى

لا يمكن للنص البرمجي للمحتوى الوصول مباشرةً إلى العنصر المحدّد حاليًا. ومع ذلك، يمكن لأي رمز تنفّذه باستخدام inspectedWindow.eval الوصول إلى وحدة تحكّم "أدوات مطوّري البرامج" وواجهات برمجة التطبيقات لسطر الأوامر. على سبيل المثال، يمكنك استخدام $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. في ما يلي مثال، بافتراض النص البرمجي في الخلفية من القسم السابق:

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

ستنتقل رسالتك الآن من النص البرمجي الذي تم إدخاله إلى النص البرمجي للمحتوى، ثم إلى النص البرمجي في الخلفية، وأخيرًا إلى صفحة "أدوات مطوّري البرامج".

يمكنك أيضًا استخدام تقنيتَين بديلتَين لتمرير الرسائل هنا.

رصد وقت فتح "أدوات مطوّري البرامج" وإغلاقها

إذا كانت الإضافة بحاجة إلى تتبُّع ما إذا كانت نافذة "أدوات مطوّري البرامج" مفتوحة، يمكنك إضافة مستمع onConnect إلى صفحة الخلفية، واستدعاء 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"
});

أمثلة على إضافات "أدوات مطوّري البرامج"

تصفَّح مصدر الأمثلة التالية على إضافات "أدوات مطوّري البرامج":

مزيد من المعلومات

للحصول على معلومات حول واجهات برمجة التطبيقات العادية التي يمكن للإضافات استخدامها، يُرجى الاطّلاع على مقالة chrome.* واجهات برمجة التطبيقات وواجهات برمجة تطبيقات الويب.

لا تنسَ إرسال التعليقات! تساعدنا ملاحظاتك واقتراحاتك في تحسين واجهات برمجة التطبيقات.

أمثلة

يمكنك العثور على أمثلة تستخدِم واجهات برمجة التطبيقات الخاصة بأدوات مطوّري البرامج في مقالة النماذج.