Progress Events
Deprecation of the technologies described here has been announced for platforms other than ChromeOS.
Please visit our migration guide for details.
There are five types of events that developers can respond to in Native Client: progress, message, view change, focus, and input events (each described in the glossary below). This section describes how to monitor progress events (events that occur during the loading and execution of a Native Client module). This section assumes you are familiar with the material presented in the Technical Overview.
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 the crash
event which is an extension of the W3C standard). The following table lists the events types reported by the Native Client runtime:
Event | Times triggered | When triggered | How you might respond |
---|---|---|---|
| once | The first progress event after the Native Client module is instantiated and initialized. | Display a status message, such as “Loading...” |
| zero or more | After loadstart has been dispatched. | Display a progress bar. |
| 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. |
| 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. |
| zero or once | After the last progress event has been dispatched, or after loadstart if no progress event was dispatched. | Remove the progress bar. |
| once | After an error , abort , or load event was dispatched. | Indicate loading is over (regardless of failure or not). |
| zero or once | 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 module |
progress (subsequent times) | |
load | start executing the module |
loadend |
Errors that occur during loading are logged to the JavaScript console in Google Chrome (select the 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 excerpted from the example in getting_started/part1/
:
<!-- Load the published pexe. Note: Since this module does not use any real-estate in the browser, its width and height are set to 0. Note: The <embed> element is wrapped inside a <div>, which has both a 'load' and a 'message' event listener attached. This wrapping method is used instead of attaching the event listeners directly to the <embed> element to ensure that the listeners are active before the NaCl module 'load' event fires. This also allows you to use PPB_Messaging.PostMessage() (in C) or pp::Instance.PostMessage() (in C++) from within the initialization code in your module. --> <div id="listener"> <script type="text/javascript"> var listener = document.getElementById('listener'); listener.addEventListener('load', moduleDidLoad, true); listener.addEventListener('message', handleMessage, true); </script> <embed id="hello_tutorial" width=0 height=0 src="hello_tutorial.nmf" type="application/x-pnacl" /> </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 + '%'; common.logMessage('progress: ' + event.url + ' ' + loadPercentString + ' (' + event.loaded + ' of ' + event.total + ' bytes)'); } else { // The total length is not yet known. common.logMessage('progress: Computing...'); } }
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.
function domContentLoaded(name, tc, config, width, height) { var listener = document.getElementById('listener'); ... listener.addEventListener('error', moduleLoadError, true); ... common.createNaClModule(name, tc, config, width, height); } function moduleLoadError() { common.logMessage('error: ' + common.naclModule.lastError); }
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-pnacl" /> </div> </body> </html>
The exitStatus
attribute
This read-only attribute is set if the application calls exit(n)
, abort()
, or crashes. Since NaCl modules are event handlers, there is no need to call exit(n)
in normal execution. If the module does exit or crash, the crash
progress event is issued and the exitStatus
attribute will contain the numeric value of the exit status:
- In the case of explicit calls to
exit(n)
, the numeric value will ben
(between 0 and 255). - In the case of crashes and calls to
abort()
, the numeric value will be non-zero, but the exact value will depend on the chosen libc and the target architecture, and may change in the future. Applications should not rely on theexitStatus
value being stable in these cases, but the value may nevertheless be useful for temporary debugging.