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

סקירה כללית

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • חלונית היא כרטיסייה ברמה העליונה, כמו החלוניות 'רכיבים', 'מקורות' ו'רשת'.
  • חלונית צדדית מציגה ממשק משתמש נוסף שקשור ללוח. הסגנונות, הסגנונות המחושבים החלוניות של 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.

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

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

החדרת סקריפט של תוכן

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

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

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

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

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

זיהוי מתי כלי פיתוח נפתחים ונסגרים

אם התוסף צריך לעקוב אחרי פתיחת החלון של כלי הפיתוח, אפשר להוסיף 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"
});

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

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

מידע נוסף

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

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

דוגמאות

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