Progress Events
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 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.
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 | 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. | 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 module 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.
The exitStatus
attribute provides
the numeric exit
status value. |
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.