Songbird Wiki > Developer Center > Articles > Porting Firefox Extensions

Porting Firefox Extensions

From $1

Applicable to Songbird version: 1.0
Required Knowledge: Javascript, XUL

Introduction

Because Songbird is built on the Mozilla platform, it shares a large amount of code and compatibility with other Mozilla applications, namely Firefox. As such, it can be quite trivial to port many Firefox extensions to also be compatible with Songbird. That being said, while Songbird is built on Mozilla... and Firefox is built on Mozilla... Songbird is NOT built on Firefox. There will undoubtedly be methods and variables that are deep in the bowels of Firefox code that are not necessarily supported (yet) by Songbird.

Because it is (nigh) impossible to exhaustively cover all of the issues involved with porting arbitrary Firefox extensions to Songbird, this guide will instead walk through the process used to port two existing extensions. The first, to illustrate the trivial case, will be the Full Screen Homestar Runner extension, and the second will be the very popular Greasemonkey extension. Since we can't cover everything you will likely encounter (though we wish we could!), some good resources to check out if you get stuck are our Add-on developer forum, and our IRC channel at irc.mozilla.org, #songbird for some real-time help.

Before you start

Prior knowledge of developing Firefox extensions is recommended for this walk-through. This guide is geared towards people familiar with XUL and Javascript, and have had familiarity with working on or with Firefox extensions. Familiarity with Songbird extensions is *not* required, though may be helpful.

We have additional guides and walkthroughs for Songbird extension developers in our Songbird Developer Center.

Full Screen Homestar Runner (a.k.a. the basics)

The Full Screen Homestar Runner extension is a good example of a pretty basic add-on in terms of functionality. As you can see from its description, it's sole purpose is to scale an embedded bit of Flash to the full size of the browser. It does all this via Javascript, and doesn't overlay or modify any additional UI elements. As you would suspect, this makes our job pretty easy. In fact, it means that we only need to make two small modifications:

  • Chrome Overlay
  • Application Compatibility

Chrome Overlay

What? Didn't you just say FSHR doesn't overlay any additional UI?!?!?

Yes - but this overlay is necessary to get the Javascript loaded into Firefox/Songbird. Typically, Firefox extensions have a chrome.manifest that overlay chrome://browser/content/browser.xul, e.g.

chrome.manifest (Firefox)
content	fullhsr	chrome/content/
overlay chrome://browser/content/browser.xul chrome://fullhsr/content/browser.xul

In Songbird, these scripts should instead retarget to overlay chrome://songbird/content/xul/mainScriptsOverlay.xul, e.g.

chrome.manifest (Songbird)
content	fullhsr	chrome/content/
overlay chrome://songbird/content/xul/mainScriptsOverlay.xul chrome://fullhsr/content/browser.xul

Of course, the best solution is to have the add-on load in both Firefox AND Songbird. Since Firefox doesn't have any overlays conflicting with Songbird's chrome URL, we can simply have both overlay entries in the chrome.manifest, e.g.

chrome.manifest (Compatible with both!)
content	fullhsr	chrome/content/
overlay chrome://browser/content/browser.xul chrome://fullhsr/content/browser.xul
overlay chrome://songbird/content/xul/mainScriptsOverlay.xul chrome://fullhsr/content/browser.xul


 

mainScriptsOverlay.xul is now obsolete, you should overlay content/xul/layoutWithBrowserOverlay.xul

Application Compatibility

Another small change needed is to the install.rdf. This is the file that specifies, among other things, which applications the extension is compatible with. Firefox extensions will advertise something like:

install.rdf (Firefox)
<em:targetApplication>
	<Description>
		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
		<em:minVersion>1.0</em:minVersion>
		<em:maxVersion>2.0.0.*</em:maxVersion>
	</Description>
</em:targetApplication>

The ID {ec8030f7-c20a-464f-9b0e-13a3a9e97384} is the GUID for the Firefox application. To have your extension advertise compatibility with Songbird, all you simply have to do is add a targetApplication block for Songbird, like so:

install.rdf (Compatible with both!)
<em:targetApplication>
	<Description>
		<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
		<em:minVersion>1.0</em:minVersion>
		<em:maxVersion>2.0.0.*</em:maxVersion>
	</Description>
</em:targetApplication>
<em:targetApplication>
	<Description>
		<em:id>songbird@songbirdnest.com</em:id>
		<em:minVersion>0.7.0</em:minVersion>
		<em:maxVersion>1.0.*</em:maxVersion>
	</Description>
</em:targetApplication>

Greasemonkey (a.k.a. the not so basics)

One of our developers, Ian, blogged about porting Greasemonkey to Songbird, earlier - but we'll try to dive into some more of the specifics of what was involved. You can see from his blog post that he had to do the same two changes to the chrome.manifest (to overlay the right chrome to be loaded into each browser window) and install.rdf (for application compatibility) that we did above for the Full Screen Homestar Runner extension.

Taking a look at the patch Ian submitted upstream to the Greasemonkey developers we can see a few additional changes:

chrome/chromeFiles/content/browser.js
GM_BrowserUI.QueryInterface = function(aIID) { 
	if (!aIID.equals(Components.interfaces.nsISupports) &&
			!aIID.equals(Components.interfaces.gmIBrowserWindow) &&
			!aIID.equals(Components.interfaces.nsISupportsWeakReference))
			!aIID.equals(Components.interfaces.nsISupportsWeakReference) &&
			!aIID.equals(Components.interfaces.nsIWebProgressListener))
		throw Components.results.NS_ERROR_NO_INTERFACE;
	
	return this;

We can see here that Ian added one more condition to reflect the fact that GM_BrowserUI implements the nsIWebProgressListener interface. This was actually a minor bug in Greasemonkey that would have had to have been fixed anyway for Firefox 3 (which uses the same Gecko 1.9 engine as Songbird)

chrome/chromeFiles/content/browser.js
GM_BrowserUI.chromeLoad = function(e) {
	// get all required DOM elements
	this.tabBrowser = document.getElementById("content");
	this.appContent = document.getElementById("appcontent");

	.
	.
	.

	// songbird compat
	if (!this.appContent && this.tabBrowser) {
		this.appContent = this.tabBrowser.parentNode;
	}

At the time Ian did his work, Songbird didn't define the appcontent element (parent of content), which is why this was in the patch. While Ian was working on this, he filed bug 5035 against Songbird to define some commonly used Firefox IDs. This led to Songbird being updated (line 169, among many other changes detailed in the bug report) with lots of ID compatibility for common elements shared with Firefox to make it easier for extension porting.

chrome/chromeFiles/content/browser.js
// this gives us onLocationChange 
document.getElementById("content").addProgressListener(this,
this.tabBrowser.addProgressListener(this,
	Components.interfaces.nsIWebProgress.NOTIFY_LOCATION); 
.
.
.
GM_BrowserUI.openInTab = function(domWindow, url) { 
	if (this.isMyWindow(domWindow)) { 
		document.getElementById("content").addTab(url);
		this.tabBrowser.addTab(url);
	} 
}

This block merely updates calls to use the this.tabBrowser element Greasemonkey set above. This wasn't strictly necessary for Songbird compatibility, it's just good coding. Ian is like that.

chrome/chromeFiles/content/browser.xul
<statusbarpanel id="gm-status" insertafter="livemark-button">
	<label id="gm-status-label" collapsed="true" crop="end" style="width:0px; margin:0;" />
	<image id="gm-status-image" width="16" height="16" style="margin:0 5px" 
		mousethrough="never"
		onclick="if (!event.button) GM_setEnabled(!GM_getEnabled()); 
		else if (event.button == 1) GM_BrowserUI.manageMenuItemClicked();" 
		context='gm-status-popup'/> 

This last change in the browser.xul file makes sure that the Greasemonkey icon in the status bar doesn't pass mouse events through to the underlying object (the statusbarpanel). In Songbird, that area is "draggable" so that the user can move the window around. This patch ensures that the Greasemonkey icon won't be trated as draggable.

Summary

We've endeavoured to make porting a Firefox extension to Songbird as straight-forward as possible. We've used same IDs for the same (or analogous) elements as Firefox, so overlays of common components such as the navigation bar (navigation-toolbar), status bar (statusbar), and menus should work pretty well. That being said, there are components (such as the Songbird Service Pane, the Firefox sidebar, or Bookmarks) which are vastly different. If your extension sticks to common UI elements, and well-defined Javascript objects and methods, then it should be a pretty straight-forward port. If, on the other hand, it utilises elements such as the Firefox sidebar, or the Bookmarks system, then things get considerably trickier and more complicated.

If you run across something which you think would make it easier for Firefox extension porters, please do file a bug so we know. We'd love to make these ports as smooth and easy as possible. And if you're lost, stuck, or just want to chat.... don't forget to ask for ...

Help!

Stuck? Need some moral support? Better yet, need some technical support? Pop on by our Add-on developer forum, or drop in on our IRC channel at irc.mozilla.org, #songbird. We'd love to chat and try to help you get things working smoothly in Songbird.

Tags:
 
Images (0)
 
Comments (0)
You must login to post a comment.