Mozilla

WebAPI Articles

Sort by:

View:

  1. WebAPIs – Firefox OS for developers: the platform HTML5 deserves

    In the fifth video of our “Firefox OS – the platform HTML5 deserves” series (part one, part two, part three and part four have already been published) we talk about how Firefox OS extends the capabilities of the Web by adding new APIs, called WebAPIs to the existing stack of technologies.

    Firefox OS - be the future

    Check out the video featuring Chris Heilmann (@codepo8) from Mozilla and Daniel Appelquist (@torgo) from Telefónica Digital/ W3C talking about the need for device APIs on the Web, how some of the existing APIs can be used and how the work on Firefox OS benefits the Web as a whole. You can watch the video here.

    The WebAPI work is important as it allows apps built with Web technologies to access the hardware. For the work on Firefox OS (which is fully built in HTML5 itself), we very much needed to know the status of the phone, how much battery is left, what the connectivity is like, the screen orientation and many more features. Thus we defined access to the various parts of the hardware as JavaScript APIs and sent these as proposals to the standard bodies.

    If you want to learn more about these new APIs the canonical place to go to is the WebAPI Wiki Page where you can find an up-to-date list of all the APIs, their implementation status in the different Firefox platforms, the standards bodies involved and where to file bugs for them. You can also click through to bugzilla to see demos of the APIs in action. We’ve blogged here about WebAPIs in detail before: Using WebAPIs to make the web layer more capable and you can see a lot of information and demos in that post.

    In general, all the APIs follow a simple model: you ask for access and you define a success and failure handler. You also get methods to ask for various properties in detail and some have Boolean values available to you. This makes it very easy to test for the support of a certain API before trying to access it.

    Not all APIs can be available on the open Web as we can not trust every server out there. That is why the APIs come in three flavours: regular, privileged and certified. Regular APIs can be used in any app, regardless of its location (you can self-host these apps). Examples for that are the geolocation or the battery API. Privileged and Certified APIs both need your app to have a content security policy and be hosted on Mozilla servers. That way we can give you access to the hardware but minimise the potential of abuse and malware at the same time.

    Take a look at the exhaustive list of blog posts here dealing with WebAPIs for more reading and we’ll be back with the next video covering WebActivities soon.

  2. The Proximity API

    Something that’s very nice with bringing the web to the mobile platform with Firefox OS and WebAPIs is the ability to connect more into the physical world. One part there is the Proximity API, which is also a W3C Working Draft – Proximity Events.

    What it is

    The API is about detecting how close the device is to any other physical object, by accessing the proximity sensor. There are two ways of working with proximity

    • Device proximity
    • User proximity

    From the spec:

    The DeviceProximityEvent interface provides web developers information about the distance between the hosting device and a nearby object.

    The UserProximityEvent interface provides web developers a user-agent- and platform-specific approximation that the hosting device has sensed a nearby object.

    Using it

    Working with proximity is as easy as adding a couple of event handlers, depending on what you want to do. The deviceproximity event works with the metric system, and you will get back the distance in centimeters (these examples take for granted that you have an existing proximityDisplay element to present the values in). You are also able to check the minimum and maximum distance the sensor in your device supports.

    window.ondeviceproximity = function (event) {
        // Check proximity, in centimeters
        var prox = "<strong>Proximity: </strong>" + event.value + " cm<br>";
            prox += "<strong>Min value supported: </strong>" + event.min + " cm<br>";
            prox += "<strong>Max value supported: </strong>" + event.max + " cm";
        proximityDisplay.innerHTML = prox;
    };

    It should be noted that the values sensors currently can return a quite small value, ranging from 0 up to 5 or 10 centimeters. In general, I believe the use case has been to detect if the user is holding the device up to the ear or not, but my personal opinion is that this could provide to be even more exciting if it supported, say, up to a meter!

    With userproximity, the value you get back is a near property on the event object, which is a boolean returning whether the user is near to the sensor or not.

    window.onuserproximity = function (event) {
        // Check user proximity
        var userProx = "<strong>User proximity - near: </strong>" + event.near + "<br>";
        userProximityDisplay.innerHTML = userProx;
    };

    I’ve also added device and proximity code and testing to the Firefox OS Boilerplate App so feel free to get the latest code there and play around with it.

    Web browser support

    The Proximity API is currently supported in:

    Conclusion

    Working with proximity is yet another example of crossing the gap between software and real physical context, and showing just how powerful the web can be. We hope to see you creating many interesting things based on it!

  3. Ambient Light Events and JavaScript detection

    I think that one of the most interesting things with all WebAPIs we’re working on, is to interact directly with the hardware through JavaScript, but also, as an extension to that, with the environment around us. Enter Ambient Light Events.

    The idea with an API for ambient light is to be able to detect the light level around the device – especially since there’s a vast difference between being outside in sunlight and sitting in a dim living room – and adapt the user experience based on that.

    One use case could be to change the CSS file/values for the page, offering a nicer reading experience under low light conditions, reducing the strong white of a background, and then something with more/better contrast for bright ambient light. Another could be to play certain music depending on the light available.

    Accessing device light

    Working with ambient light is quite simple. What you need to do is apply a listener for a devicelight event, and then read out the brightness value.

    It comes returned in the lux unity. The lux value ranges between low and high values, but a good point of reference is that dim values are under 30 lux, whereas really bright ones are 10,000 and over.

    window.addEventListener("devicelight", function (event) {
        // Read out the lux value
        var lux = event.value;
        console.log(lux);});

    Web browser support

    Ambient Light Events are currently supported in Firefox on Android, meaning both mobile phones and tablets, and it’s also supported in Firefox OS. On Android devices (the ones I’ve tested), the sensor is located just right to the camera facing the user.

    It is also a W3C Working Draft, following the type of other similar events, such as devicemotion, so we hope to see more implementations of this soon!

    Demo

    Dmitry Dragilev and Tim Wright recently wrote a blog post about the Ambient Light API, with this nice demo video:

    You can also access the demo example directly, and if you test in low light conditions, you’ll get a little music. Remember to try it out on a supported device/web browser.

  4. Introducing navigator.mozPay() For Web Payments

    What’s wrong with payments on the web? Any website can already host a shopping cart and take credit card payments or something similar. The freedom of today’s web supports many business models. Here’s what’s wrong:

    • Users cannot choose how to pay; they have to select from one of the pre-defined options.
    • In most cases, the user has to type in an actual credit card number on each site. This is like giving someone the keys to your expensive car, letting them drive it around the block in a potentially dangerous neighborhood (the web) and saying please don’t get carjacked!
    • Merchants typically have to manage all this on their own: payment processor setup, costly processing fees, and possibly even PCI compliance.

    There are services to mitigate a lot of these complications such as PayPal, Stripe, and others but they aren’t integrated into web devices very well. Mozilla wants to introduce a common web API to make payments easy and secure on web devices yet still as flexible as the checkout button for merchants.

    As a first step, Mozilla will introduce navigator.mozPay() in Firefox OS so that web apps can accept payments.

    How Does It Work?

    navigator.mozPay() is a JavaScript API inspired by google.payments.inapp.buy() but modified for things like multiple payment providers and carrier billing. When a web app invokes navigator.mozPay() in Firefox OS, the device shows a secure window with a concise UI. After authenticating, the user can easily charge the payment to her mobile carrier bill or credit card. When completed, the app delivers the product. Repeat purchases are quick and easy.

    In an earlier article I talked about purchasing an app and receiving a receipt. navigator.mozPay() is different in that there is no concept of what product is purchased, it’s just an API to facilitate a payment for a digital good or service, whatever that may be.

    The payment starts and finishes in the client but further processing and notifications happen server side. This article briefly explains how it all fits together. For complete, in-depth documentation read the Firefox Marketplace guide to in-app payments.

    Integrating With A Payment Provider

    Multiple providers will facilitate payments behind the scenes of navigator.mozPay(). For example, the Firefox Marketplace will be able to facilitate payments.

    As a developer you will essentially grant permission to each provider that you would like to sell through. In the current design of the API, you do this by asking each provider for an Application Key and an Application Secret so that you can digitally sign payment requests. A signed request prevents unauthorized parties from selling your products and prevents users from tampering with the price, etc.

    Initiating A Payment

    When the user clicks a Buy button in your web app, you create a JSON Web Token (JWT) with your Application Secret. If you have agreements with multiple providers, you would create a JWT for each provider. Starting a payment looks roughly like this:

    document.querySelector('button.buy').onclick = function() {
        navigator.mozPay([mozillaJWT, otherJWT, ...]);
    };

    Defining A Product

    A JWT is a signed JSON object that defines details like the product name and price. Here is an example with some attributes removed for brevity:

    {
      "iss": APPLICATION_KEY,
      "aud": "marketplace.firefox.com",
      ...
      "request": {
        "name": "Magical Unicorn",
        "pricePoint": 1,
        "postbackURL": "https://yourapp.com/postback",
        "chargebackURL": "https://yourapp.com/chargeback"
      }
    }

    You define prices as price points so that the payment provider can handle currency conversions for you in each region. In this example, pricePoint 1 might be €0.89 or $0.99, etc. Micropayments in small amounts will be supported. Consult the navigator.mozPay() spec for details on how to construct a payment request JWT.

    Completing a Payment

    To complete the payment, you need to wait for the provider to POST a result to your server’s postbackURL (on success) or chargebackURL (on failure). A more complete example of requesting a purchase in JavaScript would involve waiting for the postback to arrive, like this:

    var request = navigator.mozPay([mozillaJWT, otherJWT]);
    request.onsuccess = function() {
      // The payment window has closed.
      whenPaymentResultReceived(function() {
        console.log('Success! User has purchased a Magical Unicorn.');
      });
    };

    To implement whenPaymentResultReceived() you might open a web socket to your server, wait for the payment result, and verify the incoming JWT signature. The navigator.mozPay() spec has details on how postback and chargeback notifications work.

    Try It Out

    Payments aren’t fully live yet in the Firefox Marketplace but you can simulate a payment to test out your code. Log into the Firefox Marketplace Developer Hub and generate an Application Key and Application Secret for simulations. With those keys you can add a special parameter to the JWT like this:

    {
      "request": {
        "name": "Magical Unicorn",
        "pricePoint": 1,
        ...
        "simulate": {"result": "postback"}
      }
    }

    This will show a payment window on Firefox OS but it won’t charge you real money. It will let you test your client side JavaScript code and your server postback handlers to make sure everything is integrated smoothly. When you go live, just remove the simulate attribute. If you’re new to Firefox OS development, check out the Firefox OS Simulator.

    If you’re already working on a game or a web app for Firefox OS try thinking about using navigator.mozPay() to offer premium content.

    This Would Be Way Easier With A Library

    We thought so too! We built libraries for Node.JS and Python to make the server side logic for navigator.mozPay() as easy as possible. Libraries for more languages are on the way. We also are experimenting with removing the server prerequisite entirely.

    Current Status

    As you can probably tell by the prefix, navigator.mozPay() is an experimental API and might change drastically or become unprefixed without notice. It will process live payments on the first Firefox OS phones and evolve quickly from real world usage.

    Mozilla plans to work with other vendors through the W3C to reach consensus on a common API that supports web payments in the best way possible. After shipping in Firefox OS, Mozilla plans to add navigator.mozPay() to Firefox for Android and desktop Firefox.

    New Business Models

    Advertising has been the primary business model on the web for a long time but users have made it clear that they don’t want to see ads. Mozilla isn’t trying to directly disrupt the ad business but it is trying to fix serious privacy issues relating to ad networks.

    What if users explicitly paid for content instead? navigator.mozPay() enables this kind of direct payment model: if something is good on the web, you can pay for it. It already seems to be working well for existing mobile apps. Will mobile ads even generate the same revenue for content producers as they do on desktop? I don’t have answers to these questions but one thing is for certain: the web should support businesses of all kinds and payments should be a first class feature of the web.

    Is It Webby?

    Mozilla’s main goal with navigator.mozPay() is to give users and merchants choice, security, and an easy to use payments system. The details about how merchants interact with payment providers is not yet specified in the API and that is clearly a gap. The first Firefox OS phones will ship with a whitelist of allowed payment providers which is also not ideal.

    In a more webby model, all parties involved in the payment would be fully decentralized so that innovation can occur naturally and unknown payment providers could emerge. Who will be the next M-Pesa? An elegant API would support that. Building a secure decentralized payment API is an ambitious challenge; the solution would need to address these core trust issues:

    • How can customers trust that they will receive the goods after paying?
    • How would customers ensure that their payment credentials are handled securely?
    • How do merchants guarantee that they’ll get paid after delivering goods?

    As with anything related to money, there is incentive for fraud every step of the way. BitCoin is a digital currency that solves some of these trust issues with block chains and PaySwarm is a web payment protocol that solves some of these issues with decentralized assets, public keys, etc. Mozilla will be watching PaySwarm as well as other models and hopefully navigator.mozPay() can incorporate some of these concepts eventually.

  5. 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 failed\n:" + 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).

  6. Introducing Web Activities

    One of the more powerful things lately for apps on various mobile phones have been intents. Register your app for handling certain types of actions, or specify in your app what kind of support you are looking for, for the thing you are trying to do.

    This is especially important in the case of Firefox OS. No matter how good your web app is to begin with, what really takes it to the next level is interaction with other apps and activities on the device.

    This is where Web Activities come into place.

    It is basically one of the new WebAPIs we’ve been working on to make the web even more powerful as a platform, and the idea is to have a simple API to both specify intent with your activity, but also declare that your app will be able to handle actions from other apps.

    If you haven’t looked into web apps yet, by the way, the best thing is probably to read Getting started with making apps. In their simplest form, a web app is just HTML5, CSS and JavaScript, with an app manifest added.

    Getting started with Web Activities

    There are a few ways you can work with Web Activities:

    • Call an activity and get presented with apps that can handle that
    • Register your activity support for your web app in the manifest file
    • Register activity support on-the-fly
    • Attach a handler to your app for when that activity occurs

    Calling an activity

    Let’s say you have a button in your app, and you want to be able to get a picture – either from the Gallery, Camera or any other app in Firefox OS that supports that activity. You can then call the pick activity, like this:

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

    In this example, we specify the name pick and the data to be PNG or JPEG images. You will then be presented with a menu of available activities in Firefox OS:

    As a user, you choose the app you want to pick an image from – or take a picture with the Camera – and once you’ve done so, the result will be posted back to the requesting app (Note: it is chosen from within the app handling the activity what, and if, something will be returned).

    Handling the response

    For most WebAPIs, including Web Activities, you will have onsuccess and onerror event handlers. In the case of an image/file you will get a blob back. You can then represent that returned image visually directly in your app:

    pick.onsuccess = function () {// Create image and set the returned blob as the src
        var img = document.createElement("img");
        img.src = window.URL.createObjectURL(this.result.blob);
     
        // Present that image in your app
        var imagePresenter = document.querySelector("#image-presenter");
        imagePresenter.appendChild(img);
    };
     
    pick.onerror = function () {// If an error occurred or the user canceled the activity
        alert("Can't view the image!");
    };

    Register your app for an activity

    As mentioned above, you can also set your app as a handler for certain activities. There are two ways to do that:

    Through the manifest file – declaration registration

    {
        "name": "My App",
        "description": "Doing stuff",
        "activities": {
           "view": {
                "filters": {
                    "type": "url",
                    "url": {
                        "required": true, 
                        "regexp":"/^https?:/"
                    }
                }
            }
        }
    }

    Register an activity handler – dynamic registration

    var register = navigator.mozRegisterActivityHandler({
        name: "view", 
        disposition: "inline", 
        filters: {
            type: "image/png"
        }});
     
    

register.onerror = function () {
        console.log("Failed to register activity");}

    and then handle the activity:

    navigator.mozSetMessageHandler("activity", function (a) {var img = getImageObject();

        img.src = a.source.url;/*
          Call a.postResult() or a.postError() if 

          the activity should return a value

        */
    });

    Available activities

    The available activities to choose from at this time are:

    • configure
    • costcontrol/balance
    • costcontrol/data_usage
    • costcontrol/telephony
    • dial
    • new (e.g. type: “websms/sms”, “webcontacts/contact”)
    • open
    • pick (e.g. type: “image/png”)
    • record
    • save-bookmark
    • share
    • test
    • view

    A few examples:

    Dial

    var call = new MozActivity({
        name: "dial",
        data: {
            number: "+46777888999"
        }
    });

    New SMS

    var sms = new MozActivity({
        name: "new",
        data: {
            type: "websms/sms",
            number: "+46777888999"
        }
    });

    New Contact

    var newContact = new MozActivity({
        name: "new",
        data: {
            type: "webcontacts/contact",
            params: { // Will possibly move to be direct properties under "data"
                giveName: "Robert",
                familyName: "Nyman",
                tel: "+44789",
                email: "robert@mozilla.com",
                address: "Sweden",
                note: "This is a note",
                company: "Mozilla"
            }
        }
    });

    View URL

    var openURL = new MozActivity({
        name: "view",
        data: {
            type: "url", // Possibly text/html in future versions
            url: "http://robertnyman.com"
        }
    });

    Save bookmark

    var savingBookmark = new MozActivity({
        name: "save-bookmark",
        data: {
            type: "url",
            url: "http://robertnyman.com",
            name: "Robert's talk",
            icon: "http://robertnyman.com/favicon.png"}
    });

    Try it out now!

    You can try this out right now, by putting together a web app and calling web activities. You can then test it in the Firefox OS Simulator!

    Work in progress

    Web Activities are a work in progress, and the activity names, data types etc are subject to change. However, currently most of the above works right now (with the exception for mozRegisterActivityHandler and mozSetMessageHandler, that haven’t been implemented yet).

    I hope you share my excitement with all the possibilities Web Activities are offering us, and can probably think of a number of use cases, making your app much more powerful through interaction with other apps!

  7. ArchiveAPI – read out archive file contents + Introducing Bleeding Edge

    Working with files on the web has been a challenge for a long time, and when things like various File APIs have surfaced, it has made me really happy! Now on to the latest edition: ArchiveAPI, giving the ability to work with archive files.

    Introducing Bleeding Edge

    Before I start talking about the ArchiveAPI, I wanted to introduce the new Bleeding Edge category here on Mozilla Hacks. What this means is that we cover technologies/features/APIs that haven’t been released in an official version of Firefox, or any other web browser, yet. It covers things that, in most cases, have their first initial implementation in Firefox Nightly or Firefox Aurora.

    The goal is to have these features shipped, but given feedback from you, dear developers, or any other findings during this phase might result in changes to them before they are released.

    So, feel more than welcome to try them out! Either you have a headstart on knowing what’s coming, or you have the possibility of affecting the future of features for developers on the web. Win-win! :-)

    What it is

    As part of our WebAPI initiative at Mozilla to make the web an even more powerful platform, I was lucky to talk to Andrea Marchesini, the Lead Developer of the ArchiveAPI. Basically, it allows you to read the content of archive files, e.g. ZIP files, directly in web browsers.

    Basically, we have an ArchiveReader object and when it successfully manages to read the contents of an archive file, we can iterate over them, read out file data, show previews of each file’s content etc.

    var archiveFile = new ArchiveReader(archiveFileReference),
        fileNames = archiveFile.getFilenames();

    When you trigger an action/method on this file, like getFilenames, you will have two handlers: onsuccess and onerror. Like this:

    fileNames.onerror = function () {
        console.log("Error reading filenames");
    };
     
    fileNames.onsuccess = function (request) {
        // Get list of files in the archive
        var result = this.result;
     
        // Iterate over those files
        for (var i=0, l=result.length; i&lt;l; i++) {
            file = archiveFile.getFile(result[i]);
     
            file.onerror = function () {
                console.log("Error accessing file");
            };
     
            file.onsuccess = function () {
                // Read out data for that file, such as name, type and size
                var currentFile = this.result;
                console.log(currentFile.name);
            }
        }
    }

    Demo

    I’ve put together an ArchiveAPI demo where you can upload an archive file and for any of the image or text files within that archive, it will directly generate a preview in the web page. The code is available on GitHub, as part of our mozhacks GitHub repositiory.

    Note: currently this demo only works in Firefox Aurora and Firefox Nightly.

    I’ve also put together a screencast of this demo at YouTube:

    (If you’ve opted in to HTML5 video on YouTube you will get that, otherwise it will fallback to Flash)

    Feedback

    I hope you find this interesting, and one more step forward for the web as a platform! Please let us know what you think in a comment here.

    Additionally, there’s a poll/questionnaire you can take with regards to the asynchronous nature of ArchiveAPI. It’s available in Feedback on potential ArchiveReader APIs.

  8. WebRTC efforts underway at Mozilla!

    Last week, a small team from Mozilla attended IETF 83 in Paris, and we showed an early demo of a simple video call between two BrowserID-authenticated parties in a special build of Firefox with WebRTC support. It is still very early days for WebRTC integration in Firefox, but we’re really excited to show you something that works!

    At Mozilla Labs, we’ve been experimenting with integrating social features in the browser, and it seemed like a cool idea to combine this with WebRTC to establish a video call between two users who are signed in using BrowserID (now called Persona). The SocialAPI add-on, once installed, provides a sidebar where web content from the social service provider is rendered. In our demo social service, we show a “buddy list” of people who are currently signed in using Persona.

    The video chat page that is served when the user initiates a video chat uses a custom API intended to simulate the getUserMedia and PeerConnection APIs currently being standardized at the W3C. A <canvas> is used to render both the remote and local videos, though it is also possible to render them in a <video>. We’re working very quickly to implement the standard APIs, and you can follow our progress on the tracker bug.

    A lot of folks burned the midnight oil to get this demo ready before the IETF event, and special thanks are due to Eric Rescorla, Michael Hanson, Suhas Nandakumar, Enda Mannion, Ethan Hugg, the folks behind Spacegoo, and Randell Jesup, in addition to the whole media team here at Mozilla.

    Current development is being done on a branch of mozilla-central called alder. It is going to be an exciting few months ahead as we work towards bringing WebRTC to Firefox. There is a lot of work to do, and if you are interested in contributing, please reach out! Maire Reavy, our product person and project lead for WebRTC would be happy to help you find ways to contribute. Many of us are also usually available in IRC at #media, and we have a mailing list.

    Transcript of screencast:

    Hi, I’m Anant from Mozilla Labs and I’m here at IETF where we are demonstrating a simple video call between two BrowserID-authenticated parties, using the new WebRTC APIs that we are working on.

    This is a special build of Firefox with WebRTC support, and also has the experimental SocialAPI add-on from Mozilla Labs installed. On the right hand side you can see web content served by demosocialservice.org, to which I will sign with BrowserID. Once I’m signed in, I can see all my online friends on the sidebar. I see my friend Enda is currently online, and so I’m going to click the video chat button to initiate a call.

    Here, I see a very early prototype of a video call window served up by our demo social service. Now, I can click the Start Call button to let Enda know that I want to speak with him. Once he accepts the call, a video stream is established between the two parties as you can see. So, that was a video call built entirely using JavaScript and HTML!

    You can check out the source code for this demo, as well as learn how to contribute to the ongoing WebRTC efforts at Mozilla in this blog post. Thanks for watching!

  9. Taking pictures with the Camera API – part of WebAPI

    Through the Camera API, part of WebAPI, it becomes possible to take pictures with your device’s camera and upload them into the current web page. This is achieved through an input element with type="file" and an accept attribute to declare that it accepts images.

    The HTML looks like this:

    <input type="file" id="take-picture" accept="image/*">

    When the users choose to activate this HTML element, they are presented with an option from where they want to choose a file, where the device’s camera is one of the options. If the camera is selected, it goes into picture taking mode.

    After the picture has been taken, the user is presented with a choice to accept or discard it. If accepted, it gets sent to the <input type="file"> element and its onchange event is triggered.

    Get a reference to the taken picture

    With the help of the File API you can then access the taken picture/chosen file:

    var takePicture = document.querySelector("#take-picture");
    takePicture.onchange = function (event) {
        // Get a reference to the taken picture or chosen file
        var files = event.target.files,
            file;
        if (files && files.length > 0) {
            file = files[0];
        }
    };

    Presenting the taken picture in the web page

    Once we have a reference to the taken picture (i.e. file) we can then use createObjectURL to create a URL referencing the picture and setting it to the src of an image:

    // Image reference
    var showPicture = document.querySelector("#show-picture");
     
    // Get window.URL object
    var URL = window.URL || window.webkitURL;
     
    // Create ObjectURL
    var imgURL = URL.createObjectURL(file);
     
    // Set img src to ObjectURL
    showPicture.src = imgURL;
     
    // For performance reasons, revoke used ObjectURLs
    URL.revokeObjectURL(imgURL);

    If createObjectURL isn’t supported, an alternative is to fallback to FileReader:

    // Fallback if createObjectURL is not supported
    var fileReader = new FileReader();
    fileReader.onload = function (event) {
        showPicture.src = event.target.result;
    };
    fileReader.readAsDataURL(file);

    Complete example demo and code

    If you want a complete working example page, I’ve created a Camera API demo. Here is the code for the HTML page and its accompanying JavaScript file:

    HTML page

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>Camera API</title>
            <link rel="stylesheet" href="css/base.css" type="text/css" media="screen">
        </head>
     
        <body>
     
            <div class="container">
                <h1>Camera API</h1>
     
                <section class="main-content">
                    <p>A demo of the Camera API, currently implemented in Firefox and Google Chrome on Android. Choose to take a picture with your device's camera and a preview will be shown through createObjectURL or a FileReader object (choosing local files supported too).</p>
     
                    <p>
                        <input type="file" id="take-picture" accept="image/*">
                    </p>
     
                    <h2>Preview:</h2>
                    <p>
                        <img src="about:blank" alt="" id="show-picture">
                    </p>
     
                    <p id="error"></p>
     
                </section>
     
                <p class="footer">All the code is available in the <a href="https://github.com/robnyman/robnyman.github.com/tree/master/camera-api">Camera API repository on GitHub</a>.</p>
            </div>
     
     
            <script src="js/base.js"></script>
     
     
        </body>
    </html>

    JavaScript file

    (function () {
        var takePicture = document.querySelector("#take-picture"),
            showPicture = document.querySelector("#show-picture");
     
        if (takePicture &amp;&amp; showPicture) {
            // Set events
            takePicture.onchange = function (event) {
                // Get a reference to the taken picture or chosen file
                var files = event.target.files,
                    file;
                if (files && files.length > 0) {
                    file = files[0];
                    try {
                        // Get window.URL object
                        var URL = window.URL || window.webkitURL;
     
                        // Create ObjectURL
                        var imgURL = URL.createObjectURL(file);
     
                        // Set img src to ObjectURL
                        showPicture.src = imgURL;
     
                        // Revoke ObjectURL
                        URL.revokeObjectURL(imgURL);
                    }
                    catch (e) {
                        try {
                            // Fallback if createObjectURL is not supported
                            var fileReader = new FileReader();
                            fileReader.onload = function (event) {
                                showPicture.src = event.target.result;
                            };
                            fileReader.readAsDataURL(file);
                        }
                        catch (e) {
                            //
                            var error = document.querySelector("#error");
                            if (error) {
                                error.innerHTML = "Neither createObjectURL or FileReader are supported";
                            }
                        }
                    }
                }
            };
        }
    })();

    Web browser support

    • Camera API is currently supported in Firefox and Google Chrome on Android devices.
    • createObjectURL is supported in Firefox, Google Chrome and Internet Explorer 10+.
    • FileReader is supported in Firefox, Google Chrome, Internet Explorer 10+ and Opera 11.6+.

    The future

    With WebRTC – which is support for real time, audio, video & data communications between two browsers – and a navigator.getUserMedia approach we will see much more of this in the near future, in a number of the major web browsers. For more information, please see our Web Platform Roadmap for Firefox.

    But for now, you can enjoy taking/capturing pictures!