Thursday, December 14, 2017

WebAssembly – Emscripten SIDE_MODULE


In my last blog post, An Introduction to WebAssembly, I showed you some of the basics of working with a WebAssembly module by using Emscripten.

This article is the result of some research and experiments to see if it’s possible to build a WebAssembly module using Emscripten but to not have any of the plumbing code.

For example, if we were to build the following C file using the following command line, the result would be an HTML file that is 101 KB, a JS file that is 80.2 KB, and a wasm file that is 9.4 KB!

#include <stdio.h>
#include "../emscripten/emscripten.h"

int main() { return 0; }

int EMSCRIPTEN_KEEPALIVE add(int x, int y) { return x + y; }

emcc test.c -s WASM=1 -s NO_EXIT_RUNTIME=1 -O1 -o hello.html


Having all of that plumbing is very convenient because it lets you start playing around with WebAssembly modules right away but what if we want just the bare minimum and will handle the HTML and JavaScript ourselves?

Fortunately, there is a way to tell Emscripten to output just the bare bones wasm file.

Let's first strip the C file down to just the bare minimum. In this case, we only want the add method:

int add(int x, int y) { return x + y; }

If we use the following command line, we will get just the wasm file and it’s only 202 bytes!

emcc test.c -s WASM=1 -s SIDE_MODULE=1 -O1 -o test.wasm

The SIDE_MODULE flag tells Emscripten to compile only our methods and nothing else which means you will also not have access to things like printf or malloc.

If not specified, the default optimization flag used is -O0 (capital letter o and the number 0) but that results in the following error being thrown when you try to load the module:

LinkError: import object field 'DYNAMICTOP_PTR' is not a Number

Adding any optimization flag other than -O0 will fix the issue so we went with -O1 (capital letter o and the number 1) for this example.

One thing to note, however, is that the O appears to be case sensitive. The various optimization flags that are available can be found here: https://kripken.github.io/emscripten-site/docs/optimizing/Optimizing-Code.html

We also need to specify the name of the output file in the command line because, if we don't, Emscripten will output the file with the name a.out.wasm.


Because we've decided not to use Emscripten's plumbing code, we need to write our own HTML and JavaScript. The following is some example HTML and JavaScript to load in the module:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<input type="button" value="test" onclick="javascript:OnClickTest();" />

<script type="text/javascript">
var gModule = null;

var importObject = {
'env': {
'memoryBase': 0,
'tableBase': 0,
'memory': new WebAssembly.Memory({initial: 256}),
'table': new WebAssembly.Table({initial: 0, element: 'anyfunc'})
}
};

fetch('test.wasm').then(response =>
response.arrayBuffer()
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
gModule = results.instance; // Hold onto the module's instance so that we can reuse it
});

function OnClickTest(){
alert(gModule.exports._add(1, 2));
}
</script>
</body>
</html>


One thing that you may have noticed that is different with our call to the C method, as compared to what we did in the previous blog post, is that we're not using Module.ccall or Module.cwrap. Those are Emscripten helper methods. Here, we're calling the C method directly.

Something else to be aware of here is that your JavaScript will need to include an underscore character before the method name. For example, in our case, our method is called add. When you call the add method in JavaScript you would use _add(1, 2); rather than add(1, 2);

Although this approach might not be a solution that will work in every situation, given that you don't have access to things like malloc, it might be a useful way of creating a helper library if you're doing things like number crunching and don't need all of the overhead that comes with Emscripten's plumbing.

Friday, November 10, 2017

An Introduction to WebAssembly


The concept behind WebAssembly isn't new and is based on work that was pioneered by Mozilla (asm.js) and Google (Native Client – NaCl and Portable Native Client – PNaCl).

One of WebAssembly's main goals is parity with asm.js so I'll give you a little background on that before we start digging into WebAssembly.

When I first heard of asm.js a few years ago I was excited. The ability to write code in C/C++ and have it compiled down into a special form of JavaScript that the browser could then run at near native speeds if it supported asm.js.

You don't typically write asm.js code by hand, it's usually created by a compiler.

The code starts off with the asm pragma statement ("use asm";) and then typing hints are included that allow JavaScript interpreters, that support asm.js, to know that they can use low-level CPU operations rather than the more expensive JavaScript operations.

For example, a | 0 is used to hint that the variable 'a' is a 32-bit integer. This works because a bitwise operation of zero doesn't change the original value so there are no side effects to doing this. Because there are no side effects to this, it can be used wherever it's required in the code to hint the type for either the return value or the parameters passed into a method as in the following example:

function AsmModule() {
"use asm";
return {
add: function(a, b) {
a = a | 0;
b = b | 0;
return (a + b) | 0;
}
}
}

The nice thing about asm.js is that, even if the browser doesn't support it, it would still run and you would get identical results since the code is still valid JavaScript. The only difference is that it would be slower compared to if the browser did support asm.js.

Being able to write code in C/C++ and have it compiled into a special form of JavaScript that is significantly faster than standard JavaScript is pretty cool but asm.js did have some disadvantages:
  • The extra type hints could result in very large asm.js files
  • Things still need to be parsed so a large file could be expensive on lower end devices like phones
  • asm.js needs to be valid JavaScript so adding new features is complex and would affect the JavaScript language itself as well


WebAssembly

To solve the issues of asm.js, the major browser venders got together and started working on a W3C standard and an MVP of WebAssembly that is already live in most browsers! The browsers that currently support WebAssembly are:

Firefox, Chrome, Opera, Edge 16, Safari 11, iOS Safari 11, Android browsers 56, Chrome for Android, and Firefox for Android!

It can be turned on in Edge 15 by turning on the browser's Experimental JavaScript Features flag.

WebAssembly, or wasm for short, is intended to be a portable bytecode that will be efficient for browsers to download and load. The bytecode is transmitted in a binary format and, due to how the modules are structured, things can be compiled by the browser in parallel speeding things up even further.

Once the binary has been compiled into executable machine code, the module is stateless and as a result can be explicitly cashed in IndexedDB or even shared between windows and workers via postMessage calls.

WebAssembly is currently an MVP so not everything is there yet but it will eventually include both a binary notation, that compilers will produce, and a corresponding text notation for display in debuggers or development environments.


Emscripten

For the examples that follow, I'll be using Emscripten to compile C code into a wasm module. You can download Emscripten from the following location: https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html

On Windows it was simply a matter of unzipping the contents and then running some command line arguments.

I was getting errors when I first tried running a wasm module and it turned out that the version of Emscripten that came with the zip files wasn't recent enough.

You'll need git on your system in order to have the command line arguments build the latest version of the Emscripten compiler for you. The following command line downloaded git for me:

emsdk install git-1.9.4

Once you have the latest version of git on your system, run the command lines indicated on the download page to update, install, and activate Emscripten.


Hello World

For the examples that follow, I simply create a text file in named test.c and use notepad to adjust the text (you don't need an IDE for the examples I give you here).

As with any new programming technology, it's almost a requirement to start off with a hello world program so let's create a very basic hello world app using C. The following will simply write a string to the command line as soon as the module gets loaded:

#include <stdio.h>

int main()
{
printf("Hello World from C\n");
return 0;
}

To compile the code into a WebAssembly module, we need to run the following command line:

emcc test.c -s WASM=1 -o hello.html

-s WASM=1 specifies that we want a wasm module output

The nice thing about this tool is that it gives you all the JavaScript 'glue' needed allowing you to play with WebAssembly modules right away. As you get more experienced with the technology, you can customize it.

If you open the generated hello.html file in a browser, you'll see the Hello World from C text displayed in the textbox.


For the rest of the examples, I'm going to adjust the command line to generate a more minimal html template just to make things easier (less to scroll through when we edit the html file).

I've copied the emscripten.h and shell_minimal.html files into folders in the root directory where I'm creating my code files. For each code example, I've created a subfolder for the .c file I create and for the generated files just to keep each example separate which is why you'll see a relative path stepping back a folder in the following examples.

You can find the shell_minimal.html file in the emscripten src folder.

You can find the emscripten.h file in the emscripten system\include\emscripten folder.


Calling into a module from JavaScript

Let's take our code a step further and build a function that you can call from JavaScript.

First, let's add a function to our code called TestFunction that accepts an integer:

#include <stdio.h>
#include "../emscripten/emscripten.h"

int main()
{
printf("Hello World from C\n");
return 0;
}

void EMSCRIPTEN_KEEPALIVE TestFunction(int iVal) {
printf("TestFunction called...value passed in was: %i\n", iVal);
}

The EMSCRIPTEN_KEEPALIVE declaration adds our functions to the exported functions list so that they're seen by the JavaScript code.

Because we have a function we want to call in the WebAssembly, we don't want the runtime to shut down after the main method finishes executing so we're also going to include the NO_EXIT_RUNTIME parameter.

Run the following to generate the new files:

emcc test.c -s WASM=1 -o hello2.html --shell-file ../html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1

If you opened the html file in a browser at this point, you won't see anything other than the Hello World output because the JavaScript doesn't yet have the code to call TestFunction.

Open up the generated hello2.html file using a tool like notepad, scroll down to just before the opening Script tag, and add the following HTML:

<input type="text" id="txtValue" />
<input type="button" value="Pass Value" onclick="PassValue();" />

Scroll further down the html file and add the following just before the closing script tag (after the window.onerror method's code):

function PassValue(){
Module.ccall('TestFunction', // name of C function
null, //return type
['number'],//argument types
[ parseInt(document.getElementById("txtValue").value,10) ]);
}

Save the html file and then open it up in a browser.

If you type a number into the textbox next to the Pass Value button and then press the button you should see that value echoed back into the textbox.


In the example above, we used the ccall method which calls the module right away.

Another approach is that we can use the cwrap method to create a function pointer that can then be used multiple times. The JavaScript would look like this:

var fncTestFunction = Module.cwrap('TestFunction', null, ['number']);
fncTestFunction(1); //passing in an integer directly for this test
fncTestFunction(2); //passing in an integer directly for this test


Calling into JavaScript from a module using macros

Being able to talk to the WebAssembly from JavaScript is nice but what if you want to talk to JavaScript from the WebAssembly?

There are different ways that this can be achieved.

The simplest way is through macros like emscripten_run_script() or EM_ASM() which basically trigger a JavaScript eval statement.

Macros are not my recommended approach for production code especially if you're dealing with user supplied data but they could come in handy if you needed to do some quick debugging.

Note: You need to use single quotes in the macros. Double quotes will cause a syntax error that is not detected by the compiler.

To test out the EM_ASM macro, let's adjust TestFunction to simply call into JavaScript and display an alert:

#include <stdio.h>
#include "../emscripten/emscripten.h"

int main()
{
printf("Hello World from C\n");
return 0;
}

void EMSCRIPTEN_KEEPALIVE TestFunction(int iVal) {
printf("TestFunction called...value passed in was: %i\n", iVal);

EM_ASM(
alert('Test call from C to JS');
throw 'all done';
);
}

Run the following to generate the new files:

emcc test.c -s WASM=1 -o hello3.html --shell-file ../html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1

Open up the hello3.html file that was generated, scroll down to just before the opening Script tag, and add the following HTML:

<input type="text" id="txtValue" />
<input type="button" value="Pass Value" onclick="PassValue();" />

Scroll further down the html file and add the following just before the closing script tag (after the window.onerror method's code):

function PassValue(){
Module.ccall('TestFunction', // name of C function
null, //return type
['number'], //argument types
[ parseInt(document.getElementById("txtValue").value,10) ]);
}

Save the html file and then open it up in a browser. If you type a number into the textbox next to the Pass Value button and then press the button you will see that value echoed back into the textbox but you'll also see an alert displayed.


Calling into JavaScript from a module using function pointers

In the previous example we used a macro to call into the JavaScript code but that's generally taboo, especially if you have user supplied data, since it uses eval in the background.

The better approach, in my opinion, is to pass a function pointer to the WebAssembly module and have the C code call into that.

In the JavaScript code, you can use Runtime.addFunction to return an integer value that represents a function pointer. You can then pass that integer to the C code which can be used as a function pointer.

When using Runtime.addFunction, there is a backing array where these functions are stored. The array size must be explicitly set, which can be done via a compile-time setting: RESERVED_FUNCTION_POINTERS.

Let's adjust our code by getting rid of TestFunction and adding in a new function called CallFunctionPointer that simply calls the function pointer that was specified:

#include <stdio.h>
#include "../emscripten/emscripten.h"

int main(){
printf("Hello World from C\n");
return 0;
}

void EMSCRIPTEN_KEEPALIVE CallFunctionPointer(void(*f)(void)){
(*f)();
}

Run the following to generate the new files and indicate that we will have 1 function pointer:

emcc test.c -s WASM=1 -o hello4.html --shell-file ../html_template/shell_minimal.html -s NO_EXIT_RUNTIME=1 -s RESERVED_FUNCTION_POINTERS=1

Open up the hello4.html file that was generated, scroll down to just before the opening Script tag, and add the following HTML:

<input type="button" value="Test Pointer" onclick="TestPointer();" />

Scroll further down the html file and add the following just before the closing script tag (after the window.onerror method's code):

function TestPointer(){
// Create an anonymous function that will be called by the C code
var pointer = Runtime.addFunction(function() { alert('I was called from C!'); });

// Call the C code passing in the pointer reference
Module.ccall('CallFunctionPointer', null, ['number'], [pointer]);

// Remove the function pointer from the array
Runtime.removeFunction(pointer);
}

Save the html file and then open it up in a browser. If you press the Test Pointer button you will see an alert displayed.


Current Limitations

Like with JavaScript, WebAssembly is specified to be run in a safe, sandboxed execution environment which means it will enforce the browser's same-origin and permission policies too.

WebAssembly is currently an MVP which means there are a number of things still missing. For example, at the moment there is no direct DOM access from the assembly which means you will have to call into the JavaScript code if you need to update the UI.


Future Improvements

The browser makers are pushing ahead with this technology (for example, Google's Native Client has been depreciated in favor of this) so I expect to see improvements start showing up.

The following are some of the improvements that browser makers have identified:
  • Faster function calls between JavaScript and WebAssembly
  • You won't notice this overhead if you're passing a single large task off to the WebAssembly module. But, if you have lots of back-and-forth between the module and JavaScript, then this overhead becomes noticeable apparently.
  • Faster load times
  • The browser makers had to make trade-offs between fast load times and optimized code so there are more improvements that can be made here.
  • Working directly with the DOM
  • Exception handling
  • Better tooling support for things like debugging
  • Garbage collection which will make it easier for some languages like C# to target WebAssembly too


Tuesday, November 12, 2013

HTML5 IndexedDB – DZone Refcardz


IndexedDB is an exciting browser-based database technology capable of holding large amounts of structured data and conducting high-performance searches using indexes.

DZone.com gave me the opportunity to write another article for their Refcardz series and I'm pleased to announce that my article on HTML5 IndexedDB is now available!

The Refcard introduces you to IndexedDB by guiding you through setting up and using an IndexedDB database, and covers advanced usage and known issues.

The article also contains a link to a github project showing IndexedDB in action. Use the code to better understand IndexedDB or even as a jumping off point for your project.

The DZone.com article can be found here: http://refcardz.dzone.com/refcardz/html5-indexeddb

Thursday, April 11, 2013

HTML5 Web Workers – DZone Refcardz


I've recently had the privilege to work with DZone.com and write an article for their Refcardz series about HTML5 Web Workers.

The article combines the information presented in several of my blog posts and also introduces some new information and concepts like transferable objects, inline workers, as well as a link to a sample project.

The DZone.com article can be found here: http://refcardz.dzone.com/refcardz/html5-web-workers


The following are the blog posts related to HTML5 Web Workers...

Tuesday, November 13, 2012

HTML5 - WebSocket API


Before we start digging into the HTML5 WebSocket API, we need a bit of history to understand why this technology is even needed...

Normally, when you visit a web page with your browser, an HTTP request is sent to the server asking for the page. The server then responds with a result.

Depending on the type of information requested, stock prices for example, the information might be stale by the time you receive the response from the server.

So what do you do?

One common approach has been to have the web page poll the server to check for new information at a set interval as illustrated in the image below:


(click to view the image full size)

In the image above, polling is done every 50 milliseconds.

Polling the server unnecessarily has problems...
  • You're wasting the server's resources as it has to handle your request even if it has no data for you. Depending on how many web pages are checking back for new information, you can actually reduce the scalability of your server.
  • You're wasting network bandwidth as cookies and all kinds of header information has to be passed to the server and back with every request and response


Workarounds like long-polling have been tried where the client makes a request but, unlike with normal polling, the server doesn't return an empty response if it doesn't have any information. Instead, the server holds onto the request until it has some information to return.

When the server has new information, it sends it to the client, along with a complete response.

The client would then immediately make a new request to wait for more information.

Long-polling is basically just polling if the data changes frequently because there will be a bunch of connections made rather than one single connection.


Another workaround approach was to use streaming but some proxy servers and firewalls would actually buffer the messages which slows down the responses.

The result was that apps would either fall back to long-polling, if buffering was detected, or they would need to send the messages using TLS (SSL) but that adds even more overhead to the process because now the server and client also have to encrypt and decrypt the messages.


Workarounds to try and achieve full-duplex communication were also attempted by using two connections: one for the client to talk to the server and one for the server to talk to the client but that can be difficult to set up and coordinate.


Introducing Web Sockets

Web Sockets give you full-duplex functionality with a single connection between the client and server.

Full-duplex allows messages to be passed in both directions at the same time.

HTTP is half-duplex where data can only be passed in one direction at a time. For example, the server cannot respond to a client request until it has finished receiving the request.

A Web Socket connection can also remain open for the life of the session.

Based on tests run by Kaazing Corp, who have been closely involved in the specification process, depending on the amount of HTTP headers, Web Sockets have been tested to provide a 500:1, sometimes even a 1000:1 reduction in unnecessary HTTP header traffic and a 3:1 reduction in latency.

The other nice thing about Web Sockets is that they operate over port 80/443 so there are no firewall or proxy issues to contend with!


To open up a Web Socket, a client starts off with an HTTP handshake asking the server for an upgrade to the Web Socket protocol.

Once the connection is established, messages can be sent back and forth with a 0x00 byte to start the message and a 0xFF byte to end the message.

There are only 2 bytes of overhead compared to the large amount of header information that would usually exist with an HTTP request and response.


With the following example illustration comparing polling with Web Sockets, rather than the client constantly having to ask the server if there are any changes, the client no longer has to ask. The server simply tells the client when it has new information.


(click to view the image full size)


WebSocket object

The following is the current HTML5 WebSocket specification (from the September 20, 2012 W3C Candidate Recommendation):

[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols)]
interface WebSocket : EventTarget {
readonly attribute DOMString url;

// ready state
const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;
readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;

// networking
attribute EventHandler onopen;
attribute EventHandler onerror;
attribute EventHandler onclose;
readonly attribute DOMString extensions;
readonly attribute DOMString protocol;
void close([Clamp] optional unsigned short code, optional DOMString reason);

// messaging
attribute EventHandler onmessage;
attribute DOMString binaryType;
void send(DOMString data);
void send(Blob data);
void send(ArrayBuffer data);
void send(ArrayBufferView data);
};


The WebSocket object accepts a url string as the first parameter to the constructor.

The readyState attribute of the WebSocket instance created will hold one of the constants: CONNECTING, OPEN, CLOSING, CLOSED.

The bufferedAmount property holds the number of bytes (UTF-8 text or binary data) that has been queued by the Send() method but has not yet been transmitted to the network.

The byte count does not include the framing overhead or any buffering the operating system or network hardware might do.

There are several event handlers that you can hook into: onopen, onerror, onclose, and onmessage.
  • onopen receives the standard DOM event object
  • onerror...I haven't been able to track down information on what event object the onerror handler receives. In my testing it appears to receive the DOM event object but some sample code on the internet shows a handler accessing a .data property for the error message.
  • onclose receives a CloseEvent object
  • onmessage receives a MessageEvent object

The extensions property is for future use where the server will indicate which extensions, if any, were selected. For now, this is always an empty string.

The protocol property returns the subprotocol selected by the server, if any.

It can be used in conjunction with the array, from the 2nd parameter of the constructor, to perform subprotocol negotiation.

The close method allows you to manually close the Web Socket connection.

It can accept two optional parameters.

If specified, the first parameter must either be 1,000 or in the range of 3,000 to 4,999.

The second parameter is the reason why the close method is being called and has a maximum of 123 bytes.

Note: I haven't been able to get this to work in either Firefox or Chrome. Both seem to ignore the values I'm passing them.

The binaryType property will hold a string with either "blob" or "arraybuffer" for a value.

"blob" is the default value for the binaryType property.

If the binaryType property is set to "blob" then the binary data is returned in Blob form.

If the binaryType property is set to "arraybuffer" then the binary data is returned in ArrayBuffer form.

There are several overloads for the send method available allowing you to send a string, Blob, ArrayBuffer, or ArrayBufferView to the server.


MessageEvent object

The following is the current definition of the MessageEvent object which is found in the HTML5 Web Messaging specification (from the May 1, 2012 W3C Candidate Recommendation):

[Constructor(DOMString type, optional MessageEventInit eventInitDict)]
interface MessageEvent : Event {
readonly attribute any data;
readonly attribute DOMString origin;
readonly attribute DOMString lastEventId;
readonly attribute WindowProxy? source;
readonly attribute MessagePort[]? ports;
};

dictionary MessageEventInit : EventInit {
any data;
DOMString origin;
DOMString lastEventId;
WindowProxy? source;
MessagePort[]? ports;
}

When you receive the MessageEvent object, in your WebSocket's onmessage event handler, the property you will be interested in is the data property.


CloseEvent object

When the Web Socket is closed, the onclose event is triggered and will be passed the CloseEvent object:

[Constructor(DOMString type, optional CloseEventInit eventInitDict)]
interface CloseEvent : Event {
readonly attribute boolean wasClean;
readonly attribute unsigned short code;
readonly attribute DOMString reason;
};

dictionary CloseEventInit : EventInit {
boolean wasClean;
unsigned short code;
DOMString reason;
};

If you call the WebSocket instance's close method without specifying any parameters, the onclose event handler will receive a CloseEvent object containing the following values:
  • wasClean will hold false
  • code will hold 1006
  • reason will be an empty string

For some reason, in my tests using Firefox and Chrome, even if I specify values for the close event parameters, I still end up receiving the default values.


Example JavaScript Code

Before using any technology that might not exist in other browsers you should check to see if the feature exists first.

For Web Sockets, checking to see if the browser supports them is as simple as an if statement check for window.WebSocket

Also, you may want to wrap your Web Socket code in a try/catch statement because the user agent (browser) is expected to throw exceptions if certain conditions are not met.

The following is some very simple JavaScript code showing how to create an HTML5 WebSocket object, how to wire up the events, and how to send a string to the server:

if (window.WebSocket) {
try {
// Create the WebSocket and wire up the event handlers
var wsWebSocket = new WebSocket("ws://echo.websocket.org/");
wsWebSocket.onopen = function (evt) { alert("Connection opened"); }
wsWebSocket.onclose = function (ceCloseEvent) {
alert("Connection closed");
}
wsWebSocket.onerror = function (evt) { alert("we had an error"); }

// The OnMessage event handler is called when we receive data
// from the server

wsWebSocket.onmessage = function (meMessageEvent) {
alert("message from the server: " + meMessageEvent.data);
}

// Send the server a message
wsWebSocket.send("hello from the client");

// You can manually close the WebSocket connection if it's no
// longer needed
// wsWebSocket.close();
} catch (err) { alert("error: " + err.message); }
} else { alert("Sorry. WebSockets are not supported by your browser"); }


In Conclusion

There are several issues to be aware off when working with the HTML5 WebSocket API...
  1. Some browsers won't allow a mixed content environment
    • Can't us a non-secure Web Socket connection (ws://) if the page was loaded with https://
    • Can't use a secure Web Socket connection (wss://) if the page was loaded with http://
  2. Some server errors will be masked with the close code of 1006 and will not specify the actual error in order to prevent a script from being able to distinguish the actual error while probing the network in preparation for an attack. Some of the causes of the 1006 error are:
    • A server whose host name could not be resolved
    • A server to which packets could not successfully be routed
    • A server that refused the connection on the specified port
    • A server that failed to correctly perform a TLS handshake (e.g. the server certificate can't be verified)
    • A server that did not complete the opening handshake (e.g. because it was not a WebSocket server)
    • A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer)
    • A WebSocket server that abruptly closed the connection after successfully completing the opening handshake


Additional Resources

The currently published W3C Candidate Recommendation of the HTML5 WebSocket API specification can be found here: http://www.w3.org/TR/websockets/

The currently published W3C Candidate Recommendation of the HTML5 Web Messaging specification, which contains the definition for the MessageEvent object, can be found here: http://www.w3.org/TR/webmessaging/

The following is a very handy echo server that can be used when testing out the Web Socket technology: ws://echo.websocket.org/

Tuesday, October 30, 2012

Windows 8: Windows Store apps - Privacy Policy


Over the past few articles, we've been talking about creating a Windows Store app. The following are the links to the articles if you're interested:


When I first submitted my app to the Windows Store it failed certification due to the Windows 8 app certification requirement 4.1: http://msdn.microsoft.com/en-us/library/windows/apps/hh694083.aspx

At the time, the 4.1 requirement wasn't entirely clear to me but, after some digging on the internet, I was able determine what was needed.

The good news about the certification requirement documentation is that it appears to be improved over time because section 4.1 is now a bit more clear as to what is needed.


The reason why my app failed certification was because any app that makes a connection to the internet, which our app does, can result in some of your user's personal information making it onto the internet (e.g. the IP address could be used to determine their location).

If you app has the ability to communicate over a network then you need to provide a privacy policy with your app via the Settings charm as well as a link to a web page for use in the Windows App Store gallery.

The privacy policy doesn't have to be legalese but does have to tell the user how their information is used, stored, secured, if it's disclosed with third parties, etc.

Since every app is different, the common recommendation is to go through the Windows Store apps looking at the various privacy policies to come up with one that best fits your app's functionality.


A download of the project (C# and built using Visual Studio Express 2012 for Windows 8) can be found in the following location:
https://github.com/downloads/dovicoapi/DOVICOTimerForWindowsStore/DOVICOTimerForWindowsStore.zip

Friday, September 21, 2012

Windows 8: Windows Store apps - JavaScript passing data to the code containing the WebView control


Over the past few weeks, in my spare time, I've been working on building a Windows Store app that will wrap an HTML web app that I've built.

To use the web app, you enter a token in a textbox on the welcome page and then click the Verify button.

If the token is valid, a URI is given to the user which can then be used for the tracking of one's time using the start/stop timer view in the web app.


The issue that we're going to tackle in this blog post is the following:

When the user clicks the Verify button on the welcome page and a URI is generated, I would like the JavaScript to call the code that holds the WebView control to have the URI saved.

This will save the user the trouble of having to copy the URI, open up the settings flyout, and paste in the new URI.


I know that the JavaScript, of a page loaded in a WebBrowser control, can talk to the C# code when the ObjectForScripting option is turned on but do we have access to a similar feature in a Windows Store app when using a WebView control?


ScriptNotify and AllowedScriptNotifyUris

As it turns out, it is possible for the JavaScript of a page loaded into a WebView control to call into the C# code of the page if you set up a ScriptNotify event.

According to the Microsoft documentation on the ScriptNotify event (http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.webview.scriptnotify), depending on which method you use to display the page in the WebView control, you may or may not have to specify URIs that are allowed to call the event handler.

If you use the WebView's Navigate method then you must specify the list of URIs that are allowed to call the ScriptNotify event handler.

If you use the WebView's NavigateToString method then the list of URIs is not necessary.


I've been simply setting the WebView's 'Source' property with the desired URI so the question is: Do I need to specify the list of URIs or not?

As it turns out, if I don't specify the list of URIs when using the WebView's Source property, the ScriptNotify event does not trigger.

You specify a list of allowed URIs in the following manner:
List<Uri> lstAllowedUris = new List<Uri>();
lstAllowedUris.Add(new Uri("http://apps.dovico.net"));
wvBrowser.AllowedScriptNotifyUris = lstAllowedUris;

Note: The property AllowedScriptNotifyUris almost suggests that you can say one page can make ScriptNotify event handler calls but none of the other pages on the site can.

In reality, based on my testing, even if you specify a URI to a particular page, any page within that domain can call the event handler.

The AllowedScriptNotifyUris property is really a list of allowed domains who's pages are allowed to call the ScriptNotify event handler.


The following is an example of how to wire up a ScriptNotify event handler:
public MainPage()
{
// Only allow the following domain's pages to call our ScriptNotify
// event handler
List<Uri> lstAllowedUris = new List<Uri>();
lstAllowedUris.Add(new Uri("http://apps.dovico.net"));
wvBrowser.AllowedScriptNotifyUris = lstAllowedUris;

// Attach our ScriptNotify event handler
wvBrowser.ScriptNotify += wvBrowser_ScriptNotify;
}

The following is an example of the event handler itself:
void wvBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
// The string received from the JavaScript code can be found
// in e.Value
}


On the JavaScript side of things, the code is similar to what you would write when calling the C# code of a WebBrowser control with the exception that the function you call is 'notify' where with a WebBrowser control you could define your own callback function name.

The following is an example of the JavaScript code that calls the C# code:
// We have a couple of checks to make sure the 'external'
// object and 'notify' method exist before we try using them
// because our project is a web application and might not be
// running in a WebView control (the checks prevent
// JavaScript errors if the method doesn't exist)
if ((typeof (window.external) !== "undefined") &&
(typeof (window.external.notify) !== "undefined"))
{
window.external.notify(sURI);
}



In Conclusion

Even though the JavaScript is only capable of passing a string to the ScriptNotify event handler, it is highly recommended that you verify the string is in the expected format before trying to use it even if the string came from a source you included in the list of allowed URIs.


Additional Resources

If you are interested in details on how to implement a Settings flyout, especially if you are using a WebView control, I have a previous article that might be of interest: Windows 8: Windows Store apps and the WebView control (we discussed how to display a Settings flyout and focused mostly around making the WebView control play nice with the flyout).

If you are interested in RoamingSettings and the DataChanged event, the following article might also be of interest: Windows 8: Windows Store apps - RoamingSettings and the DataChanged event


A download of the project (C# and built using Visual Studio Express 2012 for Windows 8) can be found in the following location:
https://github.com/downloads/dovicoapi/DOVICOTimerForWindowsStore/DOVICOTimerForWindowsStore.zip