Using WebAPIs to make the web layer more capable

Part of making both Firefox OS and the web as a platform a stronger layer and alternative for developers, we are working on a number of WebAPIs. I’d like to introduce you them here!

Many things covered in this blog post are also available in a talk I’ve given on this topic.

Standardization

When you talk about new technology, ideas and solutions, people have a tendency to be wary. They might see it as the Not Invented Here syndrome, but that is not our intent (as we’ve written here before, and as mentioned by our CTO, Brendan Eich).

Our intention is that everything we do is, or will be, standardized. Developed in the open.

This blog post focuses on various WebAPIs, their security level and how to use them. In a later post, we will follow up specifically on standardization and progress in that area.

Types of APIs

There are basically three types of WebAPIs:

Regular APIs
APIs available from any app, hosted or packaged.
Privileged APIs
Only available in privileged apps. Privileged apps are apps that are:

Certified APIs
Certified APIs are only available to system itself (Mozilla in the case of Firefox OS), meaning they are so sensitive and need to be strictly controlled.

Regular APIs

The complete list of regular APIs is:

  • Vibration API
  • Screen Orientation
  • Geolocation API
  • Mouse Lock API
  • Open WebApps
  • Network Information API
  • Battery Status API
  • Alarm API
  • Web Activities
  • Push Notifications API
  • WebFM API
  • WebPayment
  • IndexedDB
  • Ambient light sensor
  • Proximity sensor
  • Notification
  • FMRadio

Here’s how to use a number of them:

Battery Status API

This API is about detecting the current battery level of the computer/device, how long battery life there’s left and whether it’s being charged or not. Works in all three of desktop, Android and Firefox OS.

var battery = navigator.battery;

if (battery) {

    var batteryLevel = Math.round(battery.level * 100) + "%",

        charging = (battery.charging)? "" : "not ",

        chargingTime = parseInt(battery.chargingTime / 60, 10),

        dischargingTime = parseInt(battery.dischargingTime / 60, 10);

        // Set events

        battery.addEventListener("levelchange", showStatus);
        battery.addEventListener("chargingchange", showStatus);
        battery.addEventListener("chargingtimechange", showStatus);
        battery.addEventListener("dischargingtimechange", showStatus);

}

Vibration API

Making the device vibrate, either once or with a certain pattern.

// Vibrate for one second

navigator.vibrate(1000);

// Vibration pattern [vibrationTime, pause,…]

navigator.vibrate([200, 100, 200, 100]);

// Vibrate for 5 seconds

navigator.vibrate(5000);

// Turn off vibration

navigator.vibrate(0);

Screen Orientation

Gives you as a developer the chance to lock the orientation, or to specify what you want the primary orientation experience to be.

/*
    Possible values:
        "landscape",
        "portrait"
        "landscape-primary"
        "landscape-secondary"
        "portrait-primary"
        "portrait-secondary"

*/
var portraitLock = screen.mozLockOrientation("portrait");
if (portraitLock) {
    console.log("Orientation locked to portrait");
}

Geolocation API

Finding out where the user is at the moment – approved by the user to share this.

navigator.geolocation.getCurrentPosition(function (position) {
    /*
        Getting latitude and longitude:
            position.coords.latitude
            position.coords.longitude
};

Mouse Lock API

Locking down the mouse movements and controlling the experience yourself. Especially good when you don’t want the mouse pointer/interaction to end when it hits the end of the web browser window, but rather to continue to scroll – like doing complete 360 degrees spin of an environment or similar.

var docElm = document.documentElement;

// Requesting Pointer Lock

docElm.requestPointerLock = elem.requestPointerLock ||
                            elem.mozRequestPointerLock ||
                            elem.webkitRequestPointerLock;

docElm.requestPointerLock();

document.addEventListener("mousemove", function(e) {
    var movementX = e.movementX       ||
                    e.mozMovementX    ||
                    e.webkitMovementX ||
                    0,
        movementY = e.movementY       ||
                    e.mozMovementY    ||
                    e.webkitMovementY ||
                    0;

    // Get the mouse movement delta values
    console.log("movementX=" + movementX, "movementY=" + movementY);  
}
);

Open WebApps

In general, an APIs needed to install and handle Open Web Apps.

var installApp = navigator.mozApps.install(manifestURL);

// Successful install
installApp.onsuccess = function(data) {
    console.log("Success, app installed!");
};

// Install failed
installApp.onerror = function() {
    console.log("Install failedn:" + installApp.error.name);
};

Network Information API

Used to get information about network connectivity.

var connection = window.navigator.mozConnection,
    online = connection.bandwidth,
    metered = connection.metered;

// online can return:
    0 when offline
    Infinity when the bandwidth isn't known
    Estimation of MB/s

// metered implies if the connection is being metered,
   meaning limited in some way from the ISP

Alarm API

Making it possible to set alarms.

request = navigator.mozAlarms.add(
    new Date("May 15, 2012 16:20:00"),
    "honorTimezone",
    {
        mydata: "my event"
    }
);

Web Activities

Through Web Activities you can specify intents on what kind of action you want to do, or that your app can handle.

var pick = new MozActivity({
     name: "pick",
     data: {
         type: ["image/png", "image/jpg", "image/jpeg"]
     
}
 });

pick.onsuccess = function () {

    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(this.result.blob);
    document.body.appendChild(img);
};

I’ve covered Web Activities in more detail in another blog post here.

Push Notifications API

A way for web sites to send messages to suers when aren’t on their web site. API is in a draft, not implemented yet. More can be read in the PushAPI documentation.

function getPushURL() {
    var push = navigator.push ||
                navigator.mozPush ||
                navigator.webkitPush;

    // Ask the user to allow notifications
    var request = push.requestURL(watoken, PbK);

    request.onsuccess = function () {
        var url = request.result.url;
        console.log('Push URL: ' + url);
    };
}

WebFM API

Implementing a FM Radio in the web layer.

var fmRadio = navigator.fm || navigator.mozFMRadio || navigator.mozFM;
fmRadio.frequency = 106.7;

WebPayment

Used to enable in-app payments, through JSON Web Token (JWT).

var request = navigator.mozPay(JWTs);
request.onsuccess = function () {
    // Money!
};

IndexedDB

Structured client-side storage with high performance search support. Covered in detail in Using IndexedDB and Storing images and files in IndexedDB.

// Create/open database
var request = indexedDB.open("elephantFiles", 1),
     createObjectStore = function (dataBase) {
        console.log("Creating objectStore")
        dataBase.createObjectStore("elephants");
};

request.onsuccess = function (event) {
    console.log("Success creating/accessing IndexedDB database");
    db = request.result;

    db.onerror = function (event) {
        console.log("Error creating/accessing IndexedDB database");
    };
}

// Needed for creating database/upgrading to a new version
request.onupgradeneeded = function (event) {
    createObjectStore(event.target.result);
};

Ambient light sensor

Detecting the level of ambient light, to be able to serve different versions depending on the environment the user currently is in.

window.addEventListener("devicelight", function (event) {

    /* The level of the ambient light in lux

       A lux value for "dim" typically begin below 50,
       and a value for "bright" begin above 10000
    */
    console.log(event.value);

});

window.addEventListener("lightlevel", function (event) {
    // Possible values: "normal", "bright", "dim"
    console.log(event.value);

});

Proximity sensor

Getting an indication of how close the device is to another object.

window.addEventListener("deviceproximity", function (event) {

    // Current device proximity, in centimeters

    console.log(event.value);



    // The maximum sensing distance the sensor is 

    // able to report, in centimeters

    console.log(event.max);



    // The minimum sensing distance the sensor is 

    // able to report, in centimeters

    console.log(event.min);
});

Notification

Being able to show notifications to the user.

var notification = navigator.mozNotification;

notification.createNotification(
    "See this",
    "This is a notification"
);
// You could send an optional third parameter,
// which would be the URL to an icon

Privileged APIs

These APIs can only be used in a privileged app.

The complete list of privileged APIs is:

  • Device Storage API
  • Browser API
  • TCP Socket API
  • Contacts API
  • systemXHR

Device Storage API

Accessing files stored on the device.

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;
    }

    // Show file
    console.log(file.name);
};

Browser API

Implementing your own web browser, completely with web technologies. Described more in BrowserAPI.

iframe.addEventListener("mozbrowserlocationchange", function(e) {
    console.log(e.detail);
});

iframe.addEventListener("mozbrowsersecuritychange", function(e) {
    // "secure", "insecure", or "broken".  "broken" indicates mixed content.
    console.log(e.detail.state);
});

iframe.addEventListener("mozbrowsercontextmenu", function(e) {
    // Show context menu
});

TCP Socket API

A low-level TCP socket API, that will also include SSL support.

var TCPSocket = navigator.mozTCPSocket.open(
    host,
    port,
    {
        useSSL: crypto,
        binaryType: "arraybuffer"
    }
);

Contacts API

Accessing contacts on the device – adding, reading or modifying.

var contact = new mozContact();

contact.init({name: "Tom"});



var request = navigator.mozContacts.save(contact);

request.onsuccess = function() {
    console.log("Success");

};



request.onerror = function() {
    console.log("Error")

};

systemXHR

Making it possible to allow cross-domain XMLHTTPRequests. Specify in the manifest file in the permissions part that you will want to access it – "systemXHR":{} – and then just do the request.

var xhr = new XMLHttpRequest();
xhr.open("GET", anyURL, true);

Certified APIs

The certified APIs are only available to the system itself/pre-installed apps. In the fcase of Firefox OS, this means only Mozilla.

The complete list of certified APIs is:

  • WebTelephony
  • WebSMS
  • Idle API
  • Settings API
  • Power Management API
  • Mobile Connection API
  • WiFi Information API
  • WebBluetooth
  • Permissions API
  • Network Stats API
  • Camera API
  • Time/Clock API
  • Attention screen
  • Voicemail

I’ll list a few of them here, in case you are interested in testing or contributing to Gaia, the UI of Firefox OS.

WebTelephony

For placing, receiving and dealing with calls.

// 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();

WebSMS

For sending and receiving SMS messages.

// SMS object
var sms = navigator.mozSMS;

// Send a message
sms.send("123456789", "Hello world!");

// Receive a message
sms.onreceived = function (event) {
    // Read message
    console.log(event.message);
};

Permissions

To be able to access certain APIs, in an Open Web App context, you need to specify permissions for the APIs you want to access in the manifest file.

"permissions": {
    "contacts": {
        "description": "Required for autocompletion in the share screen",
        "access": "readcreate"
    },
    "alarms": {
        "description": "Required to schedule notifications"
    }

}

For all APIs that are considered privileged or certified, this applies.

For regular APIs, only geolocation and notification are affected (and for geolocation, in a regular web browser context, the user will be presented with a dialog to approve/decline).

Additionally, the Camera API is restricted as a certified API at this time, but the long-term goal is to make it available to all apps. At the moment, if you want to access the camera, do it through Web Activities.

Please take a look at the list of all APIs requiring permissions.

Platform support

As I’m sure you understand, a number of the WebAPIs are going through a process filled with progress, iterations and improvements. Some of the APIs above will work as described and intended, while others might not at this time.

To be able to follow the current implementation state, please look at the list of APIs planned for the initial release of Firefox OS.

The three columns imply:

  • D = Desktop support in Firefox
  • A = Android support in Firefox
  • B = Firefox OS support
  • Green = Implemented and enabled
  • Orange = Implemented, but needs to explicitly be turned on
  • Red = Not implemented
  • Blue = Only available as a Certified API
  • Grey = Not planned for this platform

APIs planned for the future

While not being worked on at the moment, I’d like to list APIs that are planned for the future. To show you our intent, and things we want to implement and support, and also to show in which direction we are moving.

  • Resource lock API
  • UDP Datagram Socket API
  • Peer to Peer API
  • WebNFC
  • WebUSB
  • HTTP-cache API
  • Calendar API
  • Spellcheck API
  • LogAPI
  • Keyboard/IME API
  • WebRTC
  • FileHandle API
  • Sync API

Testing out these new APIs

Feel free to just copy and paste code from this blog post to test the API(s) that you are interested in. I’ve also implemented support for some of them in the Firefox OS Boilerplate App, available in the webapp.js file (and I plan to add more in the future).

About Robert Nyman [Editor emeritus]

Technical Evangelist & Editor of Mozilla Hacks. Gives talks & blogs about HTML5, JavaScript & the Open Web. Robert is a strong believer in HTML5 and the Open Web and has been working since 1999 with Front End development for the web - in Sweden and in New York City. He regularly also blogs at http://robertnyman.com and loves to travel and meet people.

More articles by Robert Nyman [Editor emeritus]…


16 comments

  1. Joshua Ols

    So if I’m understanding this correctly, we won’t be able to make custom dialers, SMS, etc apps since the needed APIs are for certified apps only? I understand that those need to be protected so that you can’t have apps that secretly call premium SMS/etc. Shall I assume you weighed the risks, and just decided there is too much potential for malicious exploitation?

    February 7th, 2013 at 09:34

    1. Marcelo

      That’s right.
      To avoid the risks of letting anyone to make calls or SMS, Mozilla only let their own apps to use those resources.
      But you can help Mozilla to enhance the SMS app, or the dialer. It’s Open Source and anyone can suggest a patch.

      February 7th, 2013 at 10:09

    2. Robert Nyman [Editor]

      Thanks for asking!
      As Marcelo said, that’s the current security state of those APIs. But things might change over time, and there could potentially be other ways of doing it.

      February 7th, 2013 at 13:45

  2. Ahmed Nefzaoui

    Hi Robert :) I’m sorry but.. aren’t we missing something in the battery status API ?
    chargingTime = parseInt(battery.chargingTime / 60, 10,

    like
    chargingTime = parseInt(battery.chargingTime / 60, 10),

    maybe ? :S

    Cheers :)

    February 7th, 2013 at 10:29

    1. Robert Nyman [Editor]

      Thanks! Apparently the last parentheses fell off somewhere along the way. :-)

      February 7th, 2013 at 13:42

  3. Alber

    Well, this new OS seems very promising, can’t wait for it.

    Great work on those APIs btw.

    February 7th, 2013 at 22:27

    1. Robert Nyman [Editor]

      Thanks, glad you like it!

      February 8th, 2013 at 01:35

  4. Paul Rouget

    (I think the “packaged/privileged app” is wrong)

    February 8th, 2013 at 03:34

    1. Robert Nyman [Editor]

      Updated that so it’s clearer, and with a better link.

      February 8th, 2013 at 03:47

  5. Asdrubal Heredia

    OFF TOPIC – I think.

    Hello, everybody. My name is Asdrubal.

    First. I apologize for my English. (I’m from Colombia)

    Second. What do you think about this concept of mobile? It is the “Mozilla Seabird”, and it’s a concept of 2009 from Mozilla Labs.

    An image.
    http://www.geek.com/wp-content/uploads/2010/09/seabird_2.jpg

    Here the video.
    http://www.youtube.com/watch?v=oG3tLxEQEdg

    This could be the future of Firefox Os? What do you think about it?

    February 9th, 2013 at 12:17

    1. Robert Nyman [Editor]

      Yes, I know about Mozilla Seabird. :-)
      I think it’s an interesting concept, and we’ll see how Firefox OS evolves.

      February 12th, 2013 at 03:28

  6. markg

    Great post Robert! Here is a new MDN page that covers the WebAPIs supported by the Open Web App manifest:

    https://developer.mozilla.org/en-US/docs/Apps/App_permissions

    March 3rd, 2013 at 22:22

    1. Robert Nyman [Editor]

      Excellent! I’ll weave that into the post.

      March 4th, 2013 at 03:46

  7. Batwana

    Will there be a ‘developer mode’ so we can make our own ‘certified’ apps for our own devices?

    I can understand why you don’t want downloadable apps from unknown third-parties having access to sensitive device features but surely we should be able to rejig our own devices as we see fit.

    March 13th, 2013 at 12:14

    1. Robert Nyman [Editor]

      I believe Hacking Gaia covers what you would want to do.

      March 13th, 2013 at 17:02

  8. Brock

    Mozilla corporation is taking praiseworthy steps by providing many user friendly and open source projects to the people. Firefox web browser, thunderbird mail and numerous fantastic add ons are becoming very popular. And now the upcoming operating system seems very exciting. I would be very happy if there will be a web sms send receive (sms envoyer recevoir web) application in it.

    March 13th, 2013 at 22:11

Comments are closed for this article.