The layers of FirefoxOS architecture.
Consists of a a linux kernel based on android, hardware abstraction and OEM-specific libraries.
The layout engine of Firefox, also packaged on the phone. The `B2G` project stands for `boot 2 gecko`.
The user-interface of FirefoxOS. All of the interface that you see after the phone boots lives in Gaia, including apps like system, lock and home screens.
{
"name": "Calendar",
"description": "Gaia Calendar",
"type": "certified",
"launch_path": "/index.html",
"developer": {
"name": "The Gaia Team",
"url": "https://github.com/mozilla-b2g/gaia"
},
"messages": [
{
"alarm": "/index.html"
},
{
"notification": "/index.html"
}
],
"permissions": {
"themeable": {},
"systemXHR": {},
"alarms": {},
"browser": {},
"storage": {},
"settings": {
"access": "readonly"
},
"desktop-notification": {},
"audio-channel-notification": {}
},
"locales": {
"ar": {
"name": "Calendar",
"description": "Gaia Calendar"
},
"en-US": {
"name": "Calendar",
"description": "Gaia Calendar"
},
"fr": {
"name": "Agenda",
"description": "Agenda Gaia"
},
"zh-TW": {
"name": "Calendar",
"description": "Gaia Calendar"
}
},
"default_locale": "en-US",
"icons": {
"84": "/style/icons/calendar_84.png",
"126": "/style/icons/calendar_126.png",
"142": "/style/icons/calendar_142.png",
"189": "/style/icons/calendar_189.png",
"284": "/style/icons/calendar_284.png"
},
"orientation": "default"
}
Packaged apps are the easiest way to get your app working offline.
// Service worker registration in app.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service_worker.js', {
scope: '/'
}).then(function(sw) {
// registration worked
console.log('Registration succeeded.');
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}
// Service worker in service_worker.js
this.addEventListener('fetch', function(event) {
var cachedResponse = caches.match(event.request).catch(function() {
return event.default().then(function(response) {
return caches.get('v1').then(function(cache) {
cache.put(event.request, response.clone());
return response;
});
});
}).catch(function() {
return caches.match('/caches/notFound.jpg');
});
event.respondWith(cachedResponse);
});
// Vibrate the phone for 200ms
window.navigator.vibrate(200);
// Vibrate, pause, then vibrate again.
window.navigator.vibrate([200, 100, 200]);
var battery = navigator.battery;
function updateBatteryStatus() {
console.log("Battery status: " + battery.level * 100 + " %");
if (battery.charging) {
console.log("Battery is charging");
}
}
battery.addEventListener("chargingchange", updateBatteryStatus);
battery.addEventListener("levelchange", updateBatteryStatus);
var person = new mozContact();
person.givenName = ["John"];
person.familyName = ["Doe"];
person.nickname = ["No kidding"];
var person = new mozContact(contactData);
// save the new contact
navigator.mozContacts.save(person).then(() => {
console.log('new contact saved');
});
var message = "Hi!";
var number = "1234";
navigator.mozMobileMessage.send(number, message);
// Telephony object
var tel = navigator.mozTelephony;
// Check if the phone is muted (read/write property)
console.log(tel.muted);
// Check if the speaker is enabled (read/write property)
console.log(tel.speakerEnabled);
// Place a call
var call = tel.dial("123456789");
// Events for that call
call.onstatechange = function (event) {
/*
Possible values for state:
"dialing", "ringing", "busy", "connecting", "connected",
"disconnecting", "disconnected", "incoming"
*/
console.log(event.state);
};
// Above options as direct events
call.onconnected = function () {
// Call was connected
};
call.ondisconnected = function () {
// Call was disconnected
};
// Receiving a call
tel.onincoming = function (event) {
var incomingCall = event.call;
// Get the number of the incoming call
console.log(incomingCall.number);
// Answer the call
incomingCall.answer();
};
// Disconnect a call
call.hangUp();
// Iterate over calls, and take action depending on their changed status
tel.oncallschanged = function (event) {
tel.calls.forEach(function (call) {
// Log the state of each call
console.log(call.state);
});
};
var storage = navigator.getDeviceStorage("videos"),
cursor = storage.enumerate();
cursor.onerror = function() {
console.error("Error in DeviceStorage.enumerate()", cursor.error.name);
};
cursor.onsuccess = function() {
if (!cursor.result)
return;
var file = cursor.result;
// If this isn't a video, skip it
if (file.type.substring(0, 6) !== "video/") {
cursor.continue();
return;
}
// If it isn't playable, skip it
var testplayer = document.createElement("video");
if (!testplayer.canPlayType(file.type)) {
cursor.continue();
return;
}
}
APIs that are considered safe and don't expose private info. Granted by default or with a prompt.
Lesser security requirements as privileged/certified apps and not subject to CSP. Not able to use privileged or certified APIs.
Signed apps by a marketplace. Allows access to additional APIs such as Contacts, SystemXHR, TCP socket.
Includes sensitive APIs and is only available to apps pre-installed on the phone. Gives API access to things like telephony, power and wifi management. There is a long-term goal is to harden APIs and allow access to privileged apps.
See more: https://developer.mozilla.org/en-US/Apps/Build/App_permissions
Keeping users safe.
Each app runs in its own process.
Mitigates XSS and data injection attacks.
Restricts origins of executable scripts.
https://developer.mozilla.org/en-US/Firefox_OS/Security/Security_model
Building blocks for developers.
Making FirefoxOS beautiful.
How we made this thing fast.
A process is created after app launch, and waits for the next process to take its place.
Integrated tools to help us solve performance problems.
The same tools that empower web developers.