Firebug internals

  • Revision slug: Firebug_internals
  • Revision title: Firebug internals
  • Revision id: 108887
  • Created:
  • Creator: JohnJBarton1
  • Is current revision? No
  • Comment /* Source Code */

Revision Content

Get Firebug

Source Code

Firebug source is available via subversion

Alternative:

  1. Get Firebug; The source is included.
  2. Find the installed firebug in the Mozilla extensions directory, eg
C:\Documents and Settings\John J. Barton\Application Data\Mozilla\Firefox\Profiles\w5tmpjcs.test\extensions\firebug@software.joehewitt.com\
  1. Copy the directory to your workspace
  2. find firebug.jar in the chrome directory.
  3. rename it to firebug.zip.
  4. unzip it such that chrome directory contains the content of the jar,eg
  • chrome/content
  • chrome/icons
  • chrome/locale
  • chrome/skin

Rezip the files into a jar for testing.

Major Components

  • Panels - these are the tabs in the firebug UI
  • Modules - ?
  • lib aka FBL aka Firebug Library - common functions used in many panels
  • firebug-service - javascript - implemented XPCOM component, in firebug/components.
  • sourceCache - stores .htm, .js content read for source views
  • reps.js - representations usually used by multiple panels.
  • error.js - console observer for nsIScriptError and nsIConsoleMessage
  • XUL files - structure for the UI
  • css files - decorations
  • firebug.js
    • Globals like top.Firebug: version state
    • Base objects:
      • Firebug.Module, base for eg debugger
      • Firebug.Panel, interface for panels

Extending Firebug

Checkout Christoph Dorn's awesome tutorial on Extending Firebug

Glue

  • context - a web page, passed to many functions.
  • Firebug.registerModule(Errors);
    • Errors extends Firebug.Module
  • Firebug.registerPanel(ScriptPanel);
    • ScriptPanel extends Panel

PluginPanel

PluginPanel defined in plugin.js

  • looks like a base for tabContext.createPanelType
  • getOptionsMenuItems is the options filling function, shows up on all panels
  • script panel is in debugger.js

debugger.js

Interface to firebug-service and implementation of the "script" panel.

debugger.showStackFrame

  • puts up the stack across the top of the script panel.

debuggr.onError(frame) called by FBS.onDebug(frame, type, rv)

  • so the frame should be a jsdIStackFrame
  • only called if reportNextError true, a flag set by onError when this.showStackTrace (console prefs)
  • sets Firebug.errorStackTrace (not per context?)


Firebug Service

fbs is FirebugService implemented in firebug-serivces.js, under components dir

 const fbs = CCSV("@joehewitt.com/firebug;1", "nsIFireBug");
 this.fbs = this.CCSV("@joehewitt.com/firebug;1", "nsIFireBug");
 this.jsd = this.CCSV("@mozilla.org/js/jsd/debugger-service;1", "jsdIDebuggerService");

Debugger objects can be registered with the service, then the service sets hooks (callbacks) into jsdIDebuggerService (jsd) and routes the results to the correct debugger for a given web page. The routing mechanism is a bit tricky: FBS calls supportsWindow for each debugger until one says "true"; as a side-effect of this call, the debugger sets breakContext equal to the window. Then FBS calls the debugger function (eg onXXX()) and the debugger (in its onXXX()) sets its context to breakContext. (The JS engine is thankfully single threaded).

interface nsIFireBugDebugger : nsISupports
{
  boolean supportsWindow(in nsIDOMWindow window);
  void onLock(in boolean state); 
  unsigned long onBreak(in jsdIStackFrame frame);
  unsigned long onHalt(in jsdIStackFrame frame);
  void onCall(in jsdIStackFrame frame);
  void onError(in jsdIStackFrame frame);
  void onResume();
  void onToggleBreakpoint(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleBreakpointCondition(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleBreakpointDisabled(in string url, in unsigned long lineNo, in boolean disabled);
  void onToggleErrorBreakpoint(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleMonitor(in string url, in unsigned long lineNo, in boolean isSet);
};

The service is in a different execution space from the UI; data only flows through the interfaces. This keeps jsd objects out of the UI for the most part. The all important stack is the major exception.

To change the service you must delete the file compreg.dat in the FF extension directory to force it to re-read the service definitions.

Extending nsIFirebug.idl

The firebug-service is an XPCOM component implemented in javascript. To change its API you need to create a new .idl file, compile it with xpidl.exe, and put the new .xpt file in to your .xpi file. Your interface should inherit from the ones in nsIFireBug.idl and your idl file should include nsIFireBug.idl You will also need two other idl files from XPCOM. These files and the xpcom.exe driver are available in the Gecko SDK.

The idl tools are rather terse so here are some hints for checking that you are making progress:

  • after you create your .xpt file, eg ./xpidl.exe -m typelib foo.idl, open the .xpt file, eg foo.xpt, with an edit like emacs that can show binary content. You should be able to make out the strings from your interface amongst the bits.
  • after you place your .xpt file in the components directory of your extension, delete xpti.dat from the Mozilla Firefox profile you are using. Run Firefox then open the xpti.dat file with a real editor. You should see your new interface(s) lists.
  • if you define a service, do the same check with compreg.dat.

Revision Source

<p><a class="external" href="http://getfirebug.com/">Get Firebug</a>
</p>
<h3 name="Source_Code"> Source Code </h3>
<p>Firebug source is available <a class="external" href="http://code.google.com/p/fbug/source">via subversion </a>
</p><p>Alternative:
</p>
<ol><li> <a class="external" href="http://getfirebug.com/">Get Firebug</a>; The source is included.
</li><li> Find the installed firebug in the Mozilla extensions directory, eg
</li></ol>
<pre class="eval">C:\Documents and Settings\John J. Barton\Application Data\Mozilla\Firefox\Profiles\w5tmpjcs.test\extensions\firebug@software.joehewitt.com\
</pre>
<ol><li> Copy the directory to your workspace
</li><li> find firebug.jar in the chrome directory.
</li><li> rename it to firebug.zip.
</li><li> unzip it such that chrome directory contains the content of the jar,eg
</li></ol>
<ul><li>chrome/content
</li><li>chrome/icons
</li><li>chrome/locale
</li><li>chrome/skin
</li></ul>
<p>Rezip the files into a jar for testing.
</p>
<h3 name="Major_Components"> Major Components </h3>
<ul><li> Panels - these are the tabs in the firebug UI
</li><li> Modules - ?
</li><li> lib aka FBL aka Firebug Library - common functions used in many panels
</li><li> <a href="#Firebug_Service"> firebug-service</a> - javascript - implemented XPCOM component, in firebug/components.
</li><li> sourceCache - stores .htm, .js content read for source views
</li><li> reps.js - representations usually used by multiple panels.
</li><li> error.js - console observer for nsIScriptError and nsIConsoleMessage
</li><li> XUL files - structure for the UI
</li><li> css files - decorations
</li><li> firebug.js 
<ul><li>Globals like top.Firebug: version state
</li><li>Base objects:
<ul><li>Firebug.Module, base for eg debugger
</li><li>Firebug.Panel, interface for panels
</li></ul>
</li></ul>
</li></ul>
<h3 name="Extending_Firebug"> Extending Firebug </h3>
<p>Checkout Christoph Dorn's awesome tutorial on <a class="external" href="http://code.google.com/p/firephp/wiki/ExtendingFirebug">Extending Firebug</a>
</p>
<h3 name="Glue"> Glue </h3>
<ul><li> context - a web page, passed to many functions.
</li><li> Firebug.registerModule(Errors);
<ul><li> Errors extends Firebug.Module
</li></ul>
</li><li> Firebug.registerPanel(ScriptPanel);
<ul><li> ScriptPanel extends Panel
</li></ul>
</li></ul>
<h3 name="PluginPanel"> PluginPanel </h3>
<p>PluginPanel defined in plugin.js
</p>
<ul><li> looks like a base for tabContext.createPanelType
</li><li> getOptionsMenuItems is the options filling function, shows up on all panels
</li><li> script panel is in debugger.js
</li></ul>
<h3 name="debugger.js"> debugger.js </h3>
<p>Interface to <a href="#Firebug_Service"> firebug-service</a> and implementation of the "script" panel.
</p><p>debugger.showStackFrame
</p>
<ul><li>puts up the stack across the top of the script panel.
</li></ul>
<p>debuggr.onError(frame) called by FBS.onDebug(frame, type, rv)
</p>
<ul><li> so the frame should be a jsdIStackFrame 
</li><li> only called if reportNextError true, a flag set by onError when this.showStackTrace (console prefs)
</li><li> sets Firebug.errorStackTrace (not per context?)
</li></ul>
<p><br>
</p>
<h3 name="Firebug_Service"> Firebug Service </h3>
<p>fbs  is FirebugService implemented in firebug-serivces.js, under components dir
</p>
<pre class="eval"> const fbs = CCSV("@joehewitt.com/firebug;1", "nsIFireBug");
 this.fbs = this.CCSV("@joehewitt.com/firebug;1", "nsIFireBug");
 this.jsd = this.CCSV("@mozilla.org/js/jsd/debugger-service;1", "jsdIDebuggerService");
</pre>
<p>Debugger objects can be registered with the service, then the service sets hooks (callbacks) into jsdIDebuggerService (jsd) and routes the results to the correct debugger for a given web page. The routing mechanism is a bit tricky: FBS calls <code>supportsWindow</code> for each debugger until one says "true"; as a side-effect of this call, the debugger sets breakContext equal to the window. Then FBS calls the debugger function (eg onXXX()) and the debugger (in its onXXX()) sets its context to breakContext. (The JS engine is thankfully single threaded).
</p>
<pre class="eval">interface nsIFireBugDebugger : nsISupports
{
  boolean supportsWindow(in nsIDOMWindow window);
  void onLock(in boolean state); 
  unsigned long onBreak(in jsdIStackFrame frame);
  unsigned long onHalt(in jsdIStackFrame frame);
  void onCall(in jsdIStackFrame frame);
  void onError(in jsdIStackFrame frame);
  void onResume();
  void onToggleBreakpoint(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleBreakpointCondition(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleBreakpointDisabled(in string url, in unsigned long lineNo, in boolean disabled);
  void onToggleErrorBreakpoint(in string url, in unsigned long lineNo, in boolean isSet);
  void onToggleMonitor(in string url, in unsigned long lineNo, in boolean isSet);
};
</pre>
<p>The service is in a different execution space from the UI; data only flows through the interfaces. This keeps jsd objects out of the UI for the most part.  The all important stack is the major exception.
</p><p>To change the service you must delete the file compreg.dat in the FF extension directory to force it to re-read the service definitions.
</p>
<h3 name="Extending_nsIFirebug.idl"> Extending nsIFirebug.idl </h3>
<p>The firebug-service is an XPCOM component implemented in javascript. To change its API you need to create a new .idl file, compile it with xpidl.exe, and put the new .xpt file in to your .xpi file.
Your interface should inherit from the ones in nsIFireBug.idl and your idl file should include nsIFireBug.idl  You will also need two other idl files from XPCOM.  These files and the xpcom.exe driver are available in the <a class="external" href="http://developer.mozilla.org/en/docs/Gecko_SDK">Gecko SDK</a>.
</p><p>The idl tools are rather terse so here are some hints for checking that you are making progress:
</p>
<ul><li> after you create your .xpt file, eg ./xpidl.exe -m typelib foo.idl, open the .xpt file, eg foo.xpt, with an edit like emacs that can show binary content.  You should be able to make out the strings from your interface amongst the bits.
</li><li> after you place your .xpt file in the components directory of your extension, delete <code>xpti.dat</code> from the Mozilla Firefox profile you are using. Run Firefox then open the <code>xpti.dat</code> file with a real editor.  You should see your new interface(s) lists.  
</li><li> if you define a service, do the same check with <code>compreg.dat</code>.
</li></ul>
Revert to this revision