Home | History | Annotate | Download | only in coding
      1 .. _devcycle-progress-events:
      2 
      3 :template: standard_nacl_api
      4 
      5 ###############
      6 Progress Events
      7 ###############
      8 
      9 .. contents::
     10   :local:
     11   :backlinks: none
     12   :depth: 2
     13 
     14 There are five types of events that developers can respond to in Native Client:
     15 progress, message, view change, focus, and input events (each described in the
     16 glossary below). This chapter describes how to monitor progress events (events
     17 that occur during the loading and execution of a Native Client module). This
     18 chapter assumes you are familiar with the material presented in the
     19 :doc:`Technical Overview <../../overview>`.
     20 
     21 .. Note::
     22   :class: note
     23 
     24   The load_progress example illustrates progress event handling. You can find
     25   this code in the ``/examples/tutorial/load_progress/`` directory in the Native
     26   Client SDK download.
     27 
     28 Module loading and progress events
     29 ==================================
     30 
     31 The Native Client runtime reports a set of state changes during the module
     32 loading process by means of DOM progress events. This set of events is a direct
     33 port of the proposed W3C `Progress Events
     34 <http://www.w3.org/TR/progress-events/>`_ standard (except for the ``crash``
     35 event which is an extension of the W3C standard). The following table lists the
     36 events types reported by the Native Client runtime:
     37 
     38 +-------------+--------------------+-----------+---------------+---------------+
     39 | Event       | Description        | Number of | When event is | How you might |
     40 |             |                    | times     | triggered     | react to      |
     41 |             |                    | triggered |               | event         |
     42 +=============+====================+===========+===============+===============+
     43 |``loadstart``| Native Client has  | once      | This is the   | Display a     |
     44 |             | started to load a  |           | first         | status        |
     45 |             | Native Client      |           | progress      | message, such |
     46 |             | module.            |           | event         | as            |
     47 |             |                    |           | triggered     | "Loading..."  |
     48 |             |                    |           | after the     |               |
     49 |             |                    |           | Native Client |               |
     50 |             |                    |           | module is     |               |
     51 |             |                    |           | instantiated  |               |
     52 |             |                    |           | and           |               |
     53 |             |                    |           | initialized.  |               |
     54 +-------------+--------------------+-----------+---------------+---------------+
     55 |``progress`` | Part of the module | zero or   | After         | Display a     |
     56 |             | has been loaded.   | more      | ``loadstart`` | progress bar. |
     57 |             |                    |           | has been      |               |
     58 |             |                    |           | dispatched.   |               |
     59 +-------------+--------------------+-----------+---------------+---------------+
     60 |``error``    | The Native Client  | zero or   | After the     | Inform user   |
     61 |             | module failed to   | once      | last          | that the      |
     62 |             | start execution    |           | ``progress``  | application   |
     63 |             | (includes any      |           | event has     | failed to     |
     64 |             | error before or    |           | been          | load.         |
     65 |             | during             |           | dispatched,   |               |
     66 |             | initialization of  |           | or after      |               |
     67 |             | the module). The   |           | ``loadstart`` |               |
     68 |             | ``lastError``      |           | if no         |               |
     69 |             | attribute          |           | ``progress``  |               |
     70 |             | (mentioned later)  |           | event was     |               |
     71 |             | provides details   |           | dispatched.   |               |
     72 |             | on the error       |           |               |               |
     73 |             | (initialization    |           |               |               |
     74 |             | failed, sel_ldr    |           |               |               |
     75 |             | did not start,     |           |               |               |
     76 |             | and so on).        |           |               |               |
     77 +-------------+--------------------+-----------+---------------+---------------+
     78 |``abort``    | Loading of the     | zero or   | After the     | It's not      |
     79 |             | Native Client      | once      | last          | likely you    |
     80 |             | module was         |           | ``progress``  | will want to  |
     81 |             | aborted by the     |           | event has     | respond to    |
     82 |             | user.              |           | been          | this event.   |
     83 |             |                    |           | dispatched,   |               |
     84 |             |                    |           | or after      |               |
     85 |             |                    |           | ``loadstart`` |               |
     86 |             |                    |           | if no         |               |
     87 |             |                    |           | ``progress``  |               |
     88 |             |                    |           | event was     |               |
     89 |             |                    |           | dispatched.   |               |
     90 +-------------+--------------------+-----------+---------------+---------------+
     91 |``load``     | The Native Client  | zero or   | After the     | Remove the    |
     92 |             | module was         | once      | last          | progress bar. |
     93 |             | successfully       |           | ``progress``  |               |
     94 |             | loaded, and        |           | event has     |               |
     95 |             | execution was      |           | been          |               |
     96 |             | started. (The      |           | dispatched,   |               |
     97 |             | module was         |           | or after      |               |
     98 |             | initialized        |           | ``loadstart`` |               |
     99 |             | successfully.)     |           | if no         |               |
    100 |             |                    |           | ``progress``  |               |
    101 |             |                    |           | event was     |               |
    102 |             |                    |           | dispatched.   |               |
    103 +-------------+--------------------+-----------+---------------+---------------+
    104 |``loadend``  | Loading of the     | once      | After an      | Indicate      |
    105 |             | Native Client      |           | ``error``,    | loading is    |
    106 |             | module has         |           | ``abort``, or | over          |
    107 |             | stopped. Load      |           | ``load``      | (regardless   |
    108 |             | succeeded          |           | event was     | of failure or |
    109 |             | (``load``),        |           | dispatched.   | not).         |
    110 |             | failed             |           |               |               |
    111 |             | (``error``), or    |           |               |               |
    112 |             | was aborted        |           |               |               |
    113 |             | (``abort``).       |           |               |               |
    114 +-------------+--------------------+-----------+---------------+---------------+
    115 |``crash``    | The Native Client  | zero or   | After a       | Notify user   |
    116 |             | module is not      | once      | ``loadend``.  | that the      |
    117 |             | responding (died   |           |               | module did    |
    118 |             | on an              |           |               | something     |
    119 |             | ``assert()`` or    |           |               | illegal.      |
    120 |             | ``exit()``) after  |           |               |               |
    121 |             | a successful       |           |               |               |
    122 |             | load. This event   |           |               |               |
    123 |             | is unique to       |           |               |               |
    124 |             | Native Client and  |           |               |               |
    125 |             | is not part of     |           |               |               |
    126 |             | the W3C Progress   |           |               |               |
    127 |             | Events standard.   |           |               |               |
    128 |             | The ``exitStatus`` |           |               |               |
    129 |             | attribute provides |           |               |               |
    130 |             | the numeric exit   |           |               |               |
    131 |             | status value.      |           |               |               |
    132 +-------------+--------------------+-----------+---------------+---------------+
    133 
    134 The sequence of events for a successful module load is as follows:
    135 
    136 =============================== ===============================
    137 Event is dispatched             ... then this task is attempted
    138 =============================== ===============================
    139 ``loadstart``                   load the manifest file
    140 ``progress`` (first time)       load the module
    141 ``progress`` (subsequent times)
    142 ``load``                        start executing the module
    143 ``loadend``
    144 =============================== ===============================
    145 
    146 Errors that occur during loading are logged to the JavaScript console in Google
    147 Chrome (select the menu icon |menu-icon| > Tools > JavaScript console).
    148 
    149 .. |menu-icon| image:: /images/menu-icon.png
    150 
    151 Handling progress events
    152 ========================
    153 
    154 You should add event listeners in a ``<script>`` element to listen for these
    155 events before the ``<embed>`` element is parsed. For example, the following code
    156 adds a listener for the ``load`` event to a parent ``<div>`` element that also
    157 contains the Native Client ``<embed>`` element. First, the listener is
    158 attached. Then, when the listener ``<div>`` receives the ``load`` event, the
    159 JavaScript ``moduleDidLoad()`` function is called. The following code is
    160 excerpted from the example in ``getting_started/part1/``:
    161 
    162 .. naclcode::
    163 
    164   <!--
    165   Load the published pexe.
    166   Note: Since this module does not use any real-estate in the browser, its
    167   width and height are set to 0.
    168 
    169   Note: The <embed> element is wrapped inside a <div>, which has both a 'load'
    170   and a 'message' event listener attached.  This wrapping method is used
    171   instead of attaching the event listeners directly to the <embed> element to
    172   ensure that the listeners are active before the NaCl module 'load' event
    173   fires.  This also allows you to use PPB_Messaging.PostMessage() (in C) or
    174   pp::Instance.PostMessage() (in C++) from within the initialization code in
    175   your module.
    176   -->
    177   <div id="listener">
    178     <script type="text/javascript">
    179       var listener = document.getElementById('listener');
    180       listener.addEventListener('load', moduleDidLoad, true);
    181       listener.addEventListener('message', handleMessage, true);
    182     </script>
    183 
    184     <embed id="hello_tutorial"
    185            width=0 height=0
    186            src="hello_tutorial.nmf"
    187            type="application/x-pnacl" />
    188   </div>
    189 
    190 Event listeners can be added to any DOM object. Since listeners set at the
    191 outermost scope capture events for their contained elements, you can set
    192 listeners on outer elements (including the ``<body>`` element) to handle events
    193 from inner elements. For more information, see the W3 specifications for `event
    194 flow capture
    195 <http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture>`_ and
    196 `event listener registration
    197 <http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration>`_.
    198 
    199 Displaying load status
    200 ======================
    201 
    202 One common response to progress events is to display the percentage of the
    203 module that has been loaded. In the load_progress example, when the ``progress``
    204 event is triggered the ``moduleLoadProgress`` function is called. This function
    205 uses the ``lengthComputable``, ``loaded``, and ``total`` attributes (described
    206 in the proposed W3C `Progress Events <http://www.w3.org/TR/progress-events/>`_
    207 standard) of the event to calculate the percentage of the module that has
    208 loaded.
    209 
    210 .. naclcode::
    211 
    212   function moduleLoadProgress(event) {
    213     var loadPercent = 0.0;
    214     var loadPercentString;
    215     if (event.lengthComputable && event.total > 0) {
    216       loadPercent = event.loaded / event.total * 100.0;
    217       loadPercentString = loadPercent + '%';
    218       common.logMessage('progress: ' + event.url + ' ' + loadPercentString +
    219                        ' (' + event.loaded + ' of ' + event.total + ' bytes)');
    220     } else {
    221       // The total length is not yet known.
    222       common.logMessage('progress: Computing...');
    223     }
    224   }
    225 
    226 The ``lastError`` attribute
    227 ===========================
    228 
    229 The ``<embed>`` element has a ``lastError`` attribute that is set to an
    230 informative string whenever a load failure (an ``error`` or ``abort`` event)
    231 occurs.
    232 
    233 The following code adds an event listener before the ``<embed>`` element to
    234 capture and handle an error in loading the Native Client module. The
    235 ``handleError()`` function listens for an ``error`` event. When an error occurs,
    236 this function prints the contents of the ``lastError`` attribute
    237 (``embed_element.lastError``) as an alert.
    238 
    239 .. naclcode::
    240 
    241   function domContentLoaded(name, tc, config, width, height) {
    242     var listener = document.getElementById('listener');
    243     ...
    244     listener.addEventListener('error', moduleLoadError, true);
    245     ...
    246     common.createNaClModule(name, tc, config, width, height);
    247   }
    248 
    249   function moduleLoadError() {
    250     common.logMessage('error: ' + common.naclModule.lastError);
    251   }
    252 
    253 The ``readyState`` attribute
    254 ============================
    255 
    256 You can use the ``readyState`` attribute to monitor the loading process. This
    257 attribute is particularly useful if you don't care about the details of
    258 individual progress events or when you want to poll for current load state
    259 without registering listeners. The value of ``readyState`` progresses as follows
    260 for a successful load:
    261 
    262 ===================     ====================
    263 Event                   ``readyState`` value
    264 ===================     ====================
    265 (before any events)     ``undefined``
    266 ``loadstart``           1
    267 ``progress``            3
    268 ``load``                4
    269 ``loadend``             4
    270 ===================     ====================
    271 
    272 The following code demonstrates how to monitor the loading process using the
    273 ``readyState`` attribute. As before, the script that adds the event listeners
    274 precedes the ``<embed>`` element so that the event listeners are in place before
    275 the progress events are generated.
    276 
    277 .. naclcode::
    278 
    279   <html>
    280   ...
    281     <body id="body">
    282       <div id="status_div">
    283       </div>
    284       <div id="listener_div">
    285         <script type="text/javascript">
    286            var stat = document.getElementById('status_div');
    287            function handleEvent(e) {
    288              var embed_element = document.getElementById('my_embed');
    289              stat.innerHTML +=
    290              '<br>' + e.type + ': readyState = ' + embed_element.readyState;
    291            }
    292            var listener_element = document.getElementById('listener_div');
    293            listener_element.addEventListener('loadstart', handleEvent, true);
    294            listener_element.addEventListener('progress', handleEvent, true);
    295            listener_element.addEventListener('load', handleEvent, true);
    296            listener_element.addEventListener('loadend', handleEvent, true);
    297         </script>
    298         <embed
    299           name="naclModule"
    300           id="my_embed"
    301           width=0 height=0
    302           src="my_example.nmf"
    303           type="application/x-pnacl" />
    304       </div>
    305     </body>
    306   </html>
    307 
    308 The ``exitStatus`` attribute
    309 ============================
    310 
    311 This read-only attribute is set if the application calls ``exit(n)``,
    312 ``abort()``, or crashes. Since NaCl modules are event handlers, there is no
    313 need to call ``exit(n)`` in normal execution. If the module does exit or
    314 crash, the ``crash`` progress event is issued and the ``exitStatus`` attribute
    315 will contain the numeric value of the exit status:
    316 
    317 * In the case of explicit calls to ``exit(n)``, the numeric value will be
    318   ``n`` (between 0 and 255).
    319 * In the case of crashes and calls to ``abort()``, the numeric value will
    320   be non-zero, but the exact value will depend on the chosen libc and the
    321   target architecture, and may change in the future. Applications should not
    322   rely on the ``exitStatus`` value being stable in these cases, but the value
    323   may nevertheless be useful for temporary debugging.
    324