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

نظرة عامة

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

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

// 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.* واجهات برمجة التطبيقات وواجهات برمجة تطبيقات الويب.

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

أمثلة

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