Gecko: gBrowser and tabs

As anyone who hacks on Gecko knows, the project’s documentation is, um, lacking. This is sometimes Ok if all you do is work on Gecko; But for us that dive in and out of Gecko every few weeks … let’s just say, it can drive one a little insane. It also makes it really hard to learn what the f$%# is going on and wastes tremendous amounts of (my) time just getting something up an running (I’m talking days).

Anyway, I’m writing these posts mostly for myself, so I can avoid having to go through the pain of having to (re)learn Gecko’s JS APIs every few weeks.

If you want to follow along, make sure you clone Mozilla central and then:

./mach build
./mach run

After you build you also need go to “about:config” in the browser and set the preferences <code>devtools.debugger.remote-enabled</code>, <code>devtools.debugger.chrome-enabled</code>, and <code>devtools.chrome.enabled</code>. This will allow the -jsdebugger argument (the browser toolbox) to work. Thanks to Andreas Tolfsen who pointed this out in the comments!

Now, shut down the running instance of Nightly, because we need to launch a new one. Type into your terminal:


./mach run -P "coding" -jsdebugger -purgecaches

The -P is for profile (I’m using one called “coding”). The -jsdebugger option opens the “Browser toolbox” automatically. And -purgecaches dumps the JSM caches, avoiding a whole bunch of headaches.

window

At the top of the Gecko hierarchy, there is a window (similar to HTML), but this window represents the actual application window. This means that the interface is different to HTML’s Window object. You can test this by, for instance:

//Maximize the window, and the restore it to its previous location
window.maximize();
window.restore();

This window actually points to “chrome://browser/content/browser.xul”, which is basically what the browser is composed of (XUL elements – which implement the common DOM Interfaces).

gBrowser

Inside window there is gBrowser: this object represents the browser window. You can confirm this by, for instance, calling gBrowser.addTab("http://google.com"). This will add a tab. So:

const tab = gBrowser.addTab("http://google.com");

Tabs are opened in the background and are not “selected” (i.e., the focused one, independently of window focus).

//bring the new tab to the foreground
gBrowser.selectedTab = tab;

The main purpose for creating a tab will generally be to load content and possibly do something with that content. Inside each tab, there is a Browser, which is not directly accessible through the Tab‘s interface. Also, a Tab object does not provide direct access to the Window object of the tab. Instead you need to use a method from gBrowser to get at it:

//Get the "browser"
const browser = tab.linkedBrowser;
//Get the actual window object.
//NOTE: YOU CAN'T USE win yet! see below!
const win = browser.contentWindow

Note that this puts your in a race condition (the Document object won’t be ready), so you need to wait for the actual page to “show”. this is done through the undocumented pageshow event.

const pageShow = function() {
browser.removeEventListener('pageshow', pageShow);
//do something interesting
win.document.body.innerHTML = '<h1>Yay!</h1>';
}
browser.addEventListener('pageshow', pageShow);

Of course, once you have the Window object, then you are back in Web Development land and all is good. Once you are finished with a tab, you can remove it:

//clean up!
gBrowser.removeTab(tab);

Note: don’t be fooled by the .remove() method on the Tab object. That corresponds to the DOM interface’s .remove() method, which removes the node from the XBL tree, but doesn’t actually destroy the Tab. So, calling this can cause memory leaks. For example, when you run this against mochitests, you might see something like:


TEST-UNEXPECTED-FAIL | dom/manifest/test/browser_ManifestObtainer_obtain.jsleaked 1 docShell(s) until shutdown

Transitioning to TLS

tl;dr: Migrating old content and infrastructure to TLS is still f’ing hard. If you are using CloudFlare, see “How do I fix the infinite redirect loop error after enabling Flexible SSL with WordPress?“.

After the recent push by many in the standards community to transition our sites to TLS, I decided to move my blog over to TLS. The push is driven the the need to generally try to make the Web more secure + we are trying to move the Web forward by requiring TLS for certain APIs (e.g., Service Workers).

This is not the first time I’ve moved this blog to use TLS.

Early attempt

The first time I did this was a few years ago when I became interested in encryption. During that time, AFAIK, in order to have a SSL certificate you needed to have a static IP address. Furthermore, there was no intermediary services, like StartSSL or CloudFlare, to provide sites with essentially free certificates. Doing the transition to SSL with my host (DreamHost) was fairly straight forward, but quite expensive for me at the time (I was a student or a junior engineer at the time). I don’t recall the exact numbers, but it was effectively something like $25/year for a static IP and then probably something like $50/year for the cert. This on top of the 10/year for the domain + $150 something/year I pay for hosting. Eventually, the cost became a burden to me: only a small handful of people ever visit this site (I don’t know how many as I don’t use analytics our of respect for my visitors) – but I just didn’t feel it was worth the cost so I abandoned it.

This was pre-Snowden, so I was fairly naive to the dragnet activities of the likes of the those assholes at the NSA. I also didn’t understand that, even if your site’s content is harmless, it serves as a data-point in a visitors history. By using TLS, one obscures the navigational trail: they may know you looked at marcosc.com, but not what you were reading. It can help a little.

CloudFlare

More recently, in light of all the bad shit that’s happening in the world, and prompted by Anne van Kesteren, I decided to re-encrypt this site. However, this time around I had a very negative experience trying to transition my personal blog to TLS.

After complaining to Anne about the costs, he pointed me to CloudFlare with the claims about it being free. The setup experience with CloudFlare was pretty straight forward: put a few things into a form and then go and tell DreamHost that the DNS values had changed. No big deal… but then things started to get fun.

Firstly, although my site started working straight away over TLS, I had to wait 4 days for the certificate to actually say it was for “marcosc.com”- during which time browsers accessing my site over HTTPS would see the red warning screen (effectively blocking anyone visiting the site over HTTPS). Thankfully, I had left plain old HTTP access enabled.

Once my certificate was actually granted and working, I decided to disable HTTP altogether. I did this by telling WordPress that this site’s URL was now “https://marcosc.com” – which immediately triggered a cascade of shit. Firstly, the site went into an infinite redirect loop and the whole site became inaccessible. I tried to revert this change in WordPress’ database, but it didn’t seem to help. I then tried to revert various things – but also didn’t work so I just left it be as I had other work to do.

I was offline for about 1 week, then thankfully WordPress issued an update. This seemed to fix things somewhat: at least the site started working again over HTTP. However, switching to HTTPS is still quite broken – the admin section is still completely broken. It won’t load styles because WordPress is too stupid to realize it is running over HTTPS instead of HTTP.

Anyway, and I’m still struggling with various things. Migrating old content and infrastructure to TLS is still hard.

Gargoyles

I recently found myself (re)reading Neil Stephenson’s Snow Crash for the one billionth time. In it, there is a great passage about “gargoyles”:

“Gargoyles represent the embarrassing side of the Central Intelligence Corporation. Instead of using laptops, they wear their computers on their bodies, broken up into separate modules that hang on the waist, on the back, on the headset. They serve as human surveillance devices, recording everything that happens around them. Nothing looks stupider; these getups are the modern-day equivalent of the slide-rule scabbard or the calculator pouch on the belt, marking the user as belonging to a class that is at once above and far below human society. They are a boon to Hiro because they embody the worst stereotype of the CIC stringer. They draw all the attention. The payoff for this self-imposed ostracism is that you can be in the Metaverse all the time… Gargoyles are rude by definition.”

What’s great about this bit of the book is how concisely Stephenson captures the anxiety about wearables and surveillance. The simultaneously positive and negative societal response to things like Google Glass and even BlueTooth headsets. At once, we are fascinated by the affordances of these technologies for personal use – while at the same time we are repulsed by the lack of agency and sense of disempowerment that comes from people using them around us – and so “marking the user as belonging to a class above and far below human society”.

In public spaces, we’ve come to naturalize that corporations and the government constantly survey us through, for example, ceiling mounted cameras (to the degree that we believe that such actions keep us safe or protect property) – but the thought that a fellow citizen would partake in such dehumanizing activities tends to put those people in a class far below human society. I say these are dehumanizing activities because the can so easily be used to violate our right to privacy – even in public spaces: this can be at work, at a bar, of just out on the street. It’s not possible to know if we are either being recorded by the user or if we are being watched remotely by a nefarious third-party (without the consent or knowledge of the wearer). And the fact that the wearer cannot provide any guarantees about what the device is doing marks them as suspicious at best, and arrogant or even naive at worst (a class far below human society).

At the same time, our fascination with the new affordances of these devices draws us to the wearers of such devices – putting them in a class above. The chosen ones. The explorers. “What’s it like?”, we either ask directly or just wonder.

*In Snow Crash, the CIA has been privatized – hence Central Intelligence Corporation.