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 “Loading...”</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’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> </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> </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" /> > Tools > 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><script></code> element to listen for these 263 events before the <code><embed></code> element is parsed. For example, the following code 264 adds a listener for the <code>load</code> event to a parent <code><div></code> element that also 265 contains the Native Client <code><embed></code> element. First, the listener is 266 attached. Then, when the listener <code><div></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 <!-- 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 <embed> element is wrapped inside a <div>, 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 <embed> 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 --> 283 <div id="listener"> 284 <script type="text/javascript"> 285 var listener = document.getElementById('listener'); 286 listener.addEventListener('load', moduleDidLoad, true); 287 listener.addEventListener('message', handleMessage, true); 288 </script> 289 290 <embed id="hello_tutorial" 291 width=0 height=0 292 src="hello_tutorial.nmf" 293 type="application/x-pnacl" /> 294 </div> 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><body></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 && event.total > 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><embed></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><embed></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’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><embed></code> element so that the event listeners are in place before 385 the progress events are generated.</p> 386 <pre class="prettyprint"> 387 <html> 388 ... 389 <body id="body"> 390 <div id="status_div"> 391 </div> 392 <div id="listener_div"> 393 <script type="text/javascript"> 394 var stat = document.getElementById('status_div'); 395 function handleEvent(e) { 396 var embed_element = document.getElementById('my_embed'); 397 stat.innerHTML += 398 '<br>' + 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 </script> 406 <embed 407 name="naclModule" 408 id="my_embed" 409 width=0 height=0 410 src="my_example.nmf" 411 type="application/x-pnacl" /> 412 </div> 413 </body> 414 </html> 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