Mozilla

Featured Articles

Sort by:

View:

  1. Launching feedback channels – let us know your ideas for Firefox Developer Tools

    One thing that is vital for us at Mozilla is to listen to developers and users, and care to your needs to make the web a better place. We’re strong believers in constructive communication and discussions, and that’s why I’m happy to announce our latest initiative! Feedback channels for developers.

    We’ve been looking into various ways to make it as easy as possible for developers to express their thoughts and opinions on a number of topics, and also for how we at Mozilla can be as transparent as possible around the projects we work on.

    Making the web a better place isn’t only about trying to figure out what’s right – it’s about listening to people, gather their thoughts and ideas and let that help us in achieving better results.

    Introducing UserVoice

    With that in mind, we’ve been evaluating third party services available as well as our own projects such as Mozilla Support and Firefox Input.

    For this specific use case and to match our requirements, we’ve decided to do it through the UserVoice service. We want to make it dead simple for you to enter ideas and vote for existing ones, both through an easy and intuitive user interface but also with requiring no account registration.

    Currently all you need to do know is enter a name and an e-mail address and you’re good to go! You will also have 10 votes dedicated to your e-mail address/account, which you can dispose as you seem fit for other ideas there.

    Naturally, if we see an abuse of this simplicity, we will have to add an element of moderation to process. We sincerely hope that won’t be needed, though, and that you will act and write respectfully.

    First project: Firefox Developer Tools

    The first project out the door that we will have a feedback channel for is the Developer Tools in Firefox. We have made great great progress with the Developer Tools over the last year – outlined in more detail in Dev Tools articles here on Hacks and the extensive documentation on MDN – but we want to hear the ideas you have to make them even better, what’s important to you, what could be a game changer and much more.

    People from the Developer Tools team will interact directly with you in this feedback channel, giving you a unique opportunity to influence and inspire us, resulting in a better product for you.

    A first test

    This try with UserVoice and feedback channels is our first attempt at this, with the ambition to be able to listen to your thoughts and ideas, and utilize that to make sure we focus on the most important areas.

    If we see that we can make a difference with this initiative and that you appreciate the direct contact and transparency, we will do our best to keep this going and to introduce channels for more topics in the future!

    Will you automatically implement the feature with the highest votes?

    Not automatically. The voting and ideas will help us see what you truly care about and interact with you around those, but we will also need to compare developing time and resources vs. the possible gain we see for a certain feature.

    It will however be of immense help for us weighing ideas, features and items in the roadmap against each other, and a helpful tool for prioritizing our work.

    Working with UserVoice

    Here are the most common things you can do at UserVoice – what they are and what they look like.

    Viewing ideas

    You can easily view a list of ideas, the number of votes they’ve gotten, current state (e.g. Started, Under Review), click the link to see comments and more.

    You also have a quick navigation to sort the listing based on what’s Hot, Top ideas, New or their current status. You can also list them based on your feedback or comments as well.

    Enter an idea

    To enter an idea, simply type the idea in the text box at the top:

    When you start typing, you will get suggestions for existing ideas that might match your topic, highlighting the word(s)in question. Please make sure to vote for existing ideas instead of creating duplicate ones.

    Search existing ideas

    In the right-hand side of the web site, you can also quickly search through existing topics and ideas, and see both matches and their current state.

    Official comment from Mozilla

    It also gives us the possibility to give you a reply to the state of the current feature. Whether it’s already in there, planned or if there’s something that’s not currently on our roadmap.

    Complement to Bugzilla and Stack Overflow

    At Mozilla, we use Bugzilla for tracking bugs and Stack Overflow for developer support. Our feedback channels at UserVoice are intended for conversations, constructive feedback and transparency around what we work on. Therefore, for reporting bugs or getting support for a product or challenge:

    Help us help you

    We really hope you will like this opportunity to have a discussion with us and be able to influence our thinking and work! If this works out well, we’d be glad to take it to other areas as well.

    So help us help you! Let’s work together to make a better web with better products for developing for it.

    Go to our Developer Tools feedback channel and get started!

  2. What Mozilla Hacks is

    With the Mozilla moniker, many people believe that the Hacks blog is only about Mozilla products or news. Therefore, I wanted to take the chance to enlighten you and also invite you to be a part of creating content here.

    What we cover here

    The goal and objective of Mozilla Hacks is to be one of the key resources for people developing for the Open Web; talking about both news and in-depth descriptions of technologies and features. This means that as long as it’s about open technologies, we want to share all that information, tips, tricks and learnings with you.

    We’re Mozilla, and for us it is key to be a web browser agnostic resource, and it’s exactly the same with MDN (Mozilla Developer Network). The content here is written by a lot of different authors, where about half of them aren’t part of or associated with Mozilla in any way – they just do good things for the Open Web, and we believe that deserves exposure, and that it will be beneficial to you.

    Allow me to also emphasize that Mozilla Hacks is not a press release channel, we work hard to make everything we cover to be informational, practical and inspirational for you.

    More information is outlined in the guidelines for Mozilla Hacks.

    Behavior

    Mozilla Hacks is a place based on mutual respect and understanding, and the way we address each other is supposed to reflect that. We expect anyone writing or commenting to use proper language and refrain from insulting other people. If you ask a question here, give feedback and more, you deserve a reply from us. And when we talk about things – even though we might disagree – we all should and are entitled to always be met with respect and a proper behavior.

    Write for us!

    We know that a lot of you reading this have great knowledge, skill sets and experiences, and we would be very happy to help and support you in sharing it with the world and fellow developers.

    We have had hundreds of people writing and collaborating in content for Hacks, and if you write two posts or more, you’ll show up in great company among all our fantastic authors!

    Talk to me

    For me personally, I’ve been running Mozilla Hacks as its Editor for about two years now, and I’m constantly on the lookout for good content that web developers writing for the Open Web, with open technologies, can learn from. I.e. topics that I’d love to read about myself.

    I would be very happy for you to reach out to me at robert [at] mozilla [dot] com or via @robertnyman on Twitter – I’m always interested in discussing the web, technology and the ideas you might have. Talk to me. :-)

  3. Box model highlighter, Web Console improvements, Firefox OS HUD + more – Firefox Developer Tools Episode 30

    Firefox 30 was just uplifted to the Aurora release channel, so let’s take a look at the most important DevTools changes in this release.

    Inspector

    One of our most requested features has been to highlight box model regions of elements on the page. We are happy to report that this feature has landed in Firefox 30. One of the great things is that the colors of the box model highlighter match the box model diagram found in the right pane of the inspector more clearly than before.

    Check out the inspector documentation to read more about the new functionality, or just see the screenshot and short video below:

    Inspector box model highlighter

    There is a new font family tooltip to the CSS rule view. Hover over a font-family value to see an inline preview of the font. (development notes)

    Inspector font family preview

    Web Console

    There are some big improvements in the web console to help view and navigate output.

    Sample console output

    Highlight and jump to nodes from console

    Running the cd() command in the console switches the scope between iframes. Read more in the cd command documentation. (development notes)

    Console cd() command

    You can read more from Mihai about the ongoing changes to the web console. He has also been documenting the web console API for extension authors.

    Firefox OS

    The network monitor is now working with Firefox OS. (development notes)

    There is now memory tracking (development notes) and jank tracking (development notes) in the Firefox OS Developer HUD. You can read much more about jank (aka “event loop lag”) in Paul’s Firefox OS: tracking reflows and event loop lags.

    Firefox OS Developer HUD

    Network Monitor

    The Network Monitor has a new look to go along with some new features:

    • The design of the network timeline has been updated, which has actually improved scroll performance on the panel. (development notes)
    • Hovering over a request with an image response now shows a popup with the image. (development notes)
    • Network requests with an image response now display a thumbnail near the file name. (development notes)

    Network Monitor Timeline UI

    Network requests with a JSON-like response will show an object preview, even if the response type is plain text. (development notes)

    JSON Response in Network Monitor

    Toolbox

    There is new behavior for console shortcut key (cmd+alt+k or ctrl+shift+k). It now focuses the input line in web console at all times, opening the toolbox if necessary but never closing it. There are more details about this change on robcee’s blog. (development notes)

    To save some space on the top toolbar, there are now options to hide command buttons, like Scratchpad. The only buttons enabled by default now are Inspect Element, Split Console, and Responsive Mode. More information about this change on the devtools mailing list. (development notes). To enable Scratchpad, Paint Flashing, or Tilt, just click on the checkbox in the options panel.

    Enabling Command Buttons on Toolbar

    We would like to give a special thanks to all 46 people who contributed patches to DevTools this release! Here is a list of all DevTools bugs resolved for Firefox 30.

    Do you have feedback, bug reports, feature requests, or questions? As always, you can comment here or get in touch with the team at @FirefoxDevTools.

  4. It's a wrap! "App Basics for FirefoxOS" is out and ready to get you started

    A week ago we announced a series of video tutorials around creating HTML5 apps for Firefox OS. Now we released all the videos and you can watch the series in one go.

    wrap
    Photo by Olliver Hallmann

    The series is aimed at web developers who want to build their first HTML5 application. Specifically it is meant to be distributed in the emerging markets, where Firefox OS is the first option to get an affordable smartphone and start selling apps to the audiences there.

    Over the last week, we released the different videos of the series – one each day:

    Yesterday we announced the last video in the series. For all of you who asked for the whole series to watch in one go, you now got the chance to do so.

    There are various resources you can use:

    What’s next?

    There will be more videos on similar topics coming in the future and we are busy getting the videos dubbed in other languages. If you want to help us get the word out, check the embedded versions of the videos on Codefirefox.com, where we use Amara to allow for subtitles.

    Speaking of subtitles and transcripts, we are currently considering both, depending on demand. If you think this would be a very useful thing to have, please tell us in the comments.

    Thanks

    Many thanks to Sergi, Jan, Jakob, Ketil, Nathalie and Anne from Telenor, Brian Bondy from Khan Academy, Paul Jarrat and Chris Heilmann of Mozilla to make all of this possible. Technologies used to make this happen were Screenflow, Amazon S3, Vid.ly by encoding.com and YouTube.

  5. Introducing the Canvas Debugger in Firefox Developer Tools

    The Canvas Debugger is a new tool we’ll be demoing at the Game Developers Conference in San Francisco. It’s a tool for debugging animation frames rendered on a Canvas element. Whether you’re creating a visualization, animation or debugging a game, this tool will help you understand and optimize your animation loop. It will let you debug either a WebGL or 2D Canvas context.

    Canvas Debugger Screenshot

    You can debug an animation using a traditional debugger, like our own JavaScript Debugger in Firefox’ Developer Tools. However, this can be difficult as it becomes a manual search for all of the various canvas methods you may wish to step through. The Canvas Debugger is designed to let you view the rendering calls from the perspective of the animation loop itself, giving you a much better overview of what’s happening.

    How it works

    The Canvas Debugger works by creating a snapshot of everything that happens while rendering a frame. It records all canvas context method calls. Each frame snapshot contains a list of context method calls and the associated JavaScript stack. By inspecting this stack, a developer can trace the call back to the higher level function invoked by the app or engine that caused something to be drawn.

    Certain types of Canvas context functions are highlighted to make them easier to spot in the snapshot. Quickly scrolling through the list, a developer can easily spot draw calls or redundant operations.

    Canvas Debugger Call Highlighting Detail

    Each draw call has an associated screenshot arranged in a timeline at the bottom of the screen as a “film-strip” view. You can “scrub” through this film-strip using a slider to quickly locate a draw call associated with a particular bit of rendering. You can also click a thumbnail to be taken directly to the associated draw call in the animation frame snapshot.

    Canvas Debugger Timeline Picture

    The thumbnail film-strip gives you get a quick overview of the drawing process. You can easily see how the scene is composed to get the final rendering.

    Stepping Around

    You might notice a familiar row of buttons in the attached screenshot. They’ve been borrowed from the JavaScript Debugger and provide the developer a means to navigate through the animation snapshot. These buttons may change their icons at final release, but for now, we’ll describe them as they currently look.

    Canvas Debugger Buttons image

    • “Resume” – Jump to the next draw call.
    • “Step Over” – Goes over the current context call.
    • “Step Out” – Jumps out of the animation frame (typically to the next requestAnimationFrame call).
    • “Step In” – Goes to the next non-context call in the JavaScript debugger

    Jumping to the JavaScript debugger by “stepping in” on a snapshot function call, or via a function’s stack, allows you to add a breakpoint and instantly pause if the animation is still running. Much convenience!

    Future Work

    We’re not done. We have some enhancements to make this tool even better.

    • Add the ability to inspect the context’s state at each method call. Highlight the differences in state between calls.
    • Measure Time spent in each draw call. This will readily show expensive canvas operations.
    • Make it easier to know which programs and shaders are currently in use at each draw call, allowing you to jump to the Shader Editor and tinkering with shaders in real time. Better linkage to the Shader Editor in general.
    • Inspecting Hit Regions by either drawing individual regions separately, colored differently by id, or showing the hit region id of a pixel when hovering over the preview panel using the mouse.

    And we’re just getting started. The Canvas Debugger should be landing in Firefox Nightly any day now. Watch this space for news of its landing and more updates.

  6. The Translation of the Firetext App

    The History

    Firetext is an open-source word processor. The project was started in early 2013 by @HRanDEV, @logan-r, and me (@Joshua-S). The goal of the project was to provide a user-friendly editing experience, and to fill a major gap in functionality on Firefox OS.

    Firetext 0.3Firetext 0.3

    In the year since its initiation, Firetext became one of the top ten most popular productivity apps in the Firefox Marketplace. We made a myriad of new additions, and Firetext gained Dropbox integration, enabling users to store documents in the cloud. We also added Night Mode, a feature that automatically adjusts the interface to the surrounding light levels. There was a new interface design, better performance, and web activity support.

    Even with all of these features, Firetext’s audience was rather small. We had only supported the English language, and according to Exploredia, only 17.65% of the world’s population speak English fluently. So, we decided to localize Firetext.

    The Approach

    After reading a Hacks post about Localizing Firefox Apps, we determined to use a combination of webL10n and Google Translate as our localization tools. We decided to localize in the languages known by our contributors (Spanish and German), and then use Google Translate to do the others. Eventually, we planned to grow a community that could contribute translations, instead of just relying on the often erratic machine translations.

    The Discovery

    A few months passed, and still no progress. The task was extremely daunting, and we did not know how to proceed. This stagnation continued until I stumbled upon a second Hacks post, Localizing the Firefox OS Boilerplate App.

    It was like a dream come true. Mozilla had started a program to help smaller app developers with the localization process. We could benefit from their larger contributor pool, while helping them provide a greater number of apps to foreign communities.

    I immediately contacted Mozilla about the program, and was invited to set up a project on Transifex. The game was on!

    The Code

    I started by creating a locales directory that would contain our translation files. I created a locales.ini file in that directory to show webL10n where to find the translations. Finally, I added a folder for each locale.

    locales.ini - Firetext

    I then tagged each translatable element in the html files with a data-l10n-id attribute, and localized alert()s and our other scripted notifications by using webL10n’s document.webL10n.get() or _() function.

    It was time to add the translations. I created a app.properties file in the locales/en_US directory, and referenced it from locales.ini. After doing that, I added all of the strings that were supposed to be translated.

    app.properties - Firetext

    webL10n automatically detects the user’s default locale, but we also needed to be able to change locales manually. To allow this, I added a select in the Firetext settings panel that contained all of the prospective languages.Settings - Firetext

    Even after all of this, Firetext was not really localized; we only had an English translation. This is where Transifex comes into the picture.

    The Translation

    I created a project for Firetext on Transifex, and then added a team for each language on our GitHub issue. I then uploaded the app.properties file as a resource.

    I also uploaded the app description from our manifest.webapp for translation as a separate resource.

    Firetext on Transifex

    Within hours, translations came pouring in. Within the first week, Hebrew, French, and Spanish were completely translated! I added them to our GitHub repository by downloading the translation properties file, and placing it in the appropriate locale directory. I then enabled that language in the settings panel. The entire process was extremely simple and speedy.

    The Submission

    Now that Firetext had been localized, I needed to submit it back to the Mozilla Marketplace.  This was a fairly straight forward process; just download the zip, extract git files, and add in the API key for our error reporting system.

    In less than one day, Firetext was approved, and made available for our global user base.  Firetext is now available in eight different languages, and I can’t wait to see the feedback going forward!

    The Final Thoughts

    In retrospect, probably the most difficult part of localizing Firetext was supporting RTL (Right To Left) languages.  This was a bit of a daunting task, but the results have totally been worth the effort!  All in all, localization was one of the easiest features that we have implemented.

    As Swiss app developer Gerard Tyedmers, creator of grrd’s 4 in a Row and grrd’s Puzzle, said:

    “…I can say that localizing apps is definitely worth the work. It really helps finding new users.

    The l10n.js solution was a very useful tool that was easy to implement. And I am very happy about the fact that I can add more languages with a very small impact on my code…”

    I couldn’t agree more!

    Firetext Editor - Spanish

    Editor’s Note: The Invitation

    Have a great app like Firetext?  You’re invited too!  We encourage you to join Mozilla’s app localization project on Transifex. With a localized app, you can extend your reach to include users from all over the world, and by so doing, help to support a global base of open web app users.

    For translators, mobile app localization presents some interesting translation and interface design challenges. You’ll need to think of the strings you’re working with in mobile scale, as interaction elements on a small screen. The localizer plays an important role in creating an interface that people in different countries can easily use and understand.  Please, get involved with Firetext or one of our other projects.

    This project is just getting started, and we’re learning as we go. If you have questions or issues not addressed by existing resources such the Hacks blog series on app localization, Transifex help pages, and other articles and repos referenced above, you can contact us. We’ll do our best to point you in the right direction. Thanks!

  7. Building Cordova apps for Firefox OS

    Update: In addition to the Cordova integration described below, Firefox OS is now supported in the 3.5 release of Adobe PhoneGap.

    If you’re already building apps with PhoneGap, you can quickly and easily port your existing apps to Firefox OS. We think this is so cool that we’ve launched a Phones for PhoneGap Apps program, focused specifically on compelling apps built with PhoneGap and/or Cordova. Got a great PhoneGap app? We’d love to send you a device!

    Cordova is a popular Apache Foundation open source project providing a set of device APIs to allow mobile application developers to access native device functions—such as the camera or the accelerometer—from JavaScript. HTML5 applications can be packaged as native apps via the framework and made available for installation from the app stores of supported platforms, including iOS, Android, Blackberry, Windows Phone—and now Firefox OS. Cordova is also the underlying software in the Adobe product PhoneGap.

    Over the past few months, Mozilla has been working with the Cordova team to integrate Firefox OS into the Cordova framework, making it possible to release Cordova apps on the Firefox OS platform. While this is an ongoing project, significant functionality is available now with the 3.4 release of Cordova. In this post we will describe how to use these new capabilities.

    Creating and building a Firefox OS app in Cordova

    The Cordova site explains how to install the software. Note the installation procedure requires Node.js and can be executed from the command line.

    $ sudo npm install -g cordova

    Once Cordova is installed, an application can be built with the Cordova create command. (Parameters for the command are described in the Cordova documentation linked above.)

    $ cordova create hello com.example.hello HelloWorld

    This will create a directory named hello that contains the project and a basic web app in the hello/www directory. In order to produce a Firefox OS app, the proper platform needs to be added next.

    $ cd hello
    $ cordova platform add firefoxos

    With some of the other supported platforms, you would generally run a build command at this stage to produce the output for the platform. Because Firefox OS is an HTML5-based operating system, no compile step is needed to process and produce the app. The only step required is a prepare statement to package the app.

    $ cordova prepare firefoxos

    Those are the basic steps to generate a simple Firefox OS app from a Cordova project. The output for the project will be located in the hello/platforms/firefoxos/www directory.

    Debugging the app

    With most other Cordova platforms you would use the emulate or run commands to test an app. With Firefox OS you currently need to use the App Manager, which is the primary tool for debugging and interrogating a Firefox OS app. The tool offers many capabilities including JavaScript debugging and live editing of the CSS while connected to a device.

    The above link explains how to install and start the App Manager. Once the App Manager is running, you can click the Add Packaged App button and select the hello/platforms/firefoxos/www directory of your app and press the Open button.

    appmanager

    This will add the basic app to the App Manager. You will notice no icons are present. This is because the framework integration does not provide them currently and only a bare-bones manifest.webapp is created. From here you can update the app or debug it. Note that between updates you must run a cordova prepare firefoxos command as this step packages the app and puts it in the platforms/firefoxos/www directory. Below is a screenshot of the Cordova HelloWorld app being debugged.

    debugger

    The Firefox OS Manifest

    Firefox OS apps are essentially HTML5 applications that are described by a manifest file. This manifest file points to artifacts like icons, start page, etc. that will be used by the application. In addition, the manifest controls privilege levels and device-specific APIs that are needed by the app. The manifest documentation is available on MDN.

    With the default integration in Cordova, a very generic manifest is created and placed in the platforms/firefoxos/www directory. In almost all cases this will not suffice, as you will at least want to provide icons for your app. The App Manager will complain if the app does not contain at least a 128×128 pixel sized icon. This does not prevent you from testing your app, but it is required to upload your app to the Firefox Marketplace. The manifest can be created with a simple text editor or you can modify the manifest in the App Manager. An example manifest.webapp is shown below.

    {
      "name": "My App",
      "description": "My elevator pitch goes here",
      "launch_path": "/",
      "icons": {
        "128": "/img/icon-128.png"
      },
      "developer": {
        "name": "Your name or organization",
        "url": "http://your-homepage-here.org"
      },
      "default_locale": "en"
    }

    Make sure the manifest is created or copied into the project/www folder. Subsequent cordova prepare commands will replace the auto-generated manifest with your application-specific manifest.

    Start Up Code

    When creating a Cordova app, the starter code generated includes index.html, css/index.css, img/logo.png and js/index.js files. The code in index.js is initiated in index.hml like this:

    <script type="text/javascript">
      app.initialize();
    </script>

    The initialize function essentially sets up the event trigger for the onDeviceReady event, which signifies that the Cordova framework is loaded and ready. The generated code is sufficient for Firefox OS unless you want to implement a privileged App. Privileged apps are Marketplace-signed apps that require the use of more sensitive APIs–for example, Contacts API. See the Packaged apps documentation for more information. For privileged Apps, code like this violates CSP restrictions because of the inline script tag. To get around this, remove the inline script and initiate the app using a window.onload event in the js/index.js file.

    Sample App

    To test and debug the Cordova/Firefox OS integration we developed a sample app. This application is available on GitHub. It illustrates use of the device-specific plugins. The images and code snippets in the following sections were taken from the sample app. If you want to check out the code and work with it, first create a Cordova project and check the code into the project/www directory. You can then run cordova prepare firefoxos to package the app. Run and debug as described earlier in this post.

    app

    Device APIs

    Cordova uses a plugin architecture to implement device APIs, such as Accelerometer, Geolocation or Contacts. These APIs are very similar to Firefox OS Web APIs and Web Activities and are documented on the Cordova website. Below are the current plugins implemented for Firefox OS and a brief description of how you can include them in your app. You can always see the current status of plugin development for the Firefox OS Platform by checking Jira on the Apache website.

    Notification API

    The notification API is used to alert the user of your app and is implemented in two plugins: org.apache.cordova.dialogs and org.apache.cordova.vibration. Currently we have implemented the alert, confirm, prompt and vibrate functions. To use this functionality, add the plugins to your project with the following commands:

    $ cordova plugin add org.apache.cordova.dialogs
    $ cordova plugin add org.apache.cordova.vibration

    To get proper styling of popup boxes in Firefox OS, you will need to add the notification.css file to your project. After adding the dialogs plugin, change to the project/plugins/org.apache.cordova.dialogs/www/firefoxos directory and copy the notification.css file to your project/www/css folder. Link the CSS file in head element of index.html.

    <link rel="stylesheet" type="text/css" href="css/notification.css" />

    You can now use the notification functions.

    function onPrompt(results) {
        alert("You selected button number " +
              results.buttonIndex +
              " and entered " + results.input1);
    }
    navigator.notification.vibrate(500);
    navigator.notification.prompt(
          'Enter Name', // message
           onPrompt, // callback to invoke
           'Prompt Test', // title
            ['Ok', 'Exit'], // buttonLabels
             'Doe, Jane' // defaultText
    );

    prompt

    Compass API

    The compass API is implemented using the org.apache.cordova.device-orientation plugin. This plugin implements the compass getCurrentHeading and watchHeading functions. To use it simply run the plugin add command:

    $ cordova plugin add org.apache.cordova.device-orientation

    Once the plugin is added, you can use the get or watch heading function to get compass information.

    function onSuccess(heading) {
        var element = document.getElementById('heading');
        myHeading = (heading.magneticHeading).toFixed(2);
        console.log("My Heading = " + myHeading);
    }
    function onError(compassError) {
        alert('Compass error: ' + compassError.code);
    }
    var options = {
        frequency: 500
    };
    watchID = navigator.compass.watchHeading(onSuccess, onError, options);

    compass

    Accelerometer API

    The Accelerometer is accessed using the org.apache.cordova.device-motion plugin and gives the developer access to acceleration data in x, y and z directions. This plugin implements the getCurrentAcceleration and watchAcceleration functions.

    To use these functions, add the device-motion plugin to your project by executing the following command.

    $ cordova plugin add org.apache.cordova.device-motion

    You can then monitor the acceleration values using code similar to this:

    var options = {
        frequency: 100
    };
    watchIDAccel = navigator.accelerometer.watchAcceleration(onSuccess, onError, options);
    function onSuccess(acceleration) {
      var acX = acceleration.x.toFixed(1) * -1;
      var acY = acceleration.y.toFixed(1);
      var acZ = acceleration.z.toFixed(1);
      var vals = document.getElementById('accvals');
      var accelstr = "<strong>Accel X: </strong>" + acX + "<br />" + "<strong>Accel Y: </strong>" + acY + "<br />" + "<strong>Accel Z: </strong>" + acZ;
      vals.innerHTML = accelstr;
    }
    function onError() {
      alert('Could not Retrieve Accelerometer Data!');
    }

    You can also monitor the device orienttation event and retrieve alpha, beta, and gamma rotation values like:

    function deviceOrientationEvent(eventData) {
        //skew left and right
        var alpha = Math.round(eventData.alpha);
        //front to back - neg back postive front
        var beta = Math.round(eventData.beta);
        //roll left positive roll right neg
        var gamma = Math.round(eventData.gamma);
        console.log("beta = " + beta + " gamma = " + gamma);
    }
    window.addEventListener('deviceorientation', deviceOrientationEvent);

    Camera API

    The camera API is used to retrieve an image from the gallery or from the device camera. This API is implemented in the org.apache.cordova.camera plugin. To use this feature, add the plugin to your project.

    $ cordova plugin add org.apache.cordova.camera

    In the Firefox OS implementation of this plugin, the getPicture function will trigger a Web Activity that allows the user to select where the image is retrieved.

    Code similar to the following can be used to execute the getPicture function:

    navigator.camera.getPicture(function (src) {
        var img = document.createElement('img');
        img.id = 'slide';
        img.src = src;
      }, function () {}, {
          destinationType: 1
    });

    Contacts API

    The contacts API is used to create or retrieve contacts on the device and is implemented in the org.apache.cordova.contacts plugin. To access this feature, run the following command:

    $ cordova plugin add org.apache.cordova.contacts

    Apps that access contacts must be privileged with the appropriate permission set in the manifest file. See “The Firefox OS Manifest” section earlier in this post to understand how to create a custom manifest for your application. For this API, you will need to add the following permissions to the manifest:

    "permissions": {
      "contacts": {
        "access": "readwrite",
        "description": "creates contacts"
      }
    }

    See the manifest documentation for specific access rights. In addition, you will need to change the type of app to privileged in the manifest.

    "type": "privileged",

    Once the manifest has been changed, you can add contacts with code like the following.

    // create a new contact object
    var contact = navigator.contacts.create();
    var name = new ContactName();
    name.givenName = fname;
    name.familyName = lname;
    contact.name = name;
    contact.save(onSuccess, onError);

    contact

    Geolocation API

    The geolocation API is used to retrieve the location, time and speed values from the devices GPS unit and is implemented in the org.apache.cordova.geolocation device plugin.

    $ cordova plugin add org.apache.cordova.geolocation

    You can retrieve the device latitude, longitude and a timestamp using this API on Firefox OS, but it does require the addition of a permission to the manifest file. See “The Firefox OS Manifest” section earlier in this post to understand how to create a custom manifest for your application.

    "permissions": {
        "geolocation": {
          "description": "Marking out user location"
        }
    }

    Adding this permission causes the app to prompt the user for permission to retrieve the GPS data. You can use either getCurrentPosition to read the GPS once or watchPosition to get an interval based update.

    var onSuccess = function (position) {
        console.log('Latitude: ' + position.coords.latitude + 'n' +
        'Longitude: ' + position.coords.longitude + 'n');
    };
    function onError(error) {
        console.log('Error getting GPS Data');
    }
    navigator.geolocation.getCurrentPosition(onSuccess, onError);

    geolocation

    Join Us

    This post covered some of the basics of the new Firefox OS Cordova integration. We will continue to add more device APIs to the project, so stay tuned. If you are interested in working on the integration or need support for a specific device plugin, please contact us on Stack Overflow under the firefox-os tag or in #cordova on Mozilla IRC.

    In the meantime, if you have a Cordova app that makes use of the APIs discussed above, please try generating it for Firefox OS and submitting it to the Firefox Marketplace!

  8. localForage: Offline Storage, Improved

    Web apps have had offline capabilities like saving large data sets and binary files for some time. You can even do things like cache MP3 files. Browser technology can store data offline and plenty of it. The problem, though, is that the technology choices for how you do this are fragmented.

    localStorage gets you really basic data storage, but it’s slow and can’t handle binary blobs. IndexedDB and WebSQL are asynchronous, fast, and support large data sets, but their APIs aren’t very straightforward. Even still, neither IndexedDB nor WebSQL have support from all of the major browser vendors and that doesn’t seem like something that will change in the near future.

    If you need to write a web app with offline support and don’t know where to start, then this is the article for you. If you’ve ever tried to start working with offline support but it made your head spin, this article is for you too. Mozilla has made a library called localForage that makes storing data offline in any browser a much easier task.

    around is an HTML5 Foursquare client that I wrote that helped me work through some of the pain points of offline storage. We’re still going to walk through how to use localForage, but there’s some source for those of you that like learn by perusing code.

    localForage is a JavaScript library that uses the very simple localStorage API. localStorage gives you, essentially, the features of get, set, remove, clear, and length, but adds:

    • an asynchronous API with callbacks
    • IndexedDB, WebSQL, and localStorage drivers (managed automatically; the best driver is loaded for you)
    • Blob and arbitrary type support, so you can store images, files, etc.
    • support for ES6 Promises

    The inclusion of IndexedDB and WebSQL support allows you to store more data for your web app than localStorage alone would allow. The non-blocking nature of their APIs makes your app faster by not hanging the main thread on get/set calls. Support for promises makes it a pleasure to write JavaScript without callback soup. Of course, if you’re a fan of callbacks, localForage supports those too.

    Enough talk; show me how it works!

    The traditional localStorage API, in many regards, is actually very nice; it’s simple to use, doesn’t enforce complex data structures, and requires zero boilerplate. If you had a configuration information in an app you wanted to save, all you need to write is:

    // Our config values we want to store offline.
    var config = {
        fullName: document.getElementById('name').getAttribute('value'),
        userId: document.getElementById('id').getAttribute('value')
    };
     
    // Let's save it for the next time we load the app.
    localStorage.setItem('config', JSON.stringify(config));
     
    // The next time we load the app, we can do:
    var config = JSON.parse(localStorage.getItem('config'));

    Note that we need to save values in localStorage as strings, so we convert to/from JSON when interacting with it.

    This appears delightfully straightforward, but you’ll immediately notice a few issues with localStorage:

    1. It’s synchronous. We wait until the data has been read from the disk and parsed, regardless of how large it might be. This slows down our app’s responsiveness. This is especially bad on mobile devices; the main thread is halted until the data is fetched, making your app seem slow and even unresponsive.

    2. It only supports strings. Notice how we had to use JSON.parse and JSON.stringify? That’s because localStorage only supports values that are JavaScript strings. No numbers, booleans, Blobs, etc. This makes storing numbers or arrays annoying, but effectively makes storing Blobs impossible (or at least VERY annoying and slow).

    A better way with localForage

    localForage gets past both these problems by using asynchronous APIs but with localStorage’s API. Compare using IndexedDB to localForage for the same bit of data:

    IndexedDB Code

    // IndexedDB.
    var db;
    var dbName = "dataspace";
     
    var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
     
    var request = indexedDB.open(dbName, 2);
     
    request.onerror = function(event) {
        // Handle errors.
    };
    request.onupgradeneeded = function(event) {
        db = event.target.result;
     
        var objectStore = db.createObjectStore("users", { keyPath: "id" });
     
        objectStore.createIndex("fullName", "fullName", { unique: false });
     
        objectStore.transaction.oncomplete = function(event) {
            var userObjectStore = db.transaction("users", "readwrite").objectStore("users");
        }
    };
     
    // Once the database is created, let's add our user to it...
     
    var transaction = db.transaction(["users"], "readwrite");
     
    // Do something when all the data is added to the database.
    transaction.oncomplete = function(event) {
        console.log("All done!");
    };
     
    transaction.onerror = function(event) {
        // Don't forget to handle errors!
    };
     
    var objectStore = transaction.objectStore("users");
     
    for (var i in users) {
        var request = objectStore.add(users[i]);
        request.onsuccess = function(event) {
            // Contains our user info.
            console.log(event.target.result);
        };
    }

    WebSQL wouldn’t be quite as verbose, but it would still require a fair bit of boilerplate. With localForage, you get to write this:

    localForage Code

    // Save our users.
    var users = [ {id: 1, fullName: 'Matt'}, {id: 2, fullName: 'Bob'} ];
    localForage.setItem('users', users, function(result) {
        console.log(result);
    });

    That was a bit less work.

    Data other than strings

    Let’s say you want to download a user’s profile picture for your app and cache it for offline use. It’s easy to save binary data with localForage:

    // We'll download the user's photo with AJAX.
    var request = new XMLHttpRequest();
     
    // Let's get the first user's photo.
    request.open('GET', "/users/1/profile_picture.jpg", true);
    request.responseType = 'arraybuffer';
     
    // When the AJAX state changes, save the photo locally.
    request.addEventListener('readystatechange', function() {
        if (request.readyState === 4) { // readyState DONE
            // We store the binary data as-is; this wouldn't work with localStorage.
            localForage.setItem('user_1_photo', request.response, function() {
                // Photo has been saved, do whatever happens next!
            });
        }
    });
     
    request.send()

    Next time we can get the photo out of localForage with just three lines of code:

    localForage.getItem('user_1_photo', function(photo) {
        // Create a data URI or something to put the photo in an img tag or similar.
        console.log(photo);
    });

    Callbacks and promises

    If you don’t like using callbacks in your code, you can use ES6 Promises instead of the callback argument in localForage. Let’s get that photo from the last example, but use promises instead of a callback:

    localForage.getItem('user_1_photo').then(function(photo) {
        // Create a data URI or something to put the photo in an <img> tag or similar.
        console.log(photo);
    });

    Admittedly, that’s a bit of a contrived example, but around has some real-world code if you’re interested in seeing the library in everyday usage.

    Cross-browser support

    localForage supports all modern browsers. IndexedDB is available in all modern browsers aside from Safari (IE 10+, IE Mobile 10+, Firefox 10+, Firefox for Android 25+, Chrome 23+, Chrome for Android 32+, and Opera 15+). Meanwhile, the stock Android Browser (2.1+) and Safari use WebSQL.

    In the worst case, localForage will fall back to localStorage, so you can at least store basic data offline (though not blobs and much slower). It at least takes care of automatically converting your data to/from JSON strings, which is how localStorage needs data to be stored.

    Learn more about localForage on GitHub, and please file issues if you’d like to see the library do more!

  9. CSS source map support, network performance analysis & more – Firefox Developer Tools Episode 29

    Firefox 29 was just uplifted to the Aurora release channel. This means that it is time to report some of the major changes that you can expect to see inside of the Developer Tools for this release.

    Better Looking Tools

    In addition to new features, we have been updating the look and feel of our dark and light themes. The light theme has been completely overhauled, and both themes feature a more consistent design throughout the toolbox. Your current theme can be changed from the Toolbox settings. (development notes)

    Network Monitor

    The Network Monitor now shows you how long it takes the browser to load different parts of your page. This will help measure the network performance of applications, both on first-run and with a primed cache. (development notes)

    To open the performance analysis tool, click the stopwatch icon in the network panel. For more information, watch the screencast below or read more on MDN.

    You can now copy an image request as a Data URI. Just right click on the image request, select the item from the context menu, and the Data URI will be on your clipboard. (development notes)

    Inspector

    We’ve updated the inspector highlighter behavior to bring the highlighting functionality more in line with other tools. (development notes)

    CSS transform preview tooltips have been added to the CSS rule view. Now, if you hover over a CSS transform, you will get a tooltip with a visualization of the transform. Grab a download of Firefox Nightly or Aurora and try it out on some live CSS transfom examples. (development notes)

    CSS rule view now supports pasting multiple CSS declarations at once, like background: #ccc; color: red. (development notes).

    Just like in the network panel, you can now copy <img> elements as Data URIs. (development notes)

    Style Editor

    CSS source map support has been added to the Style Editor. (development notes), and CSS properties and values will now be autocompleted in the Style Editor. (development notes)

    Want to read more? We have published a post with more information about using source maps in DevTools to live edit Sass and Less.

    Debugger

    We have added a classic call stack list in the debugger next to the list of sources. (development notes)

    There is a new ‘enable/disable all breakpoints’ button in the debugger. This will toggle the active state of all existing breakpoints at once, to allow switching between normal usage and debugging quickly. (development notes)

    You can now highlight and inspect DOM nodes from the debugger. If you hover a DOM node in the variables listing it will be highlighted on the page, and if you click on the inspect icon the node will be opened in the inspector tab. This feature is also available in the console output. (development notes)

    Pretty printing now preserves code comments. We are using the open source pretty-fast pretty printer, so it should be pretty fast. If it isn’t, be sure to let us know. (development notes)

    Console

    console.trace improvements. The call stack is shown inline with other output, and includes links to access each line in the debugger. (development notes)

    We’ve also improved console object output to show additional information based on the object type. (development notes)

    Code Editor

    The code editor can be seen throughout the tools in places like Scratchpad, Style Editor, and Debugger. Here are some of the updates you will see in this release:

    • Code folding in the editor. (development notes)
    • Emacs and VIM keybindings are now available in the code editor. To enable them, open about:config, and set “devtools.editor.keymap” to either “vim” or “emacs”, then restart DevTools. (development notes)
    • ES6 syntax highlighting support (development notes)

    Big thanks to all of our DevTools contributors this release (43 people)! Here is a list of all DevTools bugs resolved for Firefox 29.

    Do you have feedback, bug reports, feature requests, or questions? As always, you can comment here or get in touch with the team at @FirefoxDevTools.

  10. WebGL Deferred Shading

    WebGL brings hardware-accelerated 3D graphics to the web. Many features of WebGL 2 are available today as WebGL extensions. In this article, we describe how to use the WEBGL_draw_buffers extension to create a scene with a large number of dynamic lights using a technique called deferred shading, which is popular among top-tier games.

    live demosource code

    Today, most WebGL engines use forward shading, where lighting is computed in the same pass that geometry is transformed. This makes it difficult to support a large number of dynamic lights and different light types.

    Forward shading can use a pass per light. Rendering a scene looks like:

    foreach light {
      foreach visible mesh {
        if (light volume intersects mesh) {
          render using this material/light shader;
          accumulate in framebuffer using additive blending;
        }
      }
    }

    This requires a different shader for each material/light-type combination, which adds up. From a performance perspective, each mesh needs to be rendered (vertex transform, rasterization, material part of the fragment shader, etc.) once per light instead of just once. In addition, fragments that ultimately fail the depth test are still shaded, but with early-z and z-cull hardware optimizations and a front-to-back sorting or a z-prepass, this not as bad as the cost for adding lights.

    To optimize performance, light sources that have a limited effect are often used. Unlike real-world lights, we allow the light from a point source to travel only a limited distance. However, even if a light’s volume of effect intersects a mesh, it may only affect a small part of the mesh, but the entire mesh is still rendered.

    In practice, forward shaders usually try to do as much work as they can in a single pass leading to the need for a complex system of chaining lights together in a single shader. For example:

    foreach visible mesh {
      find lights affecting mesh;
      Render all lights and materials using a single shader;
    }

    The biggest drawback is the number of shaders required since a different shader is required for each material/light (not light type) combination. This makes shaders harder to author, increases compile times, usually requires runtime compiling, and increases the number of shaders to sort by. Although meshes are only rendered once, this also has the same performance drawbacks for fragments that fail the depth test as the multi-pass approach.

    Deferred Shading

    Deferred shading takes a different approach than forward shading by dividing rendering into two passes: the g-buffer pass, which transforms geometry and writes positions, normals, and material properties to textures called the g-buffer, and the light accumulation pass, which performs lighting as a series of screen-space post-processing effects.

    // g-buffer pass
    foreach visible mesh {
      write material properties to g-buffer;
    }
     
    // light accumulation pass
    foreach light {
      compute light by reading g-buffer;
      accumulate in framebuffer;
    }

    This decouples lighting from scene complexity (number of triangles) and only requires one shader per material and per light type. Since lighting takes place in screen-space, fragments failing the z-test are not shaded, essentially bringing the depth complexity down to one. There are also downsides such as its high memory bandwidth usage and making translucency and anti-aliasing difficult.

    Until recently, WebGL had a roadblock for implementing deferred shading. In WebGL, a fragment shader could only write to a single texture/renderbuffer. With deferred shading, the g-buffer is usually composed of several textures, which meant that the scene needed to be rendered multiple times during the g-buffer pass.

    WEBGL_draw_buffers

    Now with the WEBGL_draw_buffers extension, a fragment shader can write to several textures. To use this extension in Firefox, browse to about:config and turn on webgl.enable-draft-extensions. Then, to make sure your system supports WEBGL_draw_buffers, browse to webglreport.com and verify it is in the list of extensions at the bottom of the page.

    To use the extension, first initialize it:

    var ext = gl.getExtension('WEBGL_draw_buffers');
    if (!ext) {
      // ...
    }

    We can now bind multiple textures, tx[] in the example below, to different framebuffer color attachments.

    var fb = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, tx[0], 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, tx[1], 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT2_WEBGL, gl.TEXTURE_2D, tx[2], 0);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT3_WEBGL, gl.TEXTURE_2D, tx[3], 0);

    For debugging, we can check to see if the attachments are compatible by calling gl.checkFramebufferStatus. This function is slow and should not be called often in release code.

    if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
      // Can't use framebuffer.
      // See http://www.khronos.org/opengles/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml
    }

    Next, we map the color attachments to draw buffer slots that the fragment shader will write to using gl_FragData.

    ext.drawBuffersWEBGL([
      ext.COLOR_ATTACHMENT0_WEBGL, // gl_FragData[0]
      ext.COLOR_ATTACHMENT1_WEBGL, // gl_FragData[1]
      ext.COLOR_ATTACHMENT2_WEBGL, // gl_FragData[2]
      ext.COLOR_ATTACHMENT3_WEBGL  // gl_FragData[3]
    ]);

    The maximum size of the array passed to drawBuffersWEBGL depends on the system and can be queried by calling gl.getParameter(gl.MAX_DRAW_BUFFERS_WEBGL). In GLSL, this is also available as gl_MaxDrawBuffers.

    In the deferred shading geometry pass, the fragment shader writes to multiple textures. A trivial pass-through fragment shader is:

    #extension GL_EXT_draw_buffers : require
    precision highp float;
    void main(void) {
      gl_FragData[0] = vec4(0.25);
      gl_FragData[1] = vec4(0.5);
      gl_FragData[2] = vec4(0.75);
      gl_FragData[3] = vec4(1.0);
    }

    Even though we initialized the extension in JavaScript with gl.getExtension, the GLSL code still needs to include #extension GL_EXT_draw_buffers : require to use the extension. With the extension, the output is now the gl_FragData array that maps to framebuffer color attachments, not gl_FragColor, which is traditionally the output.

    g-buffers

    In our deferred shading implementation the g-buffer is composed of four textures: eye-space position, eye-space normal, color, and depth. Position, normal, and color use the floating-point RGBA format via the OES_texture_float extension, and depth uses the unsigned-short DEPTH_COMPONENT format.

    Position texture

    Normal texture

    Color texture

    Depth texture

    Light accumulation using g-buffers

    This g-buffer layout is simple for our testing. Although four textures is common for a full deferred shading engine, an optimized implementation would try to use the least amount of memory by lowering precision, reconstructing position from depth, packing values together, using different distributions, and so on.

    With WEBGL_draw_buffers, we can use a single pass to write each texture in the g-buffer. Compared to using a single pass per texture, this improves performance and reduces the amount of JavaScript code and GLSL shaders. As shown in the graph below, as scene complexity increases so does the benefit of using WEBGL_draw_buffers. Since increasing scene complexity requires more drawElements/drawArrays calls, more JavaScript overhead, and transforms more triangles, WEBGL_draw_buffers provides a benefit by writing the g-buffer in a single pass, not a pass per texture.

    All performance numbers were measured using an NVIDIA GT 620M, which is a low-end GPU with 96 cores, in FireFox 26.0 on Window 8. In the above graph, 20 point lights were used. The light intensity decreases proportionally to the square of the distance between the current position and the light position. Each Stanford Dragon is 100,000 triangles and requires five draw calls so, for example, when 25 dragons are rendered, 125 draw calls (and related state changes) are issued, and a total of 2,500,000 triangles are transformed.


    WEBGL_draw_buffers test scene, shown here with 100 Stanford Dragons.

    Of course, when scene complexity is very low, like the case of one dragon, the cost of the g-buffer pass is low so the savings from WEBGL_draw_buffers are minimal, especially if there are many lights in the scene, which drives up the cost of the light accumulation pass as shown in the graph below.

    Deferred shading requires a lot of GPU memory bandwidth, which can hurt performance and increase power usage. After the g-buffer pass, a naive implementation of the light accumulation pass would render each light as a full-screen quad and read the entirety of each g-buffer. Since most light types, like point and spot lights, attenuate and have a limited volume of effect, the full-screen quad can be replaced with a world-space bounding volume or tight screen-space bounding rectangle. Our implementation renders a full-screen quad per light and uses the scissor test to limit the fragment shader to the light’s volume of effect.

    Tile-Based Deferred Shading

    Tile-based deferred shading takes this a step farther and splits the screen into tiles, for example 16×16 pixels, and then determines which lights influence each tile. Light-tile information is then passed to the shader and the g-buffer is only read once for all lights. Since this drastically reduces memory bandwidth, it improves performance. The following graph shows performance for the sponza scene (66,450 triangles and 38 draw calls) at 1024×768 with 32×32 tiles.

    Tile size affects performance. Smaller tiles require more JavaScript overhead to create light-tile information, but less computation in the lighting shader. Larger tiles have the opposite tradeoff. Therefore, choosing a suitable tile is important for the performance. The figure below is shown the relationship between tile size and performance with 100 lights.

    A visualization of the number of lights in each tile is shown below. Black tiles have no lights intersecting them and white tiles have the most lights.


    Shaded version of tile visualization.

    Conclusion

    WEBGL_draw_buffers is a useful extension for improving the performance of deferred shading in WebGL. Checkout the live demo and our code on github.

    Acknowledgements

    We implemented this project for the course CIS 565: GPU Programming and Architecture, which is part of the computer graphics program at the University of Pennsylvania. We thank Liam Boone for his support and Eric Haines and Morgan McGuire for reviewing this article.

    References