Native Client

Progress Events

There are five types of events that developers can respond upon in Native Client: progress, message, view change, focus, and input events (each described in the glossary below). This chapter describes how to monitor progress events (events that occur during the loading and execution of a Native Client module). This chapter assumes you are familiar with the material presented in the Technical Overview.

The load_progress example illustrates progress event handling. You can find this code in the /examples/load_progress directory in the Native Client SDK download.

Glossary

instance
The rectangle on the web page that is managed by the Native Client module. (The rectangle can have width=0 and height=0, which means that nothing is drawn on the page.) In the future it may be possible to embed multiple instances of a Native Client module in a web page, but currently each module can only be embedded once.
module
Short for "Native Client module," which is the code that is compiled into an executable file. The file extension for the module is .nexe.
progress events
Events generated by the Native Client runtime system during the module loading process.
message events
Events used to pass data between JavaScript and the Native Client module (see the Messaging System chapter).
view change events
Events that occur when a change in the browser affects the module instance (such as resizing the browser window or going to and from fullscreen mode).
focus events
Events that indicate whether certain parts of a web page are in our out of focus.
input events
Events that occur when an input device (such as keyboard or mouse) is used to interact with a module instance.

Module loading and progress events

The Native Client runtime reports a set of state changes during the module loading process by means of DOM progress events. This set of events is a direct port of the proposed W3C Progress Events standard (except for crash event which is an extension of the W3C standard). The following table lists the events types reported by the Native Client runtime:

Event Description Number of times triggered When event is triggered How you might react to event
loadstart Native Client has started to load a Native Client module (.nexe file). once This is the first progress event triggered after the Native Client module is instantiated and initialized. Display a status message, such as "Loading..."
progress Part of the .nexe file has been loaded zero or more After loadstart has been dispatched. Display a progress bar.
error The Native Client module failed to start execution (includes any error before or during initialization of the module).The lastError attribute (mentioned later) provides details on the error (initialization failed, sel_ldr did not start, and so on). zero or once After the last progress event has been dispatched, or after loadstart if no progress event was dispatched. Inform user that the application failed to load.
abort Loading of the Native Client module was aborted by the user. zero or once After the last progress event has been dispatched, or after loadstart if no progress event was dispatched. It's not likely you will want to respond to this event.
load The Native Client module was successfully loaded, and execution was started. (The module was initialized successfully.) zero or once After the last progress event has been dispatched, or after loadstart if no progress event was dispatched. Remove the progress bar.
loadend Loading of the Native Client module has stopped. Load succeeded (load), failed (error), or was aborted abort). once After an error, abort, or load event was dispatched. Indicate loading is over (regardless of failure or not).
crash The Native Client module is not responding (died on an assert() or exit()) after a successful load. This event is unique to Native Client and is not part of the W3C Progress Events standard. zero or more After a loadend. Notify user that the module did something illegal.

The sequence of events for a successful module load is as follows:

Event is dispatched ... then this task is attempted
loadstart load the manifest file
progress (first time) load the .nexe file
progress (subsequent times)
load start executing the .nexe file
loadend

Errors that occur during loading are logged to the JavaScript console in Google Chrome (select the menu icon menu icon > Tools > JavaScript console).

Handling progress events

You should add event listeners in a <script> element to listen for these events before the <embed> element is parsed. For example, the following code adds a listener for the load event to a parent <div> element that also contains the Native Client <embed> element. First, the listener is attached. Then, when the listener <div> receives the load event, the JavaScript moduleDidLoad() function is called. The following code is from the "Hello, World" example:

<div id="listener">
  <script type="text/javascript">
    document.getElementById('listener').addEventListener('load', moduleDidLoad, true);
  </script>
  <embed
    name="nacl_module"
    id="hello_world"
    width=0 height=0
    src="hello_world.nmf"
    type="application/x-nacl" />
</div>

Event listeners can be added to any DOM object. Since listeners set at the outermost scope capture events for their contained elements, you can set listeners on outer elements (including the <body> element) to handle events from inner elements. For more information, see the W3 specifications for event flow capture and event listener registration.

Displaying load status

One common response to progress events is to display the percentage of the module that has been loaded. In the load_progress example, when the progress event is triggered the moduleLoadProgress function is called. This function uses the lengthComputable, loaded, and total attributes (described in the proposed W3C Progress Events standard) of the event to calculate the percentage of the module that has loaded.

function moduleLoadProgress(event) {
    var loadPercent = 0.0;
    var loadPercentString;

    if (event.lengthComputable && event.total > 0) {
      loadPercent = event.loaded / event.total * 100.0;
        loadPercentString = loadPercent + '%';
    } else {
        // The total length is not yet known.
        loadPercent = -1.0;
        loadPercentString = 'Computing...';
    }

    appendToEventLog('progress: ' + loadPercentString +
    ' (' + event.loaded + ' of ' + event.total + ' bytes)');
}

The lastError attribute

The <embed> element has a lastError attribute that is set to an informative string whenever a load failure (an error or abort event) occurs.

The following code adds an event listener before the <embed> element to capture and handle an error in loading the Native Client module. The handleError() function listens for an error event. When an error occurs, this function prints the contents of the lastError attribute ( embed_element.lastError) as an alert.

<html>
…
  <body id="body">
    <div id="listener_div">
      <script type="text/javascript">
          function handleError(e) {
            var embed_element = document.getElementById('my_embed');
            window.alert('Error: lastError = ' + embed_element.lastError);
           }
         var listener_element = document.getElementById('listener_div');
         listener_element.addEventListener('error', handleError, true);
      </script>
      <embed
        name="naclModule"
        id="my_embed"
        width=100 height=20
        src="my_nacl_module.nmf"
        type="application/x-nacl" />
    </div>
  </body>
</html>

The readyState attribute

You can use the readyState attribute to monitor the loading process. This attribute is particularly useful if you don't care about the details of individual progress events or when you want to poll for current load state without registering listeners. The value of readyState progresses as follows for a successful load:

Event readyState value
(before any events) undefined
loadstart 1
progress 3
load 4
loadend 4

The following code demonstrates how to monitor the loading process using the readyState attribute. As before, the script that adds the event listeners precedes the <embed> element so that the event listeners are in place before the progress events are generated.

<html>
…
  <body id="body">
    <div id="status_div">
    </div>
    <div id="listener_div">
      <script type="text/javascript">
         var stat = document.getElementById('status_div');
         function handleEvent(e) {
           var embed_element = document.getElementById('my_embed');
           stat.innerHTML +=
           '<br>' + e.type + ': readyState = ' + embed_element.readyState;
         }
         var listener_element = document.getElementById('listener_div');
         listener_element.addEventListener('loadstart', handleEvent, true);
         listener_element.addEventListener('progress', handleEvent, true);
         listener_element.addEventListener('load', handleEvent, true);
         listener_element.addEventListener('loadend', handleEvent, true);
      </script>
      <embed
        name="naclModule"
        id="my_embed"
        width=0 height=0
        src="my_example.nmf"
        type="application/x-nacl" />
    </div>
  </body>
</html>

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.