Getting Your Geolocation in Firefox / Firefox OS

Getting your Geolocation in a browser is a fairly easy feature to understand yet has quite a large amount of complexity to implement. First, let's go back to our starting point, we can build a web application that displays our geolocation using the Geolocation Web API. What happens underneath the covers in the browser level to actually get your geolocation?

We start by parsing some of the Javascript, and thus the SpiderMonkey VM. Since our application isn't performance critical, the JavaScript is actually interpreted in Interpreter.cpp. We hit the js::Invoke function to call our native function. A native function is a function built into the VM rather than another JavaScript function in the same script. By this time, the JavaScript interpreter has looked up the function and determined that to get the geolocation, it has to call a native C function in the VM. The function that's called is Navigator::GetGeolocation, which initiates a new Geolocation Object.

During the initialization phase of the Geolocation object, it attaches itself as an "observer", which is just a listener to a GeolocationServices object. The GeolocationServices object is what actually maintains all the information about our Geolocation. Everything discussed so far applies to both Firefox OS and Firefox Desktop. However, how we actually fetch our location now differs between the two platforms.

Firefox Desktop
Firefox Desktop on Mac is a little bit easier to explain. When Firefox requests for your location, it jumps to nsGeolocationRequest::Allow, which fires after you allow Firefox to use your location. Allow() then checks for a cached Geolocation. If it exists, it fires off a new event with your current Geolocation. This is an important underpinning in the browser and JavaScript in general - Everything is an event.

A main thread constantly checks a queue to see if an event has arrived. Once it has, it processes the event. This is called the Event Loop. Our Geolocation just creates a new event and submits it to the queue, where another thread will pick it up and process our location.

Now what happens if we don't have a cached position? Actually what happens is once we create the nsGeolocationService, Firefox uses OS X's CoreLocation service. CoreLocation is an OSX provided API to get your location. You supply CoreLocation with a callback function whenever you want to get an updated location. What Firefox does is tell CoreLocation to callback nsGeolocationService::Update, which calls nsGeoLocationService::SetCachedPosition and sets our cached location. Thus, Firefox actually always has your location due to CoreLocation. When Firefox requests your location, it just reads the cached location which is constantly being updated by OS X's CoreLocation. If you deny your location to a website, Firefox just returns an error and the website doesn't get your address, but internally, (I think) the OS X and Firefox have your location ready to reply.

Firefox OS
Firefox OS has mostly the same logic as Firefox Desktop except there is one big difference. Apps in Firefox OS, like apps on Desktop, are different processes, but core functionality such as getting your Geolocation belong to the core B2G process. Different apps talk to the core B2G process to request your Geolocation. Each app has it's own event queue that's being run.

When an app requests your location, it creates a new event requesting your Geolocation. Through IPC, the event gets pushed onto the main B2G's event loop queue. When the main B2G process handles your Geolocation request, it submits the position event back through IPC to your app. The app then gets a Geolocation update, which pushes another event to update whatever part of the app needed the location.

Finally, there is some part of the OS that has to actually call the GPS driver to get the location. I haven't found that part yet, but I'm on the hunt!