1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 * A helper function to abbreviate getElementById.
12 * @param {string} elementId The id to get.
15 function $(elementId) {
16 return document.getElementById(elementId);
22 * @return {string} MIME type
24 function PNaClmimeType() {
25 return 'application/x-pnacl';
29 * Check if the browser supports PNaCl.
33 function browserSupportsPNaCl() {
34 var mimetype = PNaClmimeType();
35 return navigator.mimeTypes[mimetype] !== undefined;
39 * Get the URL for Google Cloud Storage.
41 * @param {string} name The relative path to the file.
44 function getDataURL(name) {
45 var revision = '236779';
46 var baseUrl = '//storage.googleapis.com/gonacl/demos/publish/';
47 return baseUrl + revision + '/life/' + name;
51 * Create the Native Client <embed> element as a child of the DOM element
54 * @param {string} name The name of the example.
55 * @param {number} width The width to create the plugin.
56 * @param {number} height The height to create the plugin.
57 * @param {Object} attrs Dictionary of attributes to set on the module.
59 function createNaClModule(name, width, height, attrs) {
60 var moduleEl = document.createElement('embed');
61 moduleEl.setAttribute('name', 'nacl_module');
62 moduleEl.setAttribute('id', 'nacl_module');
63 moduleEl.setAttribute('width', width);
64 moduleEl.setAttribute('height', height);
65 moduleEl.setAttribute('path', '');
66 moduleEl.setAttribute('src', getDataURL(name + '.nmf'));
67 moduleEl.setAttribute('type', PNaClmimeType());
69 // Add any optional arguments
71 for (var key in attrs) {
72 moduleEl.setAttribute(key, attrs[key]);
76 // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
77 // and a 'message' event listener attached. This wrapping method is used
78 // instead of attaching the event listeners directly to the <EMBED> element
79 // to ensure that the listeners are active before the NaCl module 'load'
81 var listenerDiv = $('listener');
82 listenerDiv.appendChild(moduleEl);
86 * Add the default event listeners to the element with id "listener".
88 function attachDefaultListeners() {
89 var listenerDiv = $('listener');
90 listenerDiv.addEventListener('load', moduleDidLoad, true);
91 listenerDiv.addEventListener('error', moduleLoadError, true);
92 listenerDiv.addEventListener('progress', moduleLoadProgress, true);
93 listenerDiv.addEventListener('crash', handleCrash, true);
94 listenerDiv.addEventListener('message', handleMessage, true);
98 * Called when the Browser can not communicate with the Module
100 * This event listener is registered in attachDefaultListeners above.
102 * @param {Object} event
104 function handleCrash(event) {
105 if (naclModule.exitStatus == -1) {
106 updateStatus('CRASHED');
108 updateStatus('EXITED [' + naclModule.exitStatus + ']');
113 * Handle a message coming from the NaCl module.
114 * @param {Object} message_event
116 function handleMessage(message_event) {
117 // Assume value is the current fps, sent as a float.
118 $('fps').textContent = message_event.data.toFixed(1);
122 * Called when the NaCl module is loaded.
124 * This event listener is registered in attachDefaultListeners above.
126 function moduleDidLoad() {
127 var bar = $('progress-bar');
128 bar.style.width = 100;
129 naclModule = $('nacl_module');
134 * Hide the status field and progress bar.
136 function hideStatus() {
137 $('loading-cover').style.display = 'none';
141 * Called when the plugin fails to load.
143 * @param {Object} event
145 function moduleLoadError(event) {
146 updateStatus('Load failed.');
150 * Called when the plugin reports progress events.
152 * @param {Object} event
154 function moduleLoadProgress(event) {
155 $('progress').style.display = 'block';
157 var loadPercent = 0.0;
158 var bar = $('progress-bar');
160 if (event.lengthComputable && event.total > 0) {
161 loadPercent = event.loaded / event.total * 100.0;
163 // The total length is not yet known.
166 bar.style.width = loadPercent + "%";
169 * If the element with id 'statusField' exists, then set its HTML to the status
172 * @param {string} opt_message The message to set.
174 function updateStatus(opt_message) {
175 var statusField = $('statusField');
177 statusField.style.display = 'block';
178 statusField.textContent = opt_message;
183 * Listen for the DOM content to be loaded. This event is fired when parsing of
184 * the page's document has finished.
186 document.addEventListener('DOMContentLoaded', function() {
187 updateStatus('Loading...');
188 if (!browserSupportsPNaCl()) {
189 updateStatus('Browser does not support PNaCl or PNaCl is disabled');
190 } else if (naclModule == null) {
191 createNaClModule('life', '100%', '100%');
192 attachDefaultListeners();
194 // It's possible that the Native Client module onload event fired
195 // before the page's onload event. In this case, the status message
196 // will reflect 'SUCCESS', but won't be displayed. This call will
197 // display the current message.
198 updateStatus('Waiting.');