Per-Window Private Browsing for Add-ons

Per-Window Private Browsing is coming soon (Bug 463027), and for addon developers this is going to mean a lot of work.

I’m going to be writting about the work being done for the Addon SDK soon, but for now I wanted to write some notes down for old school developers, because I think the change is going to be a painful one for some of us. When I think about the changes that I’m going to have to make to Scriptish I get a bit queasy.

First of all, the global private browsing service, nsIPrivateBrowsingService, is being deprecated, so a dummy service will still exist in it’s place for a few versions of Firefox. This is mainly because I didn’t see this change coming a long time ago when the SDK team would have needed to in order to correct older versions of the Add-on SDK (before they were released) so that they wouldn’t break when nsIPrivateBrowsingService is ripped out.. It turns out there are some important add-ons that are mainly used on Firefox nightly builds, and they all broke when nsIPrivateBrowsingService was removed. So would any other add-on using nsIPrivateBrowsingService too though of course.

Alas, here we are with a dummy service, which means that add-ons developers have 3 options:

  1. Raise their add-on’s menVersion supported to Firefox 20, remove the old nsIPrivateBrowsingService code and only support per-window private browsing.
  2. Support both global private browsing and per-window private browisng via code forks by Firefox version.
  3. Support both global private browsing and per-window private browisng via feature detection.

The first two are easy to understand how to do so I won’t bother explaining those, the latter I have a code snippet for:

let pbService;
let PrivateBrowsingUtils;

// get the nsIPrivateBrowsingService if it exists
try {
	pbService = Cc["@mozilla.org/privatebrowsing;1"].
	          getService(Ci.nsIPrivateBrowsingService);

	// a dummy service exists for the moment (Fx20 atleast), but will be removed eventually
	// ie: the service will exist, but it won't do anything and the global private browing
	//     feature is not really active.  See Bug 818800 and Bug 826037
	if (!('privateBrowsingEnabled' in pbService))
	  pbService = undefined;
} catch(e) { /* Private Browsing Service has been removed (Bug 818800) */ }

try {
	PrivateBrowsingUtils = Cu.import('resource://gre/modules/PrivateBrowsingUtils.jsm', {}).PrivateBrowsingUtils;
}
catch(e) { /* if this file DNE then an error will be thrown */ }

// checks that global private browsing is implemented
// if the global private browsing service dne here then it dne at all or it is a dummy
let isGlobalPBSupported = !!pbService;

// checks that per-window private browsing is implemented
// if the global pb service dne but the PrivateBrowsingUtils.jsm exists then assume
// is enabled.
let isWindowPBSupported = !isGlobalPBSupported && !!PrivateBrowsingUtils;

The last two variables defined here namely isGlobalPBSupported and isWindowPBSupported will tell you what is supported.

I’m sure a lot of people will say option 1 or 2 is the way to go, but I have to update Scriptish soon and I know that for me option 3 is really the only option for the short term, long term I’ll do option 1.

I’ll be writing about the changes that will be required for the Add-on SDK soon too.