I’m working to create a functional test for Firebug’s Open-In-New-Window feature and then to get the feature to work again. In the process I think I’ve finally decoded how this feature works.
Here is the critical bit: Every Firebug window has a different copy of FirebugChrome, but they all share the same copy of the Firebug and FBL objects.
If you’ve looked through the Firebug source you should be familiar with the modules (controllers) and panels (views). You will also know the ubiquitous Firebug global object that holds everything together, the ‘context’ for each web page, and the utility code like
You will also have encountered FirebugChrome, but (if you are like me) its role seems a bit puzzling. It seems to be most–but curiously not all–of global UI related code. Now that I am deep into the open in new window feature, I can understand: it holds just the code to run the Firebug window UI, whether that UI is in the browser or in a separate window.
When you open Firebug in a new window you already have one copy of FirebugChrome in the Firefox window. This object manages the various bit of the Firebug ‘
chrome‘: the XUL overlays (
firebugOverlay.js), the XBL (
bindings.xml), and all of the CSS. In the scope of the new Firebug window, a newly created FirebugChrome manages the chrome in the window. This window is of course not Firefox (
browser.xul) but simple window defined in
That is not so surprising, but the next step is: immediately the newly created FirebugChrome sets the global Firebug and FBL objects to point back into the original Firefox window. So all of the modules, panels, reps, and the context management code in Firebug are shared across the windows, but the FirebugChrome is unique to each window. This is how Firebug can ‘detach’ and ‘reattach’ to the browser: the metadata is shared and never has to moved or synchronized between windows. (This is also why you almost never see window global object used in Firebug).
One function shows the special role of FirebugChrome more than any other:
setFirebugContext(context). This function (renamed in v1.4 from
showContext()) simply sets the global FirebugContext object to the argument
context. Beneath the simplicity lies the clues to how Open-In-New-Window works. Consider the call from a Firebug method:
browser is essentially Firefox tab. Hanging off the tab is a reference,
chrome, to the FirebugChrome object managing the Firebug window for the tab. If Firebug is open in Firefox, then
chrome points to FirebugChrome in Firefox. But if Firebug is open in a new window,
chrome points to a different FirebugChrome, the one managing the
firebug.xul window. So when we execute
setFirebugContext() we cross from the global object Firebug into the window-specific object FirebugChrome and then we set a global object, FirebugContext to one of the
context objects. That’s how we get two different values for FirebugContext, one in Firefox and one the new Firebug window. Got it?