1. Firefox 4: An early walk-through of IndexedDB

    Web developers already have localStorage, which is used for client side storage of simple key-value pairs. This alone doesn’t address the needs of many web applications for structured storage and indexed data. Mozilla is working on a structured storage API with indexing support called IndexedDB, and we will have some test builds in the next few weeks. This can be compared to the WebDatabase API implemented by several browsers that uses a subset of the allowable language of SQLite. Mozilla has chosen to not implement WebDatabase for various reasons discussed in this post.

    In order to compare IndexedDB and WebDatabase, we are going to show four examples that use most parts of the asynchronous APIs of each specification. The differences between SQL storage with tables (WebDatabase) and JavaScript object storage with indexes (IndexedDB) becomes pretty clear after reading the examples. The synchronous versions of these APIs are only available on worker threads. Since not all browsers currently implement worker threads, the synchronous APIs will not be discussed at this time. The IndexedDB code is based off a proposal that Mozilla has submitted to the W3C WebApps working group that has gotten positive feedback so far. The code for both APIs does not include any error handling (for brevity), but production code should always have it!

    These examples are for the storage of a candy store’s sale of candy to customers, which we’ll refer to as kids. Each entry in candySales represents a sale of a specified amount of candy to a kid, specified by an entry in candy and kids respectively.

    Example 1 – Opening and Setting Up a Database

    This first example demonstrates how to open a database connection and create the tables or object stores if the version number is not correct. Upon opening the database, both examples check the version and create the necessary tables or object stores and then set the correct version number. WebDatabase is a bit stricter in how it handles versions by giving an error if the database version is not what the caller expects (this is specified by the second argument to openDatabase). IndexedDB simply lets the caller handle versioning as they see fit. Note that there is active discussion about how IndexedDB should handle version changes in the working group.

    WebDatabase

    var db = window.openDatabase("CandyDB", "",
                                 "My candy store database",
                                 1024);
    if (db.version != "1") {
      db.changeVersion(db.version, "1", function(tx) {
        // User's first visit.  Initialize database.
        var tables = [
          { name: "kids", columns: ["id INTEGER PRIMARY KEY",
                                    "name TEXT"]},
          { name: "candy", columns: ["id INTEGER PRIMARY KEY",
                                     "name TEXT"]},
          { name: "candySales", columns: ["kidId INTEGER",
                                          "candyId INTEGER",
                                          "date TEXT"]}
        ];
     
        for (var index = 0; index < tables.length; index++) {
          var table = tables[index];
          tx.executeSql("CREATE TABLE " + table.name + "(" +
                        table.columns.join(", ") + ");");
        }
      }, null, function() { loadData(db); });
    }
    else {
      // User has been here before, no initialization required.
      loadData(db);
    }

    IndexedDB

    var request = window.indexedDB.open("CandyDB",
                                        "My candy store database");
    request.onsuccess = function(event) {
      var db = event.result;
      if (db.version != "1") {
        // User's first visit, initialize database.
        var createdObjectStoreCount = 0;
        var objectStores = [
          { name: "kids", keyPath: "id", autoIncrement: true },
          { name: "candy", keyPath: "id", autoIncrement: true },
          { name: "candySales", keyPath: "", autoIncrement: true }
        ];
     
        function objectStoreCreated(event) {
          if (++createdObjectStoreCount == objectStores.length) {
            db.setVersion("1").onsuccess = function(event) {
              loadData(db);
            };
          }
        }
     
        for (var index = 0; index < objectStores.length; index++) {
          var params = objectStores[index];
          request = db.createObjectStore(params.name, params.keyPath,
                                         params.autoIncrement);
          request.onsuccess = objectStoreCreated;
        }
      }
      else {
        // User has been here before, no initialization required.
        loadData(db);
      }
    };

    Example 2 – Storing Kids in the Database

    This example stores several kids into the appropriate table or object store. This example demonstrates one of the risks that have to be dealt with when using WebDatabase: SQL injection attacks. In WebDatabase explicit transactions must be used, but in IndexedDB a transaction is provided automatically if only one object store is accessed. Transaction locking is per-object store in IndexedDB. Additionally, IndexedDB takes a JavaScript object to insert, whereas with WebDatabase callers must bind specific columns. In both cases you get the insertion id in the callback.

    WebDatabase

    var kids = [
      { name: "Anna" },
      { name: "Betty" },
      { name: "Christine" }
    ];
     
    var db = window.openDatabase("CandyDB", "1",
                                 "My candy store database",
                                 1024);
    db.transaction(function(tx) {
      for (var index = 0; index < kids.length; index++) {
        var kid = kids[index];
        tx.executeSql("INSERT INTO kids (name) VALUES (:name);", [kid],
                      function(tx, results) {
          document.getElementById("display").textContent =
              "Saved record for " + kid.name +
              " with id " + results.insertId;
        });
      }
    });

    IndexedDB

    var kids = [
      { name: "Anna" },
      { name: "Betty" },
      { name: "Christine" }
    ];
     
    var request = window.indexedDB.open("CandyDB",
                                        "My candy store database");
    request.onsuccess = function(event) {
      var objectStore = event.result.objectStore("kids");
      for (var index = 0; index < kids.length; index++) {
        var kid = kids[index];
        objectStore.add(kid).onsuccess = function(event) {
          document.getElementById("display").textContent =
            "Saved record for " + kid.name + " with id " + event.result;
        };
      }
    };

    Example 3 – List All Kids

    This example lists all of the kids stored in the kids table or the kids object store. WebDatabase uses a result set object which will be passed to the callback method provided after all rows have been retrieved. IndexedDB, on the other hand, passes a cursor to the event handler as results are retrieved. Results should come back faster, as a result. While not shown in this example, you can also stop iterating data with IndexedDB by simply not calling cursor.continue().

    WebDatabase

    var db = window.openDatabase("CandyDB", "1",
                                 "My candy store database",
                                 1024);
    db.readTransaction(function(tx) {
      // Enumerate the entire table.
      tx.executeSql("SELECT * FROM kids", function(tx, results) {
        var rows = results.rows;
        for (var index = 0; index < rows.length; index++) {
          var item = rows.item(index);
          var element = document.createElement("div");
          element.textContent = item.name;
          document.getElementById("kidList").appendChild(element);
        }
      });
    });

    IndexedDB

    var request = window.indexedDB.open("CandyDB",
                                        "My candy store database");
    request.onsuccess = function(event) {
      // Enumerate the entire object store.
      request = event.result.objectStore("kids").openCursor();
      request.onsuccess = function(event) {
        var cursor = event.result;
        // If cursor is null then we've completed the enumeration.
        if (!cursor) {
          return;
        }
        var element = document.createElement("div");
        element.textContent = cursor.value.name;
        document.getElementById("kidList").appendChild(element);
        cursor.continue();
      };
    };

    Example 4 – List Kids Who Bought Candy

    This example lists all the kids, and how much candy each kid purchased. WebDatabase simply uses a LEFT JOIN query which makes this example very simple. IndexedDB does not currently have an API specified for doing a join between different object stores. As a result, the example opens a cursor to the kids object store and an object cursor on the kidId index on the candySales object store and performs the join manually.

    WebDatabase

    var db = window.openDatabase("CandyDB", "1",
                                 "My candy store database",
                                 1024);
    db.readTransaction(function(tx) {
      tx.executeSql("SELECT name, COUNT(candySales.kidId) " +
                    "FROM kids " +
                    "LEFT JOIN candySales " +
                    "ON kids.id = candySales.kidId " +
                    "GROUP BY kids.id;",
                    function(tx, results) {
        var display = document.getElementById("purchaseList");
        var rows = results.rows;
        for (var index = 0; index < rows.length; index++) {
          var item = rows.item(index);
          display.textContent += ", " + item.name + "bought " +
                                 item.count + "pieces";
        }
      });
    });

    IndexedDB

    candyEaters = [];
    function displayCandyEaters(event) {
      var display = document.getElementById("purchaseList");
      for (var i in candyEaters) {
        display.textContent += ", " + candyEaters[i].name + "bought " +
                               candyEaters[i].count + "pieces";
      }
    };
     
    var request = window.indexedDB.open("CandyDB",
                                        "My candy store database");
    request.onsuccess = function(event) {
      var db = event.result;
      var transaction = db.transaction(["kids", "candySales"]);
      transaction.oncomplete = displayCandyEaters;
     
      var kidCursor;
      var saleCursor;
      var salesLoaded = false;
      var count;
     
      var kidsStore = transaction.objectStore("kids");
      kidsStore.openCursor().onsuccess = function(event) {
        kidCursor = event.result;
        count = 0;
        attemptWalk();
      }
      var salesStore = transaction.objectStore("candySales");
      var kidIndex = salesStore.index("kidId");
      kidIndex.openObjectCursor().onsuccess = function(event) {
        saleCursor = event.result;
        salesLoaded = true;
        attemptWalk();
      }
      function attemptWalk() {
        if (!kidCursor || !salesLoaded)
          return;
     
        if (saleCursor && kidCursor.value.id == saleCursor.kidId) {
          count++;
          saleCursor.continue();
        }
        else {
          candyEaters.push({ name: kidCursor.value.name, count: count });
          kidCursor.continue();
        }
      }
    }

    IndexedDB generally simplifies the programming model for interacting with databases, and allows for a wide number of use cases. The working group is designing this API so it could be wrapped by JavaScript libraries; for instance, there’s plenty of room for a CouchDB-style API on top of our IndexedDB implementation. It would also be very possible to build a SQL-based API on top of IndexedDB (such as WebDatabase). Mozilla is eager to get developer feedback about IndexedDB, particularly since the specification has not been finalized yet. Feel free to leave a comment here expressing your thoughts or leave anonymous feedback through Rypple.

  2. Beyond HTML5: Database APIs and the Road to IndexedDB

    IndexedDB is an evolving web standard for the storage of significant amounts of structured data in the browser and for high performance searches on this data using indexes. Mozilla has submitted substantial technical feedback on the specification, and we plan to implement it in Firefox 4. We spoke to prominent web developers about evolving an elegant structured storage API for the web. While versions of Safari, Chrome, and Opera support a technology called Web SQL Database, which uses SQL statements as string arguments passed to a JavaScript API, we think developer aesthetics are an important consideration, and that this is a particularly inelegant solution for client-side web applications. We brought developer feedback to the editor of the IndexedDB specification, and also spoke with Microsoft, who agree with us that IndexedDB is a good option for the web. With additional implementations from the Chrome team in the offing, we think it is worth explaining our design choices, and why we think IndexedDB is a better solution for the web than Web SQL Database.

    Web applications can already take advantage of localStorage and sessionStorage in IE 8+, Safari 4+, Chrome 4+, Opera 10.5+ and Firefox 2+ to store key-value pairs with a simple JavaScript API. The Web Storage standard (encompassing localStorage and sessionStorage), now widely implemented, is useful for storing smaller amounts of data, but less useful for storing larger amounts of structured data. While many server-side databases use SQL to programmatically store structured data and to meaningfully query it, on the client-side, the use of SQL in a JavaScript API has been contentious.

    SQL? Which SQL?

    Many web developers certainly are familiar with SQL, since many developers touch just as much server-side code (e.g. PHP and database operations) as client-side code (e.g. JavaScript, CSS, and markup). However, despite the ubiquity that SQL enjoys, there isn’t a single normative SQL standard that defines the technology. In particular, SQLite supports most of SQL-92, with some notable omissions, and is what the WebDatabase API is based on. But SQLite itself isn’t a specification — it’s a release-ready technology! And the best definition of what constitutes the supported subset of SQL that SQLite uses is the SQLite manual. In order to really get Web SQL Database right, we’d have to first start with defining a meaningful subset of SQL for web applications. Why define a whole other language, when more elegant solutions exist within JavaScript itself?

    The Benefits and Pitfalls of SQLite

    We think SQLite is an extremely useful technology for applications, and make it available for Firefox extensions and trusted code. We don’t think it is the right basis for an API exposed to general web content, not least of all because there isn’t a credible, widely accepted standard that subsets SQL in a useful way. Additionally, we don’t want changes to SQLite to affect the web later, and don’t think harnessing major browser releases (and a web standard) to SQLite is prudent. IndexedDB does not have this problem; even though our underlying implementation of IndexedDB may be based on SQLite, we keep developers insulated from changes to SQLite by exposing an API that isn’t based on SQLite’s supported syntax.

    Aesthetics and Web Developers

    Last year, we held a summit at the Mozilla campus to discuss storage on the web. We invited web developers to speak to us about a desirable structured storage API on the web. Many did express resigned acceptance of a SQLite-based API, since they had already experimented with releases of Web SQL Database in some browsers, and claimed that something in circulation was better than a collection of ideas. Yet, all voiced enthusiasm for better design choices, and how a simpler model would make life easier for them. We watched as developers whiteboarded a simple BTree API that addressed their application storage needs, and this galvanized us to consider other options. We were resolved that using strings representing SQL commands lacked the elegance of a “web native” JavaScript API, and started looking at alternatives. Along with Microsoft, we sent feedback about the IndexedDB proposal and actively became involved in the standardization effort.

    In another article, we compare IndexedDB with Web SQL Database, and note that the former provides much syntactic simplicity over the latter. IndexedDB leaves room for a third-party JavaScript library to straddle the underlying primitives with a BTree API, and we look forward to seeing initiatives like BrowserCouch built on top of IndexedDB. Intrepid web developers can even build a SQL API on top of IndexedDB. We’d particularly welcome an implementation of the Web SQL Database API on top of IndexedDB, since we think that this is technically feasible. Starting with a SQL-based API for use with browser primitives wasn’t the right first step, but certainly there’s room for SQL-based APIs on top of IndexedDB.

    We want to continue the discussion with web developers about storage on the web, since that helps us structure our thoughts about product features and future web standards. We look forward to seeing the next generation of web applications with support for high performance searches on indexed data, and to seeing web applications work even more robustly in “airplane mode.”

    Links

  3. upcoming changes to the viewport meta tag for firefox mobile

    This is a guest post by Matt Brubeck who works on the Firefox Mobile team.

    The upcoming release of Mobile Firefox (Fennec) 1.1 features improved
    support for the <meta name="viewport"> tag. Previous version of Fennec supported the width, height, and initial-scale viewport properties, but had problems with some sites designed for iPhone and Android browsers. We now support the same properties Mobile Safari does, and we also changed Fennec to render mobile sites more consistently on screens of different sizes and resolutions.

    touch.facebook.com before:

    touch.facebook.com after:

    You can see these changes for yourself in the latest Fennec 1.1 and trunk nightly builds for Maemo, Android, Windows, Mac, or Linux.

    Background

    Mobile browers like Fennec render pages in a virtual “window” (the viewport), usually wider than the screen, so they don’t need to squeeze every page layout into a tiny window (which would break many non-mobile-optimized sites). Users can pan and zoom to see different areas of the page.

    Mobile Safari introduced the “viewport meta tag” to let web developers control the viewport’s size and scale. Many other mobile browsers now support this tag, although it is not part of any web standard. Apple’s documentation does a good job explaining how web developers can use this tag, but we had to do some detective work to figure out exactly how to implement it in Fennec. For example, Safari’s documentation says the content is a “comma-delimited list,” but existing browsers and web pages use any mix of commas, semicolons, and spaces as separators.

    Viewport basics

    A typical mobile-optimized site contains something like the following:

    <meta name="viewport"
     content="width=device-width, initial-scale=1, maximum-scale=1"/>

    The width property controls the size of the viewport. It can be set to a specific number of pixels like width=600 or to the special value device-width value which is the width of the screen in CSS pixels at a scale of 100%. (There are corresponding height and device-height values, which may be useful for pages with elements that change size or position based on the viewport height.)

    The initial-scale property controls the zoom level when the page is first loaded. The maximum-scale, minimum-scale, and user-scalable properties control how users are allowed to zoom the page in or out.

    A pixel is not a pixel

    The iPhone and many popular Android phones have 3- to 4-inch (7–10 cm) screens with 320×480 pixels (~160 dpi). Firefox for Maemo runs on the Nokia N900, which has the same physical size but 480×800 pixels (~240 dpi). Because of this, the last version of Fennec displayed many pages about one third smaller (in actual, physical size) than iPhone or Android. This caused usability and readability problems on many touch-optimized web sites. Peter-Paul Koch wrote about this problem in A pixel is not a pixel.

    Fennec 1.1 for Maemo will use 1.5 hardware pixels for each CSS “pixel”, following the lead of Android’s WebKit-based browser. This means a page with initial-scale=1 will render at close to the same physical size in Fennec for Maemo, Mobile Safari for iPhone, and the Android Browser on both HDPI and MDPI phones. This is consistent with the CSS 2.1 specification, which says:

    If the pixel density of the output device is very different from that of a typical computer display, the user agent should rescale pixel values. It is recommended that the pixel unit refer to the whole number of device pixels that best approximates the reference pixel. It is recommended that the reference pixel be the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm’s length.

    For web developers, this means that 320px be full width in portrait mode at scale=1, on all of the above-mentioned handheld devices, and they may size their layouts and images accordingly. But remember that not all mobile devices are the same width; you should also make sure that your pages work well in landscape mode, and on larger devices like the iPad and Android tablets.

    On 240-dpi screens, pages with initial-scale=1 will effectively be zoomed to 150% by both Fennec and Android WebKit. Their text will be smooth and crisp, but their bitmap images will probably not take advantage of the full screen resolution. To get sharper images on these screens, web developers may want to design images – or whole layouts – at 150% of their final size (or 200%, to support the rumored 320-dpi iPhone) and then scale them down using CSS or viewport properties.

    Right now Fennec uses the same default ratio of 1.5 on all devices. (It’s a hidden preference that can be changed in about:config or by an add-on.) Later we’ll need to change this – as well as many other parts of Fennec’s user interface – to work correctly on screens with different pixel densities. Note that the default ratio of 1.5 is true only when the viewport scale equals 1. Otherwise, the relationship between CSS pixels and device pixels depends on the current zoom level.

    Viewport width and screen width

    Many sites set their viewport to "width=320, initial-scale=1" to fit precisely onto the iPhone display in portrait mode. As mentioned above, this caused problems when Fennec 1.0 endered these sites, especially in landscape mode. To fix this, Fennec 1.1 will expand the viewport width if necessary to fill the screen at the requested scale. This matches the behavior of Android and Mobile Safari, and is especially useful on large-screen devices like the iPad. (Allen Pike’s Choosing a viewport for iPad sites has a good explanation for web developers.)

    For pages that set an initial or maximum scale, this means the width property actually translates into a minimum viewport width. For example, if your layout needs at least 500 pixels of width then you can use the following markup. When the screen is more than 500 pixels wide, the browser will expand the viewport (rather than zoom in) to fit the screen:

    <meta name="viewport" content="width=500, initial-scale=1"/>

    Fennec 1.1 also adds support for minimum-scale, maximum-scale, and user-scalable, with defaults and limits similar to Safari’s. These properties affect the initial scale and width, as well as limiting changes in zoom level.

    Mobile browsers handle orientation changes slightly differently. For example, Mobile Safari often just zooms the page when changing from portrait to landscape, instead of laying out the page as it would if originally loaded in landscape. If web developers want their scale settings to remain consistent when switching orientations on the iPhone, they must add a maximum-scale value to prevent this zooming, which has the sometimes-unwanted side effect of preventing users from zooming in:

    <meta name="viewport" content="initial-scale=1, maximum-scale=1">

    This is not necessary in Fennec; when the device changes orientation, Fennec updates the viewport size, the page layout, and JavaScript/CSS properties like device-width, based on its new “window” dimensions.

    Standards

    There is clearly demand for the viewport meta tag, since it is supported by most popular mobile browsers and used by thousands of web sites. It would be good to have a true standard for web pages to control viewport properties. According to the HTML5 spec, extensions to the meta element should first be registered on the WHATWG wiki and then go through the W3C standards process. If this happens, then we at Mozilla will work to make sure we can implement any changes made during standardization.

  4. Firefox, YouTube and WebM

    Five important items of note today relating to Mozilla’s support for the VP8 codec:

    1. Google will be releasing VP8 under an open source and royalty-free basis. VP8 is a high-quality video codec that Google acquired when they purchased the company On2. The VP8 codec represents a vast improvement in quality-per-bit over Theora and is comparable in quality to H.264.

    2. The VP8 codec will be combined with the Vorbis audio codec and a subset of the Matroska container format to build a new standard for Open Video on the web called WebM. You can find out more about the project at its new site: http://www.webmproject.org/.

    3. We will include support for WebM in Firefox. You can get super-early WebM builds of Firefox 4 pre-alpha today. WebM will also be included in Google Chrome and Opera.

    4. Every video on YouTube will be transcoded into WebM. They have about 1.2 million videos available today and will be working through their back catalog over time. But they have committed to supporting everything.

    5. This is something that is supported by many partners, not just Google and others. Content providers like Brightcove have signed up to support WebM as part of a full HTML5 video solution. Hardware companies, encoding providers and other parts of the video stack are all part of the list of companies backing WebM. Even Adobe will be supporting WebM in Flash. Firefox, with its market share and principled leadership and YouTube, with its video reach are the most important partners in this solution, but we are only a small part of the larger ecosystem of video.

    We’re extremely excited to see Google joining us to support Open Video. They are making technology available on terms consistent with the Open Web and the W3C Royalty-Free licensing terms. And – most importantly – they are committing to support a full open video stack on the world’s largest video site. This changes the landscape for video and moves the baseline for what other sites have to do to maintain parity and keep up with upcoming advances in video technology, not to mention compatibility with the set of browsers that are growing their userbase and advancing technology on the web.

    At Mozilla, we’ve wanted video on the web to move as fast as the rest of the web. That has required a baseline of open technology to build on. Theora was a good start, but VP8 is better. Expect us to start pushing on video innovation with vigor. We’ll innovate like the web has, moving from the edges in, with dozens of small revolutions that add up to something larger than the sum of those parts. VP8 is one of those pieces, HTML5 is another. If you watch this weblog, you can start to see those other pieces starting to emerge as well. The web is creeping into more and more technologies, with Firefox leading the way. We intend to keep leading the web beyond HTML5 to the next place it needs to be.

    Today is a day of great change. Tomorrow will be another.

  5. Getting involved with Account Manager

    It’s been a couple of weeks since we originally posted about Account Manager and we’ve gotten a lot of feedback. We’ve got a few opportunities for people to get more involved with the project, listed below.

    Join us at the Account Manager Meet-up or at IIW

    We are hosting an Account Manager Meet-up on Friday, May 21st at Mozilla’s Mountain View Headquarters. This meetup will be an excellent opportunity to give your feedback on the draft specification as we prepare to finalize it. So, if you are a web developer, sysadmin, protocol or security expert, RSVP here.

    The summit will be from 1PM to 4PM followed by a “cantina” during which you’ll get a chance to meet with other Mozilla developers over informal drinks and snacks.

    We’ll also be presenting at the Internet Identity Workshop next week; if you are planning on attending IIW look for the Account Manager talk and come and say hello!

    Browser-assisted registration

    Another way to help out is to add reigistration support to your site. The latest version of the Account Manager add-on adds support for a basic registration flow, and we’re very interested in finding out what the Web development community thinks about it. Here’s what you need to do:

    Add a snippet to the username-password-form profile in your AMCD:

    "register": {
        "method": "POST",
        "path": "/register-endpoint",
        "id-type": "email"
    }

    Then you need to add a method at /register-endpoint which will receive the user id and secret as POST parameters. Your method should return 200 if the id and secret are OK, otherwise return 400 with a snippet of JSON (see the spec for details and examples).

    You might need to change your content to accomodate this new model: after you return 200 the expectation is that there is a username+password pair which is valid, even though it might map to a disabled account. For example, if you need to ask for additional information, have the user solve a captcha, or require email verification, simply keep the account disabled until those additional requirements have been met.

    Addressing cross-site request forgeries

    Based on feedback from the community, we’ve been investigating several possibilities for preventing CSRF attacks with Account Manager. In addition to supporting CSRF tokens, the latest proposal leverages headers to achieve the same goal with fewer requests and without a session cookie. Interested? Join the discussion on our forum.

    Join us online

    Join our online community, visit the Account Manager feature page to learn more about Account Manager, and to subscribe to our mailing list/forum.

    If you add support for Account Manager to your site, please add yourself to the the wiki page for early Account Manager sites.

  6. Firefox 4: the HTML5 parser – inline SVG, speed and more

    This is a guest post from Henri Sivonen, who has been working on Firefox’s new HTML5 parser. The HTML parser is one of the most complicated and sensitive pieces of a browser. It controls how your HTML source is turned into web pages and as such changes to it are rare and need to be well-tested. While most of Gecko has been rebuilt since its initial inception in the late 90s, the parser was one of the stand-outs as being “original.” This replaces that code with a new parser that’s faster, compliant with the new HTML5 standard and enables a lot of new functionality as well.

    A project to replace Gecko’s old HTML parser, dating from 1998, has been ongoing for some time now. The parser was just turned on by default on the trunk, so you can now try it out by simply downloading a nightly build without having to flip any configuration switch.

    There are four main things that improve with the new HTML5 parser:

    • You can now use SVG and MathML inline in HTML5 pages, without XML namespaces.
    • Parsing is now done off Firefox’s main UI thread, improving overall browser responsiveness.
    • It’s improved the speed of innerHTML calls by about 20%.
    • With the landing of the new parser we’ve fixed dozens of long-standing parser related bugs.

    Try the demo with a Firefox Nightly or another HTML5-ready browser. It should look like this:

    What Is It?

    The HTML5 parser in Gecko turns a stream of bytes into a DOM tree according to the HTML5 parsing algorithm.

    HTML5 is the first specification that tells implementors, in detail, how parse HTML. Before HTML5, HTML specifications didn’t say how to turn a stream of bytes into a DOM tree. In theory, HTML before HTML5 was supposed to be defined in terms of SGML. This implied a certain relationship between the source of valid HTML documents and the DOM. However, parsing wasn’t well-defined for invalid documents (and Web content most often isn’t valid HTML4) and there are SGML constructs that were in theory part of HTML but that in reality popular browsers didn’t implement.

    The lack of a proper specification led to browser developers filling in the blanks on their own and reverse engineering the browser with the largest market share (first Mosaic, then Netscape, then IE) when in doubt about how to get compatible behavior. This led to a lot of unwritten common rules but also to different behavior across browsers.

    The HTML5 parsing algorithm standardizes well-defined behavior that browsers and other applications that consume HTML can converge on. By design, the HTML5 parsing algorithm is suitable for processing existing HTML content, so applications don’t need to continue maintaining their legacy parsers for legacy content. Concretely, in the trunk nightlies, the HTML5 parser is used for all text/html content.

    How Is It Different?

    The HTML5 parsing algorithm has two major parts: tokenization and tree building. Tokenization is the process of splitting the source stream into tags, text, comments and attributes inside tags. The tree building phase takes the tags and the interleaving text and comments and builds the DOM tree. The tokenization part of the HTML5 parsing algorithm is closer to what Internet Explorer does than what Gecko used to do. Internet Explorer has had the majority market share for a while, so sites have generally been tested not to break when subjected to IE’s tokenizer. The tree building part is close to what WebKit does already. Of the major browser engines WebKit had the most reasonable tree building solution prior to HTML5.

    Furthermore, the new HTML5 parser parses network streams off the main thread. Traditionally, browsers have performed most tasks on the main thread. Radical changes like off-the-main-thread parsing are made possible by the more maintainable code base of the HTML5 parser compared to Gecko’s old HTML parser.

    What’s In It for Web Developers?

    The changes mentioned above are mainly of interest to browser developers. A key feature of the HTML5 parser is that you don’t notice that anything has changed.

    However, there is one big new Web developer-facing feature, too: inline MathML and SVG. HTML5 parsing liberates MathML and SVG from XML and makes them available in the main file format of the Web.

    This means that you can include typographically sophisticated math in your HTML document without having to recast the entire document as XHTML or, more importantly, without having to retrofit the software that powers your site to output well-formed XHTML. For example, you can now include the solution for quadratic equations inline in HTML:

    <math>
      <mi>x</mi>
     
      <mo>=</mo>
      <mfrac>
        <mrow>
          <mo>&minus;</mo>
          <mi>b</mi>
          <mo>&PlusMinus;</mo>
          <msqrt>
            <msup>
     
              <mi>b</mi>
              <mn>2</mn>
            </msup>
            <mo>&minus;</mo>
            <mn>4</mn>
            <mo>&InvisibleTimes;</mo>
            <mi>a</mi>
     
            <mo>&InvisibleTimes;</mo>
            <mi>c</mi>
          </msqrt>
        </mrow>
        <mrow>
          <mn>2</mn>
          <mo>&InvisibleTimes;</mo>
          <mi>a</mi>
     
        </mrow>
      </mfrac>
    </math>

    Likewise, you can include scalable inline art as SVG without having to recast your HTML as XHTML. As screen sized and pixel densities become more varied, making graphics look crisp at all zoom levels becomes more important. Although it has previously been possible to use SVG graphics in HTML documents by reference (using the object element), putting SVG inline is more convenient in some cases. For example, an icon such as a warning sign can now be included inline instead of including it from an external file.

    <svg height=86 width=90 viewBox='5 9 90 86' style='float: right;'>
      <path stroke=#F53F0C stroke-width=10 fill=#F5C60C stroke-linejoin=round d='M 10,90 L 90,90 L 50,14 Z'/>
      <line stroke=black stroke-width=10 stroke-linecap=round x1=50 x2=50 y1=45 y2=75 />
    </svg>

    Make yourself a page that starts with <!DOCTYPE html> and put these two pieces of code in it and it should work with a new nightly.

    In general, if you have a piece of MathML or SVG as XML, you can just copy and paste the XML markup inline into HTML (omitting the XML declaration and the doctype if any). There are two caveats: The markup must not use namespace prefixes for elements (i.e. no svg:svg or math:math) and the namespace prefix for the XLink namespace has to be xlink.

    In the MathML and SVG snippits above you’ll see that the inline MathML and SVG pieces above are more HTML-like and less crufty than merely XML pasted inline. There are no namespace declarations and unnecessary quotes around attribute values have been omitted. The quote omission works, because the tags are tokenized by the HTML5 tokenizer—not by an XML tokenizer. The namespace declaration omission works, because the HTML5 tree builder doesn’t use attributes looking like namespace declarations to assign MathMLness or SVGness to elements. Instead, <svg> establishes a scope of elements that get assigned to the SVG namespace in the DOM and <math> establishes a scope of elements that get assigned to the MathML namespace in the DOM. You’ll also notice that the MathML example uses named character references that previously haven’t been supported in HTML.

    Here’s a quick summary of inline MathML and SVG parsing for Web authors:

    • <svg></svg> is assigned to the SVG namespace in the DOM.
    • <math></math> is assigned to the MathML namespace in the DOM.
    • foreignObject and annotation-xml (an various less important elements) establish a nested HTML scope, so you can nest SVG, MathML and HTML as you’d expect to be able to nest them.
    • The parser case-corrects markup so <SVG VIEWBOX=’0 0 10 10′> works in HTML source.
    • The DOM methods and CSS selectors behave case-sensitively, so you need to write your DOM calls and CSS selectors using the canonical case, which is camelCase for various parts of SVG such as viewBox.
    • The syntax <foo/> opens and immediately closes the foo element if it is a MathML or SVG element (i.e. not an HTML element).
    • Attributes are tokenized the same way they are tokenized in HTML, so you can omit quotes in the same situations where you can omit quotes in HTML (i.e. when the attribute value is not the empty string and does not contain whitespace, ", , `, <, =, or >).
    • Warning: the two above features do not combine well due to the reuse of legacy-compatible HTML tokenization. If you omit quotes on the last attribute value, you must have a space before the closing slash. <circle fill=green /> is OK but <circle fill=red/> is not.
    • Attributes starting with xmlns have absolutely no effect on what namespace elements or attributes end up in, so you don’t need to use attributes starting with xmlns.
    • Attributes in the XLink namespace must use the prefix xlink (e.g. xlink:href).
    • Element names must not have prefixes or colons in them.
    • The content of SVG script elements is tokenized like they are tokenized in XML—not like the content of HTML script elements is tokenized.
    • When an SVG or MathML element is open <![CDATA[]]> sections work the way they do in XML. You can use this to hide text content from older browsers that don’t support SVG or MathML in text/html.
    • The MathML named characters are available for use in named character references everywhere in the document (also in HTML content).
    • To deal with legacy pages where authors have pasted partial SVG fragments into HTML (who knows why) or used a <math> tag for non-MathML purposes, attempts to nest various common HTML elements as children of SVG elements (without foreignObject) will immediately break out of SVG or MathML context. This may make some typos have surprising effects.
  7. Revitalizing Caching

    Apparently, there are only two hard problems in computer science: cache invalidation and the naming of things (or so Phil Karlton’s dictum goes). Earlier this month, we invited representatives of Twitter, Facebook, SproutCore, Palm’s webOS, Microsoft’s “Office On The Web”, Yahoo, and Google to talk to us about the former problem (amongst other things), though we also learned something about the latter.

    Caching is an important issue to get right on the web, not least of all because of the proliferation of web applications on mobile devices. The goals of our caching summit were to identify use cases that would help us move forward with caching and with HTTP request efficiency. How desirable was rolling up our sleeves to look at HTTP/1.1 Pipelining in Firefox, for instance? What else was needed at the HTTP layer? And was the vaunted HTML5 AppCache, implemented in Firefox 3.5 onwards, actually useful to developers? What else needed to be exposed to web applications, either within content or via additional headers?

    Developer feedback is invaluable, and is increasingly the basis of how we want to evolve the next integral pieces of the web platform. Web developers are one of our primary constituencies; going forward, we want them to help us prioritize what we should implement, and what we need to focus on with respect to web standards. We chose our attendees wisely; if any group of people could talk about web applications at scale, the current performance of the cache, and their wishlist for future browser caching behavior on the web platform, it was this group of people. And the feedback they gave us was copious and useful — our work is cut-out for us. Notably, we’ve got a few actions we’re going to follow-up on:

    • Increase the default size of our disk and memory caches. Firefox’s disk cache is currently set at 50MB, a small-ish number given the amount of disk space available on hardware currently (and although this limit can be increased using advanced preferences, few users actually change the default). This is low-hanging fruit for us to fix. An interesting open question is whether we should determine disk cache size heuristically, in lieu of choosing a new upper bound. Steve Souders, who attended our caching summit, blogs about cache sizes, as well as premature cache evictions.

    • Conduct a “Mozilla Test-Pilot” project to get more data about how exactly we cache resources currently. This is part of a larger question about updating our caching algorithm. Like other browsers, we use an optimization of the Least Recently Used (LRU) caching algorithm, called LRU-SP. Data that we would want to gather includes determining what the hit rate, mean, variance and distribution of cached resources are. What’s the average lifetime? How about different modes where our LRU-SP replacement policy doesn’t work well for certain apps, where big resources (such as an essential script file) may get eliminated before smaller ones (such as map tiles)? We’ll also have to research the role that anti-virus software plays in routinely flushing out the cache, leading to further occurrences of untimely eviction of relevant resources.

    • Explore prioritization of resources in the cache based on MIME type. For instance, allowing for JavaScript (text/javascript) to always get higher priority in terms of what gets pruned by our LRU-SP algorithm. A good follow-up for this would be to get Chrome, IE, Apple, and Opera to discuss this with us, and then document what we come up with as a MIME-type based “naive” prioritization. We also want to allow developers to set resource priority on their own, perhaps through a header. This is likely to be an ongoing discussion.

    • Really figure out what hampers the adoption of HTTP/1.1 Pipelining on the web, including data from proxies and how they purge. While Pipelining is enabled in Mobile Firefox builds (such at that running on the Nokia N900 and on Android devices) by default, we have it turned off in desktop Firefox builds. We do this for a variety of reasons, not least of all the risk of performance slow downs if one of the pipelined requests slows down the others. It’s clear from our discussion that many who attended our caching summit think pipelining will help their applications perform much better. The situation on the web now with respect to pipelining is a kind of hostage’s dilemma: of the main desktop browsers, nobody has turned on pipelining, for fear of a scenario that slows down performance (leading to that particular browser being accused of “being slow”). The developers who visited us threw down the proverbial gauntlet; at a minimum we’ve got to figure out what hamstrings the use of pipelining on the web, and determine what we can actually do to remove those obstacles.

    • Figure out how to evolve the HTML5 AppCache, which frankly hasn’t seen the adoption we initially expected. While we tend to view parts of HTML5 such as Cache Manifests and window.applicationCache as yet another performance tool (to ensure web applications rapidly load upon subsequent accesses), it is different than the general browser cache. What’s in a name, and why is naming something amongst the hardest problems in computer science? The use of the word “cache” to describe the parts of HTML5 that deal with offline web applications has confused some developers. What we’re calling the HTML5 AppCache was primarily conceived of to enable offline web application use, but many applications (such as those built with SproutCore) treat it as an auxiliary cache, to ensure that applications have a rapid start-up time and generally perform well. Why, we were asked, should we have two things: a general purpose browser cache, and something else, uniquely for offline usage? On the one hand, the HTML5 AppCache allows web apps to act like native apps (enabling “rapid-launch icons” on some mobile handsets), perhaps even eventually integrating with native application launchers. And on the other hand, the HTML5 AppCache’s separateness from the general cache may mean that we coin different APIs to work with the general cache. In general, simultaneously evolving multiple APIs with “cache” in the name may be confusing. But that’s why naming is amongst the hard problems, and that’s why we have to architect the next iteration mindful of the potential for both redundancy as well as confusion.

    • We’ve got a tracking bug in place with a bold moniker: “Improve HTTP Cache.” You’ll see the gamut of changes we’d like to introduce here, including benchmarking our cache against Chromium’s (and perhaps just using Chromium’s cache code, if we need to).

      Caching is important, but difficult. It would be fair to describe most of the near-term evolution of the web that way, whether that is the introduction of an indexable database capability, streaming video, or new layout models within CSS. These evolutions won’t necessarily happen within a standards body or on a listserv, but rather through rapid prototyping and meaningful feedback. That’s why we have to talk to web developers to help us do the right thing, and that’s why we’ll keep organizing meet-ups such as the recent caching summit.

  8. WebSockets in Firefox

    Here’s the pitch for WebSockets: a low-complexity, low-latency, bi-directional communication system that has a pretty simple API for web developers. Let’s break that down, and then talk about if and when we’re going to include it in Firefox:

    Low-complexity

    The WebSocket protocol, which is started via an HTTP-like handshake, has a relatively simple model for sending text packets back and forth. The complexity of the protocol is quite low. There’s no multiplexing, no support for binary data, and once the data connection is set up, the actual transport is quite cheap.

    Note that there are people who feel – possibly correctly – that support for multiplexing and binary data should be added. That would obviously increase the complexity but in some cases might be worth the cost. But more on that later.

    Bi-directional Communication

    One of the key aspects of WebSocket is its support for simple bi-directional communication. Servers can easily send updates to clients and clients can send updates to servers. Many of the comet-style applications that people have built will be much simpler and faster with this model because the protocol and API support it directly.

    While allowing for bi-directional communication it also is bound by the HTTP same-origin model. That is, it’s doesn’t give the browser the ability to connect to any site on any port it wants to.

    So WebSocket is really TCP with the HTTP security model.

    Low-latency

    This is actually the primary value in WebSockets. The key thing is that the cost of sending a small amount of data is also very small. It’s possible to do bi-directional communication today with comet-style applications, but small amounts of data often require a huge amount of overhead to do so.

    A second-hand story to give you a sense of scale: Google Wave, which tries to do real-time communication with keystrokes has a several-kilobyte overhead for just about every keystroke because of the TCP startup, teardown and HTTP message headers involved with what should be only a few bytes sent over the wire.

    I haven’t tried, but I’m going to guess that if you built Quake on top of HTTP comet that the interactive experience would be poor. So this is where WebSockets really shine.

    Simple API

    The actual API that a developer sees for WebSocket is relatively simple. You can send messages, you can get messages, you get events when sockets open, close or there’s an error. Additional complexity, which I’m sure others will develop, will happen in JavaScript and backend libraries.

    (While this might seem like punting on the issue of complexity, this is actually the model for success we’ve seen for other browser standards: build something relatively simple that others can experiment with. When we understand what’s slow or what’s preventing progress, iterate and improve.)

    When will it be in Firefox?

    We really really want to support WebSockets in the next version of Firefox. And a lot of other people want us to include support too.

    The first set of test patches, written by the wonderful Wellington Fernando de Macedo (one of our most excellent contributors!) was first submitted in April of 2009. Since then we’ve been iterating both on the patches themselves and following the spec as it’s changed.

    Unfortunately, the spec itself is still under revision. WebSockets did ship in Chrome with version 4 and I’m told by Chrome developers that it’s going to be included in Chrome 5, without changes. Unfortunately, the version that Google included in Chrome doesn’t reflect the current draft. The handshake for how to start a WebSocket connection has changed, largely to improve security on servers. There’s also a lot of ongoing discussion on the role of integrated compression, direct support for binary data (instead of encoding binary data as strings), whether or not the protocol should support multiplexing and a number of other issues.

    Since WebSocket isn’t used widely yet, and that Chrome has an uptake rate that’s similar to Firefox, the hope is that once a more recent draft makes it through the process that both Chrome and Firefox can include a more recent version at around the same time.

    So in short: we want to ship it because the promise of WebSockets is great, but we’ll have to see if it’s stable and safe enough to do so. Code isn’t the issue – we’ve had that for a while. It’s whether or not there’s consensus on if the protocol is “done enough” to ship it to a few hundred million people.

  9. The CSS 3 Flexible Box Model

    This article about the Flexible Box Layout was written by Jérémie Patonnier, French open Web enthusiast.

    The flexible box model

    CSS 3 introduces a brand new box model in addition of the traditional box model from CSS 1 and 2. The flexible box model determines the way boxes are distributed inside other boxes and the way they share the available space.

    You can see the specification here.

    This box model is similar to the one used by XUL (the user interface language used by Firefox). Some others languages use similar box models such as XAML or GladeXML.

    Usually the flexible box model is exactly what you need if you want to create fluid layouts which adapt themselves to the size of the browser window or elastic layouts which adapt themselves to the font size.

    In this article, all my examples are based on the following HTML code:

    <body>
      <div id="box1">1</div>
      <div id="box2">2</div>
      <div id="box3">3</div>
    </body>

    Distributing boxes: so what?

    By default, the traditional CSS box model distributes boxes vertically depending on the HTML flow. With the flexible box model, it’s possible to specify the order explicitly. You can even reverse it. To switch to the flexible box model, set the property display to the value box (or inline-box) on a box which has child boxes.

    display: box;

    Horizontal or vertical distribution

    The box-orient property lets you specify the distribution axis. vertical and horizontal values define how boxes are displayed. Other values (inline-axis and block-axis) have the same effect, but also let you define the baseline alignment itself (basically the boxes are treated like “inline” boxes).

    body{
      display: box;
      box-orient: horizontal;
    }

    Reversed distribution

    The property box-direction allows you to set the order in which the boxes appear. By default–when you simply specify the distribution axis–the boxes follow the HTML flow and are distributed from top to bottom if you are using a vertical axis and from left to right if you are using a horizontal axis. By setting box-direction to reverse, you can reverse the boxes’ distribution order. It acts as if you actually reversed the order of the elements in the HTML.

    Be careful with this property because it changes the way some other properties work, which can produce some unexpected behavior.

    body {
      display: box;
      box-orient: vertical;
      box-direction: reverse;
    }

    Explicit distribution

    The property box-ordinal-group lets you specify the order in which the boxes will be distributed. This is the ultimate customization opportunity, because you can define the order you want, regardless of the HTML flow order. Those groups are defined by a number starting at 1 (which is the default value). So the box model will first distribute those groups, then all the boxes inside each group. The distribution occurs from the lowest value (the group numbered 1) to the highest (the groups numbered 2 and above).

    body {
      display: box;
      box-orient: vertical;
      box-direction : reverse;
    }
    #box1 {
      box-ordinal-group: 2;
    }
    #box2 {
      box-ordinal-group: 2;
    }
    #box3 {
      box-ordinal-group: 1;
    }

    And what about flexibility?

    If changing the natural HTML flow order is huge, the real fun begins when you start to deal with the available space.

    Box sizing

    By default, a box is not flexible. It becomes flexible only if it has the property box-flex with a value of at least 1.

    If a box is not flexible, it will be as wide as possible to make its content visible without any overflow. Its size can be forced with the properties width and height (or their min-*, and max-* alternatives).

    If a box is flexible, its size will be computed as follows:

    1. The explicit size declarations (width, height, min-* and max-*)
    2. The size of the parent box and all the remaining available inner space.

    So, if the boxes haven’t any size declarations, their sizes will fully depend on their parent box’s size. It will work like this: the size of box is equal to the size of its parent multiplied by the value of the its box-flex property divided by the sum of all the box-flex properties values of all boxes included in its parent.

    On the other hand, if one or more boxes have an explicit size statements, the size of all those boxes is computed and all the flexible boxes share the remaining available space on the same principle as above.

    It probably sounds a bit tricky, but with some examples it will become easier.

    All boxes are flexible

    In the next example, box 1 is twice the size of box 2 and box 2 has the same size as box 3. It looks the same as using percentages to set the boxes’ sizes. But there is a big difference. If you add a box, you don’t need to recalculate its size. With the flexible box model, each time you add a box, all the others automatically shrink to make room for the new one.

    body {
      display: box;
      box-orient: horizontal;
    }
    #box1 {
      box-flex: 2;
    }
    #box2 {
      box-flex: 1;
    }
    #box3 {
      box-flex: 1;
    }

    Some boxes have a fixed size

    In the next example, box 3, which is not flexible, is 160px in width. In this case, there’s 240px of free space available for boxes 1 and 2. So, box 1 will be 160px in width (240px x 2/3) and box 2 will be 80px in width (240px x 1/3). If you wish, you can make box 3 flexible as well. In this case the way the size of this box is computed will be almost the same as with the property min-width.

    body {
      display: box;
      box-orient: horizontal;
      width: 400px;
    }
    #box1 {
      box-flex: 2;
    }
    #box2 {
      box-flex: 1;
    }
    #box3 {
      width: 160px;
    }

    Managing overflow

    Because we can mix flexible boxes, inflexible boxes, and flexible boxes which have preset sizes, It’s possible for the sum of all the boxes’ sizes to be larger or smaller than the parent box size. So you can have too much space or not enough.

    I have too much space available; what do I do?

    The available space gets distributed depending on the properties box-align and box-pack

    The property box-pack manages the way the space is distributed on the horizontal axis and can have one of four possible values: start, end, justify, or center

    1. start: All the boxes are on the left side of the parent box and all the remaining space is on the right side.
    2. end: All the boxes are on the right and the remaining space is on the left
    3. justify: The available space is divided evenly in-between each boxes
    4. center: The available space is divided evenly on each side of the parent box

    The property box-align manages the way the space is distributed on the vertical axis and can have one of five values: start, end, center, baseline, and stretch

    1. start: The top edge of each box is placed along the top of the parent box and all the remaining space is placed below.
    2. end: The bottom edge of each box is placed along the bottom of the parent box and all the remaining space is placed above.
    3. center: The available space is divided evenly and placed half above and half below.
    4. baseline: All children are placed with their baselines aligned and the remaining space is placed before or after as necessary (This is a simplification about how this value really works, but you see the point).
    5. stretch: The height of each boxes is adjusted to fit the parent box height

    A warning about how those properties work: they are strongly influenced by the use of the properties box-orient and box-direction. They can cause some unexpected behavior (for example, the behavior of values start and end could be fully reversed). I hope that once the specification is finalized, we’ll have more information about how those properties work together.

    body {
      display: box;
      box-orient: horizontal;
      /* The content of the body is horizontally centered */
      box-pack: center;
      /* and vertically as well ... \o/ */
      box-align: center;
      width: 100%;
      height : 100%;
    }

    What happens if I don’t have enough space?

    Just like with the traditional box model, the overflow property lets you to define the way it’s managed. No surprise here.

    However, you must be careful here too. Indeed, the use of the properties box-orient and box-direction can mess it up. For example, you can see elements overflowed to the right instead of the left or to the top instead of the bottom. Take the time to experiment before trying to use it on a big project or you could go mad.

    You can also avoid overflow by making the boxes run over multiple lines (or columns, depending on the orientation) by setting the property box-lines to multiple.

    Okay, cool, but does it work in real life?

    Yes it does! Both Gecko and WebKit have vendor-prefixed implementations of a box model (Note: The current state of the specification does not reflect Mozilla’s or WebKit’s implementation). This means that Firefox, Safari, Chrome, and any browsers that use one of those rendering engines are able to use the features described in this article. If you use one of those awesome browsers, here is a little demo of the flexible box model in action.

    If you’re not using a browser implementing a box model, this screenshot shows you what it looks like:

    To conclude

    You can start to use this box model to layout your HTML documents with modern web browsers. Be careful though, it’s the really first iteration of a W3C Working Draft. There will certainly be some changes. Anyway, the implementations available in Gecko and Webkit are extremely consistent and mature, so if there are changes, they should not be that troublesome.

    This box model is a very easy and simple way to solve some usual problems in web design (form layout, page footers, vertical centering, disassociation of visual flow from HTML flow, etc.). I strongly suggest you become familiar with it because it could become a standard tool for web designers in the near future (if Microsoft decides to include it in IE, it could become so very fast).

    What is already available is a good start to play with. But at this point, the way the traditional box model and the flexible box model interact is not very clear (for example, it’s impossible to use position:relative with the properties left or top on a box which uses the property box-ordinal-group). This will be improved, but don’t be surprised if your work habits are somewhat undermined. Another tricky point: the way all the properties relative to this new box model interact can be sometimes really confusing. This should remind you of the day you discovered the float property. ;)

    For further information

  10. mozilla developer preview 4 ready for testing

    Note: this is a re-post of the entry in the Mozilla Project Development Weblog. There’s some juicy stuff in here for Web Developers that need testing. In particular, this is the first build with the CSS history changes.

    As part of our ongoing platform development work, we’re happy to announce the fourth pre-release of the Gecko 1.9.3 platform. Gecko 1.9.3 will form the core of Firefox and other Mozilla project releases.

    It’s available for download on Mac, Windows or Linux.

    Mozilla expects to release a Developer Preview every 2-3 weeks. If you’ve been running a previous release, you will be automatically updated to the latest version when it is released.

    This preview release contains a lot of interesting stuff that’s worth pointing out, and contains many things that were also in previous releases. Here are the things of note in this release:

    User Interface Changes

    • Open tabs that match searches in the Awesomebar now show up as “Switch to Tab.”
    • This is the first preview release to contain resizable text areas by default.

    Web Developer Changes

    • This is the first preview release to contain changes to CSS :visited that prevent a large class of history sniffing attacks. You can find more information about the details of why this change is important over on the hacks post on the topic and on the Mozilla Security Weblog. Note that this change is likely to break some web sites and requires early testing – please test if you can.
    • SVG Attributes which are mapped to CSS properties can now be animated with SMIL. See the bug or a demo.

    Plugins

    • Out of process plugins support for Windows and Linux continues to improve. This release contains many bug fixes vs. our previous developer preview releases. (In fact, it’s good enough that we’ve ported this code back to the 3.6 branch and have pushed that to beta for a later 3.6.x release.)
    • This is the first release that contains support for out of process plugins for the Mac. If you are running OSX 10.6 and you’re running the latest Flash beta, Flash should run out of process

    Performance

    • One area where people complained about performance was restart performance when applying an update. It turns out that a lot of what made that experience poor wasn’t startup time, it was browser shutdown time. We’ve made a fix since the last preview release that made a whopping 97% improvement in shutdown time. (That’s not a typo, it’s basically free now.)
    • Our work to reduce the amount of I/O on the main thread continues unabated. This preview release will feel much snappier than previous snapshots, and feel much faster than Firefox 3.6.
    • We continue to add hardware acceleration support. If you’re on Windows and you’ve got decent OpenGL 2 drivers, open video will use hardware to scale the video when you’re in full screen mode. For large HD videos this can make a huge difference in the smoothness of the experience and how much power + CPU are used. We’ll be adding OSX and Linux support at some point in the future as well, but we’re starting with Windows.
    • We continue to make improvements and bug fixes to our support for Direct2D. (Not enabled by default. If you want to turn it on see Bas’ post.) If you’re running Alpha 4 on Windows Vista or Windows 7, and you’ve turned on D2D, try running this stress test example in Alpha 4 vs. Firefox 3.6. The difference is pretty amazing. You can also see what this looks like compared to other browsers in this this video. (Thanks to Hans Schmucker for the video and demo.)

    Platform

    • JS-ctypes, our new easy-to-use system for extension authors who want to call into native code now has support for complex types: structures, pointers, and arrays. For more information on this, and how easy it can make calling into native code from JavaScript, see Dan Witte’s post.
    • Mozilla is now sporting an infallible allocator. What is this odd-sounding thing, you ask? It’s basically an allocator that when memory can’t be allocated it aborts instead of returning NULL. This reduces the surface area for an entire class of security bugs related to checking NULL pointers, and also allows us to vastly simplify a huge amount of Gecko’s source code.