Access to the file system on the local device is an increasingly important capability for apps that interact with the user and the user’s data on that file system. Until APIs were added to HTML5, client-side JavaScript code in web apps did not have much access to the file system except through plug-ins, which are not necessarily supported in all browsers. For Windows Store apps, access to the file system is of course a very important need, so there are extensive APIs for this purpose as well as protections for that file system. As we’ll see, Windows Store apps really need to use the WinRT APIs to work within those protections; the HTML5 file APIs are of only limited used.

This comparison is different from others posted here in that the HTML APIs and WinRT APIs really address different uses and purposes; they do not overlap as other APIs we’ve compared.

Note: a key difference for any comparison with WinRT APIs is that HTML and native JavaScript APIs are available in the web context whereas WinRT is not. This comparison therefore only applies to pages running in the local context. In the web context you are limited to HTML5/JS APIs.

 

HTML File API and File System API

HTML5 has two emerging standards for file-related APIs: the File API and the File System API.

The File API, a working draft at the time of writing, is oriented around handling of filenames that a user provides in a form, typically for upload purposes. It’s entirely oriented around the workflow of obtaining one or more filenames through <input type=”file”> elements, then asynchronously accessing the contents of those files in various forms (text, binary, array, and URL). It is not intended to be a generic means of accessing files, and provides reading capabilities only. Files, in fact, are represented by a File object type that only surfaces the name, not the path, of the files—the API, in other words, hides those details that are specific to the underlying operating system.

The File System API, also a working draft (and not generally available to apps at this time), provides for more general read/write access to “a sandboxed section of the user’s local file system.” The API provides for folder operations like moving, copying, deleting, and creating files, as well as reading and writing files. The API provides both synchronous and asynchronous forms.

 

WinRT File API

The Windows.Storage API is intended as the means of asynchronous file system access for Windows Store apps. The API is fully aware of app container restrictions, brokering, and restrictions placed on the app by the capabilities (or lack thereof) as declared in the manifest. It provides for reading and writing to arbitrary files (if access is allowed) as well as to app-specific data folders (local, roaming, and temp) and user data libraries (music, pictures, videos, and documents, with the latter having additional requirements).

Unlike the working draft HTML5 File System API, the WinRT API is completely available to app Windows Store apps today. The capabilities also go far beyond the HTML5 specifications. WinRT provides a file picker that allows the user to point to and thus give permission to apps to use any non-sensitive area of the file system. Apps can cache this permission for future access through the Windows.Storage.AccessCache APIs.

WinRT also provides capabilities to perform deep and detailed searches of the file system through file queries (see Windows.Storage.StorageFolder). Furthermore, WinRT is designed to accommodate the needs of online storage systems (e.g. SkyDrive) and local caching of files obtained from those systems.

 

Recommendations

If an app wishes, it can use the HTML5 File API for its intended and specific purpose, that is, for an <input type=”file”> form field and resulting data transfer. It should be noted that using this method, the app will only have the ability to use the methods in the HTML FileReader object to read data from the file; if any other capabilities are needed, the app should collect pathnames directly through the WinRT file picker and use the Windows.Storage API for reading (and/or writing). This is because the paths are otherwise hidden (and not accessible) in the HTML File objects.

The HTML File System APIs, for their part, are not presently available to Windows Store apps at all (they are only available in Google Chrome at present). At such a time that the standard becomes more finalized, it would seem an open question as to how the API would operate. Generally speaking, since the File System API is designed to provide access to an app-specific section of the file system, as is already provided by Windows.Storage.ApplicationData, making such an API available to Windows Store apps would seem both redundant and pointless, since WinRT already provides a much richer set of features.


In contrast to other posts in this series of HTML5/WinRT comparisons, this one on web sockets is relatively short. I haven’t worked too much with either set of APIs, so only have a few details to write up.

Standard WebSockets, as they’re defined in the W3C/HTML5 API, are entirely supported for Windows Store apps. However, they support only a transaction-based UDP model like DatagramSocket and only text content. The MessageWebSocket in WinRT supports both text and binary, plus you can use the StreamWebSocket for a streaming TCP model as well. The WinRT APIs also emit more detailed error information.

For all these reasons, we generally recommend using the WinRT APIs for web sockets over the HTML5 APIs.

 


Processing XML data is a common activity for web applications and will likely be employed by many Windows Store apps. For apps written in HTML, CSS, and JavaScript, two APIs are available: the XML DOM API represented by the DOMParser object, and the WinRT API in the Windows.Data.Xml.Dom namespace. This post will make a brief comparison between the two.

Note: one key difference for any comparison with WinRT APIs is that HTML and native JavaScript APIs are available in the web context whereas WinRT is not. This comparison therefore only applies to pages running in the local context. In the web context you must use the HTML5/JS APIs.

It’s also helpful to note that overlaps such as these exist (a) because of the local and web contexts, and (b) to provide the capability to Windows Store apps written in other languages where an intrinsic API is not available.

 

XML DOM API

The XML DOM API is already familiar to JavaScript developers, because the HTML DOM API is really just a specific flavor of the XML API. Functions like getElementById, for example, which every JavaScript developer can probably type in their sleep, is shared between both. The XML DOM API is compliant with the HTML5 Web DOM Core spec.

This API is the most extensive where manipulating XML is concerned. Converting XML text to an XML document is done with a simple call to DOMParser.parse; the API is then available on that document object.

As far as drawbacks are concerned, this API is synchronous and entirely based on having the XML as a string. No provision is made for loading the XML from another source. It also does not support XSLT or XPath.

For details on the implementation of DOMParser for Windows Store apps, the documentation is here.

 

WinRT API: Windows.Data.Xml.Dom

Generally speaking, the API available for an XML document in WinRT, Windows.Data.Xml.Dom, is very similar to the XML DOM API. It is compliant with the W3C DOM Core specification.

In its design, many method names match the DOM versions, such as getElementById. That said, the WinRT API isn’t quite as extensive as the DOM API. Compare, for example, the XML DOM’s API on an element to IXmlElement. Similarly, IXmlText in WinRT has a single method, SplitText, while the XML DOM Text object has quite a few more.

The WinRT API provides other functionality, however. It provides XSLT and XPath support, and can, in addition to synchronous parsing of in-memory XML, asynchronously load XML from a file or remote URL. An XML document object obtained from WinRT can also be used with other WinRT APIs.

 

Recommendations

In the end, the specific differences between these APIs will determine what’s best for you:

  1. By default, use XML DOM API (DOMParser) in an app. It is the web-friendliest API, works in the web compartment, and covers the majority of web scenarios.
  2. Use XML WinRT API where XML DOM API is insufficient. It is necessary if you need to use XSLT or XPath, need to pass XML objects to WinRT APIs, require async loading of XML from a file or remote URL, or if compliance with the W3C DOM Core spec is required.

 


HTML5 includes facilities for client-side “web storage” from within JavaScript as a great improvement over cookies. For reference, see http://en.wikipedia.org/wiki/DOM_storage for an overview, http://www.w3.org/TR/webstorage/ for the spec. In Windows Store apps written in HTML/CSS/JavaScript, these features overlap with the application storage APIs in WinRT. In this article I’ll compare and contrast the two.

Note: one key difference for any comparison with WinRT APIs is that HTML and native JavaScript APIs are available in the web context whereas WinRT is not. This comparison therefore only applies to pages running in the local context. In the web context you must use the HTML5/JS APIs.

It’s also helpful to note that overlaps such as these exist (a) because of the local and web contexts, and (b) to provide the capability to Windows Store apps written in other languages where an intrinsic API is not available.

 

In Web Storage, there is local and session storage that differ in scope and lifetime. Local storage is per-domain and persists after the browser is closed. Session storage is per-page/per-window and is cleaned up when the window is closed. If you have multiple windows open with the same site, the benefit here is that session storage is kept separate.

The storage itself is an associative array of strings at present; there is a proposal spec for structured data.

Two such associative arrays are made available in JavaScript: localStorage and sessionStorage. You can create any property in them you want, and retrieve them as you want (checking for existence first, of course):

if (sessionStorage.insurance) { … }

if (!localStorage.pageLoadCount)
localStorage.pageLoadCount = 0;

localStorage.pageLoadCount += 1;
document.getElementById(‘count’).textContent = localStorage.pageLoadCount;

The WinRT APIs are available through the Windows.Storage.ApplicationData class, which gives you access to StorageFolder objects for Local, Temp, and Roaming areas of AppData along with localSettings and roamingSettings (containers for key-value pairs including sub-containers). The Application object in the Windows Library for JavaScript (WinJS) also contains a local, temp, and roaming objectsto simplify working with the ApplicationData APIs (it also has a sessionState object into which you can write values, but these are only restored if an app is restarted after being terminated by Windows when freeing up memory). For details, see Chapter 8 of my book (as well as sections of Chapter 3).

Comparing the APIs:

  • HTML5 sessionStorage (per window) in browsers is effectively the same as local variables in an app, because typically you use a single-page navigation model (with DOM replacement) to preserve the script context across pages. From an app’s point of view, then, In other words, sessionStorage is just a global array that had an automatic new done for it. That’s all.
  • WinRT local and HTML5 web local storage both use persistent storage that is available to the app across instances, that is, if the app runs and writes to local storage, is then closed by the user, then restarted, the local storage values are persistent.
  • HTML5 web storage has only a simple array model with strings. WinRT is much richer, with type-specific settings, hierarchical containers, composite settings (groups of settings that act as a single unit), and also supports unstructured (binary) data in arbitrary files. You’d have to encode binary data into text for web storage.
  • Web storage works on a synchronous model; WinRT is synchronous for settings, asynchronous for files.
  • WinRT and HTML5 storage are both kept in the user’s AppDatapackages<package> folder and is automatically cleaned up when the app is uninstalled.
  • WinRT supports automatic roaming through the RoamingSettings container and Roaming folder (up to 100K total data); HTML5 web storage is entirely local.
  • WinRT supports a temp folder that can be cleaned out with the Disk Cleanup tool. This makes a great place for caching data that can be restored at another time.

 

For small bits of data, an app might use HTML storage for the sake of simplicity if you’re familiar with the API. However, it means having a different (and UI-thread blocking) programming model from the roaming settings and a lack of unstructured data (file) capability. One also has to watch out for the fact that all the data are a strings and will be handled like strings. So for the code that does the launch count as above (which is pulled from the W3C spec), when you reload the pageLoadCount at a later time, the data type is actually a string, and adding 1 doesn’t increment the value, it appends “1” to the string. You have to do a parseInt on the value from localStorage to get a numerical value again.

The other comparison to make between these methods is to review the storage limits imposed by each mechanism, as summarized in the following table. For completeness, we’ve also included other storage HTML5 mechanisms like IndexedDB and AppCache as these also employ the app’s AppData area on the file system.

Storage Method Limit (up to file system capacity)
Web storage (local) 10MB
Web storage (session) 10MB
WinRT localSettings
(structured settings)
  • 8K per individual setting (1)
  • 64K per composite setting (1)
  • No limit on overall settings
WinRT localFolder
(unstructured files)
None
WinRT roamingSettings
(structured settings)
  • 8K per individual setting (1)
  • 64K per composite setting (1)
  • No limit on overall settings. Exception:   sync engine may limit total amount of roamingSettings and roamingFolder   data that will roam (2)
WinRT roamingFolder
(unstructured files)
No storage limit. However, the sync engine limits total the   amount of roamingSettings and roamingFolder data that will   actually roam. (2)
WinRT tempFolder
(unstructured files)
None (3)
Cookies 4K per cookie; no limit on total cookies
History None
Temporary Internet Files None (4)
IndexedDB 250MB per app, 12.5% of overall storage or 1TB, whichever is   less.
HTML5 Appcache None (4)

 

(1)    These are arbitrary limits and may change.

(2)    The default sync engine presently imposes a 100K limit (see the roamingStorageQuota property); if the combined contents of the roamingSettings and roamingFolder exceed that limit, the settings will still only be stored locally and no data is roamed. Again, this is a limit of the sync engine: the WinRT APIs themselves don’t impose limits. Different sync engines can behave differently.

(3)    Files created in the tempFolder are subject to deletion by Windows’ Disk Cleanup utility.

(4)    Current design with Windows Store apps does not impose a storage limit for AppCache (along with any other cached files from the web); IE will continue to enforce user- and system-defined limits.

 

In the end, if you’re writing new code, I recommend using the WinRT APIs to have a consistent async programming model across local, roaming, and temp data. If you have existing code that uses HTML5 web storage, it will continue to work subject to the limits outlined above.


HTML5 contains a geolocation API to find the user’s location, something that used to be accomplished by analyzing IP addresses. As shown in the specification, http://www.w3.org/TR/geolocation-API/, the API itself is fairly simple. For Windows Store apps written in HTML/CSS/JavaScript, then, there is an overlap with the Windows.Devices.Geolocation API in WinRT. So which one should you use?

Note: one key difference for any comparison with WinRT APIs is that HTML5 and native JavaScript APIs are available in the web context whereas WinRT is not. This comparison therefore only applies to pages running in the local context; in the web context you’ll want to use the HTML5/JS APIs.

It’s also helpful to note that overlaps such as these exist (a) because of the local and web contexts, and (b) to provide the capability to Windows Store apps written in other languages where an intrinsic API is not available.

With that, let’s look at both APIs in turn.

Geolocation in HTML5

HTML5′s geolocation is available through the navigator.gelocation object in JavaScript. With this you can obtain a single reading, which is useful to present location-relevant content for a visitor, and also watch the position for ongoing readings.

A single reading is retrieved through the navigator.geolocation.getCurrentPosition method, to which you pass a function that receives a position object:

navigator.geolocation.getCurrentPosition(function(position) {
     var lat = position.coords.latitude;
     var long = position.coords.longitude;
     …
});

Additional parameters to getCurrentPosition include an error function and an object containing the options enableHighAccuracy (bool), maximumAge (maximum age of cached data in milliseconds), and timeout (in milliseconds).

Ongoing (asynchronous) readings are taken by passing a callback function to navigator.geolocation.watchPosition that takes the same parameters as getCurrentPosition. watchPosition returns an ID for the operation which can be passed to clearWatch to end the readings.

The timeout option value is important as it determines the maximum length of time that can elapse between a call to getCurrentPosition and watchPosition and a callback with a position value. If that timeout is exceeded, the error function is called with a TIMEOUT error. Other error conditions are PERMISSION_DENIED (see below) and POSITION_UNAVAILABLE (no geolocation capability is available, or there’s an error in determining the location). Note that a watch will remain in place when an error occurs.

The position object passed to the callback in both cases contains a timestamp member as well as a coords object. The latter contains latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, and speed (all doubles). Complete details are, of course, in the specification.

Privacy is a concern with geolocation. The W3C specification places the responsibility for insuring privacy on the agent that implements the API. Internet Explorer, for instance, pops up an alert to the user asking their permission on behalf of sites that use the API. This can be seen with the IE9 TestDrive site’s Geolocation page, http://ie.microsoft.com/testdrive/HTML5/Geolocation/Default.html.

If the user disallows geolocation, the error function given to getCurrentPosition or watchPosition is called with a PERMISSION_DENIED error.

Note that when using HTML5 geolocation in a Windows Store app (including any web content in iframes and pages within navigation domains), it is necessary to declare the Location capability in the app manifest. Without this declaration, the APIs will fail with PERMISSION_DENIED errors.

Note also that if a Windows Store app navigates to any additional websites (e.g. uses navigation domains or includes content in iframes) that utilize geolocation, it must also include the domain in the ApplicationContentUris list.

Geolocation in WinRT

In WinRT, geolocation is provided through the Windows.Devices.Geolocation API. In WinRT you create (with new) a Windows.Devices.Geolocation.Geolocator object, which you then configure with various properties if desired: desiredAccuracy (default or high), movementThreshold (double), and reportInterval (double).

Obtaining a one-time position reading is done through the getGeopositionAsync method that produces a Windows.Devices.Geolocation.Geoposition object. Its properties are civicAddress and coordinate, where the properties of the latter are accuracy, altitude, altitudeAccuracy, heading, latitude, longitude, speed, and timestamp.
var gl = new Windows.Devices.Geolocation.Geolocator();
gl.getGeopositionAsync().then(function (posOp) {
     var position = posOp.getResults();
     var lat = position.coordinate.latitude;
     var long = position.coordinate.longitude;
     …
});

A variation of getPositionAsync lets you specify maximumAge and timeout parameters.

You can also assign functions to the positionChanged and statusChanged members of the Geolocator object for ongoing readings. positionChanged will be called within the reportInterval setting, and statusChanged is called when the device status changes between the following states:

  • ready: location data is available.
  • initializing: the location provider is initializing (e.g. a GPS receiver is still acquiring satellites).
  • noData: no location data is available from any location provider (like POSITION_UNAVAILABLE in HTML5).
  • disabled: the application doesn’t have permission to access location (like PERMISSION_DENIED in HTML5).
  • notInitialized: an operation to retrieve location has not yet been initialized (i.e. the app has not called getGeopositionAsync or registered for the positionChanged event).
  • notAvailable: the Windows Sensor and Location Platform is not available on this version of Windows.

Where privacy is concerned, this API will fail unless the app has declared the Location capability in its manifest. At runtime, Windows will also prompt the user for consent.

API Differences and Distinctions

As with other overlapping parts of WinRT and HTML5/JavaScript, the Geolocation APIs in WinRT are primarily there for apps written in C++ and .NET languages, where no other option is available. For written in HTML/CSS/JS, the two alternatives are more or less equal, with a few distinctions:

  • Geolocation options: The movementThreshold option is unique to WinRT, which is used for system power management and which allows an app to only receive readings there has been enough of a change. This is helpful for geo-fencing apps that only want to update themselves when the user has moved far enough away from a given point. To do the same with the HTML5 API requires more frequent location polling and calculating distance to filter out events.
  • Position information: When address information is supported by a location provider, WinRT provides for surfacing that data through the civicAddress property (and its individual sub-propeities).

Thus, developers with existing HTML5 geolocation code, or those who want to maintain as much platform-neutral code in their apps as possible, will likely use the HTML5 API. On the other hand, the convenience of movementThreshold and its positive effect on power management is a significant benefit of the WinRT API.


Mozilla has introduced two simple methods to the DOM API for encrypting and decrypting base64 values. These are btoa, which converts binary (or string) data to a base64 ASCII-encoded string, and atob, which will do the opposite.  These APIs are being adopted by Internet Explorer 10 and are thus also available to Metro style apps written in JavaScript.

The basic functionality of these methods overlaps with the WinRT APIs found in the Windows.Security.Cryptography.CryptographicBuffer class, with the results being entirely interchangeable as you would expect. This means that base64-encrypted data created in one app using the DOM APIs can be passed to and successfully decrypted by an app using the WinRT APIs, and vice versa. This is shown in the code example below.

The difference between the two APIs thus rests in their structure and scope. As seen in the code example below, the btoa and atob methods are the simplest and most concise, but they work only with binary or basic string data, and cannot handle raw Unicode. As Mozilla’s btoa docs point out, Unicode strings will cause an exception in both methods and must be worked around with additional code. These methods are also focused solely on base64.

The WinRT APIs, on the other hand, are a little more complicated for basic usage but are much more flexible overall. For one, they handle Unicode strings just fine, with support for UTF-8, UTF-16LE, and UTF-16BE. Second, these APIs work with an intermediary buffer that can be created from a string, a byte array, or filled with random data. Finally, such buffers can then be encoded to base64 or hexadecimal, or copied to a separate byte array.

In short, the two can be used interchangeably for basic base64 operations, but developers might find it more consistent to use WinRT for other kinds of encoding.

Code example

This example simply shows the equivalence of the APIs and their cross compatibility. Create a new JavaScript project using the Blank template and drop in the code below. When you run the app and press the Run Test button, you’ll see the original string, the base64 encryption, and the decrypted values, using WinRT exclusively, using HTML APIs exclusively, then intermixing the two. As you’ll see, the results are entirely as expected.

HTML (body of default.html)

<body>
     <h1>Encryption Comparison</h1>
     <button<span >id="btnRun">Run Test</button>
     <p>Input Text: <spanid="txtInput">A text string for encyption</span></p>
     <p>Encrypted String (WinRT): <spanid="txtEncryptedWinRT"></span></p>
     <p>Decrypted String (WinRT): <spanid="txtDecryptedWinRT"></span></p>
     <p>Encrypted String (btoa): <spanid="txtEncryptedJS"></span></p>
     <p>Decrypted String (atob): <spanid="txtDecryptedJS"></span></p>
     <p>Decrypted String (WinRT using btoa output): <spanid="txtDecryptedCross1"></span></p>
     <p>Decrypted String (atob using WinRT output): <spanid="txtDecryptedCross2"></span></p>
</body>

 

JavaScript (entire contents of default.js)

(function () {
    "use strict";
    var app = WinJS.Application;
    app.onactivated = function (e) {
        if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
            WinJS.UI.processAll();
            var btn = btnRun;
            btnRun.addEventListener("click", runTest);
        }
    }


    function runTest() {
        var wsc = Windows.Security.Cryptography;
        var input = document.getElementById("txtInput").innerText;
        var buffer1a = wsc.CryptographicBuffer.convertStringToBinary(input,
        wsc.BinaryStringEncoding.utf8);
        var encrypt1 = wsc.CryptographicBuffer.encodeToBase64String(buffer1a);
        document.getElementById("txtEncryptedWinRT").innerText = encrypt1;
        var buffer1b = wsc.CryptographicBuffer.decodeFromBase64String(encrypt1);
        document.getElementById("txtDecryptedWinRT").innerText =
        wsc.CryptographicBuffer.convertBinaryToString(wsc.BinaryStringEncoding.utf8, buffer1b);
        var encrypt2 = btoa(input);
        document.getElementById("txtEncryptedJS").innerText = encrypt2.toString();
        document.getElementById("txtDecryptedJS").innerText = atob(encrypt2);
        document.getElementById("txtDecryptedCross1").innerText = wsc.CryptographicBuffer.convertBinaryToString(wsc.BinaryStringEncoding.utf8,
        wsc.CryptographicBuffer.decodeFromBase64String(encrypt2));
        document.getElementById("txtDecryptedCross2").innerText = atob(encrypt1);
    }


    app.start();
})();