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