הרחבת כלי הפיתוח

סקירה כללית

תוסף של כלי פיתוח מוסיף פונקציונליות לכלי הפיתוח ל-Chrome. ניתן להוסיף בה חלוניות וסרגלי צד חדשים של ממשק המשתמש, לבצע פעולות בדף שנבדק, לקבל מידע על בקשות ברשת ועוד. כאן תוכלו לראות את התוספים המומלצים של כלי הפיתוח. לתוספים של כלי הפיתוח יש גישה לקבוצה נוספת של ממשקי API לתוספים שהם ספציפיים לכלי פיתוח:

תוסף של DevTools מובנה כמו כל תוסף אחר: הוא יכול לכלול דף רקע, סקריפטים של תוכן ופריטים אחרים. בנוסף, לכל תוסף של DevTools יש דף DevTools, שכולל גישה לממשקי ה-API של כלי הפיתוח.

תרשים ארכיטקטורה שמציג את התקשורת של דף כלי הפיתוח עם
       החלון שנבדק ודף הרקע. מוצג דף הרקע במהלך התקשורת עם הסקריפטים של התוכן ועם הגישה לממשקי ה-API של התוספים.
       לדף של כלי הפיתוח יש גישה לממשקי ה-API של כלי הפיתוח, לדוגמה: יצירת לוחות.

הדף של כלי הפיתוח

מופע של דף DevTools של התוסף נוצר בכל פעם שנפתח חלון של כלי פיתוח. הדף של כלי הפיתוח קיים לכל משך החיים של חלון כלי הפיתוח. לדף של כלי הפיתוח יש גישה לממשקי ה-API של כלי הפיתוח ולקבוצה מוגבלת של ממשקי API של תוספים. באופן ספציפי, בדף כלי הפיתוח ניתן לבצע את הפעולות הבאות:

  • יוצרים לוחות ומקיימים איתם אינטראקציה באמצעות ממשקי ה-API של devtools.panels.
  • קבלת מידע על החלון שנבדק וביצוע הערכה של הקוד בחלון שנבדק באמצעות ממשקי ה-API של devtools.inspectedWindow.
  • קבלת מידע על בקשות ברשת באמצעות ממשקי ה-API של devtools.network.

רוב ממשקי ה-API של התוספים לא יכולים להשתמש ישירות בדף של כלי הפיתוח. יש לו גישה לאותה קבוצת משנה של ממשקי ה-API של extension ו-runtime שיש לסקריפט תוכן גישה אליהם. בדומה לסקריפט תוכן, גם דף של DevTools יכול לתקשר עם דף הרקע באמצעות העברת הודעות. לדוגמה, תוכלו לקרוא את המאמר החדרת סקריפט תוכן.

יצירת תוסף של כלי פיתוח

כדי ליצור דף של כלי פיתוח לתוסף, מוסיפים את השדה devtools_page במניפסט של התוסף:

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

מופע של ה-devtools_page שצוין במניפסט של התוסף נוצר לכל חלון של כלי פיתוח שנפתח. יכול להיות שהדף יתווסף כחלוניות וסרגלי צד לחלון של כלי הפיתוח באמצעות devtools.panels API.

המודולים של chrome.devtools.* API זמינים רק לדפים שנטענים בחלון כלי הפיתוח. סקריפטים של תוכן ודפי תוספים אחרים לא כוללים את ממשקי ה-API האלה. לכן ממשקי ה-API זמינים רק לכל משך החיים של חלון כלי הפיתוח.

יש גם כמה ממשקי API של כלי פיתוח שעדיין ניסיוניים. מידע נוסף זמין בכתובת chrome.experimentsal.* ממשקי API לרשימה של ממשקי ה-API הניסיוניים והנחיות לשימוש בהם.

רכיבי ממשק המשתמש של כלי הפיתוח: חלוניות וחלוניות של סרגלי צד

בנוסף לרכיבים הרגילים בממשק המשתמש של התוספים, כמו פעולות דפדפן, תפריטי הקשר וחלונות קופצים, תוסף של כלי פיתוח יכול להוסיף רכיבים של ממשק המשתמש לחלון של כלי הפיתוח:

  • חלונית היא כרטיסייה ברמה העליונה, כגון החלוניות 'רכיבים', 'מקורות' ו'רשת'.
  • בחלונית צדדית מוצג ממשק משתמש משלים שקשור לחלונית. החלוניות Styles, Computed Styles ו-Event Listeners בחלונית Elements הן דוגמאות לחלוניות בסרגל הצד. (שימו לב: יכול להיות שהמראה של חלוניות סרגל הצד לא יתאים לתמונה, בהתאם לגרסת Chrome שבה אתם משתמשים ולמיקום שבו חלון כלי הפיתוח מוצמד).

חלון של כלי פיתוח עם החלונית 'רכיבים' וחלונית סרגל הצד של סגנונות.

כל חלונית היא קובץ HTML משלה, שאפשר לכלול בו משאבים אחרים (JavaScript, CSS, תמונות וכו'). כך נראית יצירה של לוח בסיסי:

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

ל-JavaScript שמופעל בחלונית או בחלונית סרגל צד יש גישה לאותם ממשקי API כמו בדף כלי הפיתוח.

יצירת חלונית בסיסית של סרגל צד עבור חלונית הרכיבים נראית כך:

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.

תקשורת בין רכיבי התוסף

בקטעים הבאים מתוארים כמה תרחישים אופייניים לתקשורת בין הרכיבים השונים של תוסף DevTools.

הזרקת סקריפט תוכן

אי אפשר להפעיל את 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 של DevTools, כמו בדיקת רכיבים (inspect(elem)), פריצת פונקציות (debug(fn)), העתקה ללוח (copy()) ועוד. ב-inspectedWindow.eval() נעשה שימוש באותו הקשר ובאפשרויות לביצוע סקריפט כמו בקוד שהוזן במסוף כלי הפיתוח, כדי לאפשר גישה לממשקי ה-API האלה בתוך ההערכה. לדוגמה, הקוד 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 יש גישה למסוף כלי הפיתוח ולממשקי API של שורת הפקודה. לדוגמה, בקוד מוערך אפשר להשתמש בפונקציה $0 כדי לגשת לרכיב שנבחר.

כדי להעביר את הרכיב שנבחר אל סקריפט תוכן:

  • יוצרים שיטה בסקריפט התוכן שמקבלת את הרכיב שנבחר כארגומנט.
  • מפעילים את השיטה מהדף של כלי הפיתוח באמצעות inspectedWindow.eval עם האפשרות useContentScriptContext: true.

הקוד בסקריפט התוכן עשוי להיראות כך:

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

יש להפעיל את השיטה מהדף DevTools באופן הבא:

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

האפשרות useContentScriptContext: true מציינת שיש להעריך את הביטוי באותו הקשר של הסקריפטים של התוכן, כדי שניתן יהיה לגשת באמצעותו ל-method setSelectedElement.

מקבלים window של חלונית הפניה

כדי לבצע postMessage מחלונית של כלי פיתוח, יש צורך בהפניה לאובייקט window שלו. שליפה של חלון iframe של לוח מה-handler של האירועים panel.onShown:

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

העברת הודעות מסקריפטים של תוכן אל הדף של כלי הפיתוח

העברת ההודעות בין הדף של כלי הפיתוח לבין הסקריפטים של התוכן היא עקיפה דרך דף הרקע.

כששולחים הודעה אל סקריפט תוכן, דף הרקע יכול להשתמש בשיטה tabs.sendMessage, שמעבירה את ההודעה לסקריפטים של התוכן בכרטיסייה ספציפית, כפי שמוצג בקטע החדרת סקריפט תוכן.

כששולחים הודעה מסקריפט תוכן, אין שיטה מוגדרת מראש לשליחת הודעה למופע הנכון של דף כלי הפיתוח שמשויך לכרטיסייה הנוכחית. כפתרון עקיף, אפשר לבקש מדף ה-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;
});

בדף של כלי הפיתוח (או בחלונית או בחלונית של סרגל הצד) נוצר החיבור באופן הבא:

// 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 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, אפשר להוסיף האזנה של onConnect לדף הרקע ולהפעיל את connect מהדף 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.js

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

דוגמאות לתוספי כלי פיתוח

דוגמאות לתוספים הבאים של כלי פיתוח:

מידע נוסף

מידע על ממשקי ה-API הרגילים שבהם אפשר להשתמש בתוספים זמין בכתובת chrome.* ממשקי API וממשקי API לאינטרנט.

נשמח לקבל ממך משוב! ההערות וההצעות שלכם יעזרו לנו לשפר את ממשקי ה-API.

דוגמאות

בקטע דוגמאות מופיעות דוגמאות לשימוש בממשקי API של כלי פיתוח.