1// Copyright (c) 2012 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. 4 5function moduleDidLoad() { 6 common.hideModule(); 7} 8 9function $(id) { 10 return document.getElementById(id); 11} 12 13// Called by the common.js module. 14function domContentLoaded(name, tc, config, width, height) { 15 navigator.webkitPersistentStorage.requestQuota(1024 * 1024, 16 function(bytes) { 17 common.updateStatus( 18 'Allocated ' + bytes + ' bytes of persistant storage.'); 19 common.attachDefaultListeners(); 20 common.createNaClModule(name, tc, config, width, height); 21 }, 22 function(e) { alert('Failed to allocate space') }); 23} 24 25// Called by the common.js module. 26function attachListeners() { 27 var radioEls = document.querySelectorAll('input[type="radio"]'); 28 for (var i = 0; i < radioEls.length; ++i) { 29 radioEls[i].addEventListener('click', onRadioClicked); 30 } 31 32 // Wire up the 'click' event for each function's button. 33 var functionEls = document.querySelectorAll('.function'); 34 for (var i = 0; i < functionEls.length; ++i) { 35 var functionEl = functionEls[i]; 36 var id = functionEl.getAttribute('id'); 37 var buttonEl = functionEl.querySelector('button'); 38 39 // The function name matches the element id. 40 var func = window[id]; 41 buttonEl.addEventListener('click', func); 42 } 43 44 $('pipe_input_box').addEventListener('keypress', onPipeInput) 45 $('pipe_output').disabled = true; 46 47 $('pipe_name').addEventListener('change', 48 function() { $('pipe_output').value = ''; }) 49} 50 51// Called with keypress events on the pipe input box 52function onPipeInput(e) { 53 // Create an arraybuffer containing the 16-bit char code 54 // from the keypress event. 55 var buffer = new ArrayBuffer(1*2); 56 var bufferView = new Uint16Array(buffer); 57 bufferView[0] = e.charCode; 58 59 // Pass the buffer in a dictionary over the NaCl module 60 var pipeSelect = $('pipe_name'); 61 var pipeName = pipeSelect[pipeSelect.selectedIndex].value; 62 var message = { 63 pipe: pipeName, 64 operation: 'write', 65 payload: buffer, 66 }; 67 nacl_module.postMessage(message); 68 e.preventDefault(); 69 return false; 70} 71 72function onRadioClicked(e) { 73 var divId = this.id.slice(5); // skip "radio" 74 var functionEls = document.querySelectorAll('.function'); 75 for (var i = 0; i < functionEls.length; ++i) { 76 var visible = functionEls[i].id === divId; 77 if (functionEls[i].id === divId) 78 functionEls[i].removeAttribute('hidden'); 79 else 80 functionEls[i].setAttribute('hidden', ''); 81 } 82} 83 84function addNameToSelectElements(cssClass, handle, name) { 85 var text = '[' + handle + '] ' + name; 86 var selectEls = document.querySelectorAll(cssClass); 87 for (var i = 0; i < selectEls.length; ++i) { 88 var optionEl = document.createElement('option'); 89 optionEl.setAttribute('value', handle); 90 optionEl.appendChild(document.createTextNode(text)); 91 selectEls[i].appendChild(optionEl); 92 } 93} 94 95function removeNameFromSelectElements(cssClass, handle) { 96 var optionEls = document.querySelectorAll(cssClass + ' > option'); 97 for (var i = 0; i < optionEls.length; ++i) { 98 var optionEl = optionEls[i]; 99 if (optionEl.value == handle) { 100 var selectEl = optionEl.parentNode; 101 selectEl.removeChild(optionEl); 102 } 103 } 104} 105 106var filehandle_map = {}; 107var dirhandle_map = {}; 108 109function fopen(e) { 110 var filename = $('fopenFilename').value; 111 var access = $('fopenMode').value; 112 postCall('fopen', filename, access, function(filename, filehandle) { 113 filehandle_map[filehandle] = filename; 114 115 addNameToSelectElements('.file-handle', filehandle, filename); 116 common.logMessage('File ' + filename + ' opened successfully.'); 117 }); 118} 119 120function fclose(e) { 121 var filehandle = parseInt($('fcloseHandle').value, 10); 122 postCall('fclose', filehandle, function(filehandle) { 123 var filename = filehandle_map[filehandle]; 124 removeNameFromSelectElements('.file-handle', filehandle, filename); 125 common.logMessage('File ' + filename + ' closed successfully.'); 126 }); 127} 128 129function fread(e) { 130 var filehandle = parseInt($('freadHandle').value, 10); 131 var numBytes = parseInt($('freadBytes').value, 10); 132 postCall('fread', filehandle, numBytes, function(filehandle, data) { 133 var filename = filehandle_map[filehandle]; 134 common.logMessage('Read "' + data + '" from file ' + filename + '.'); 135 }); 136} 137 138function fwrite(e) { 139 var filehandle = parseInt($('fwriteHandle').value, 10); 140 var data = $('fwriteData').value; 141 postCall('fwrite', filehandle, data, function(filehandle, bytesWritten) { 142 var filename = filehandle_map[filehandle]; 143 common.logMessage('Wrote ' + bytesWritten + ' bytes to file ' + filename + 144 '.'); 145 }); 146} 147 148function fseek(e) { 149 var filehandle = parseInt($('fseekHandle').value, 10); 150 var offset = parseInt($('fseekOffset').value, 10); 151 var whence = parseInt($('fseekWhence').value, 10); 152 postCall('fseek', filehandle, offset, whence, function(filehandle, filepos) { 153 var filename = filehandle_map[filehandle]; 154 common.logMessage('Seeked to location ' + filepos + ' in file ' + filename + 155 '.'); 156 }); 157} 158 159function fflush(e) { 160 var filehandle = parseInt($('fflushHandle').value, 10); 161 postCall('fflush', filehandle, function(filehandle, filepos) { 162 var filename = filehandle_map[filehandle]; 163 common.logMessage('flushed ' + filename + '.'); 164 }); 165} 166 167function stat(e) { 168 var filename = $('statFilename').value; 169 postCall('stat', filename, function(filename, size) { 170 common.logMessage('File ' + filename + ' has size ' + size + '.'); 171 }); 172} 173 174function opendir(e) { 175 var dirname = $('opendirDirname').value; 176 postCall('opendir', dirname, function(dirname, dirhandle) { 177 dirhandle_map[dirhandle] = dirname; 178 179 addNameToSelectElements('.dir-handle', dirhandle, dirname); 180 common.logMessage('Directory ' + dirname + ' opened successfully.'); 181 }); 182} 183 184function readdir(e) { 185 var dirhandle = parseInt($('readdirHandle').value, 10); 186 postCall('readdir', dirhandle, function(dirhandle, ino, name) { 187 var dirname = dirhandle_map[dirhandle]; 188 if (ino === undefined) { 189 common.logMessage('End of directory.'); 190 } else { 191 common.logMessage('Read entry ("' + name + '", ino = ' + ino + 192 ') from directory ' + dirname + '.'); 193 } 194 }); 195} 196 197function closedir(e) { 198 var dirhandle = parseInt($('closedirHandle').value, 10); 199 postCall('closedir', dirhandle, function(dirhandle) { 200 var dirname = dirhandle_map[dirhandle]; 201 delete dirhandle_map[dirhandle]; 202 203 removeNameFromSelectElements('.dir-handle', dirhandle, dirname); 204 common.logMessage('Directory ' + dirname + ' closed successfully.'); 205 }); 206} 207 208function mkdir(e) { 209 var dirname = $('mkdirDirname').value; 210 var mode = parseInt($('mkdirMode').value, 10); 211 postCall('mkdir', dirname, mode, function(dirname) { 212 common.logMessage('Directory ' + dirname + ' created successfully.'); 213 }); 214} 215 216function rmdir(e) { 217 var dirname = $('rmdirDirname').value; 218 postCall('rmdir', dirname, function(dirname) { 219 common.logMessage('Directory ' + dirname + ' removed successfully.'); 220 }); 221} 222 223function chdir(e) { 224 var dirname = $('chdirDirname').value; 225 postCall('chdir', dirname, function(dirname) { 226 common.logMessage('Changed directory to: ' + dirname + '.'); 227 }); 228} 229 230function getcwd(e) { 231 postCall('getcwd', function(dirname) { 232 common.logMessage('getcwd: ' + dirname + '.'); 233 }); 234} 235 236function getaddrinfo(e) { 237 var name = $('getaddrinfoName').value; 238 var family = $('getaddrinfoFamily').value; 239 postCall('getaddrinfo', name, family, function(name, addrType) { 240 common.logMessage('getaddrinfo returned successfully'); 241 common.logMessage('ai_cannonname = ' + name + '.'); 242 var count = 1; 243 for (var i = 1; i < arguments.length; i+=2) { 244 var msg = 'Address number ' + count + ' = ' + arguments[i] + 245 ' (' + arguments[i+1] + ')'; 246 common.logMessage(msg); 247 count += 1; 248 } 249 }); 250} 251 252function gethostbyname(e) { 253 var name = $('gethostbynameName').value; 254 postCall('gethostbyname', name, function(name, addrType) { 255 common.logMessage('gethostbyname returned successfully'); 256 common.logMessage('h_name = ' + name + '.'); 257 common.logMessage('h_addr_type = ' + addrType + '.'); 258 for (var i = 2; i < arguments.length; i++) { 259 common.logMessage('Address number ' + (i-1) + ' = ' + arguments[i] + '.'); 260 } 261 }); 262} 263 264function connect(e) { 265 var host = $('connectHost').value; 266 var port = parseInt($('connectPort').value, 10); 267 postCall('connect', host, port, function(sockhandle) { 268 common.logMessage('connected'); 269 addNameToSelectElements('.sock-handle', sockhandle, '[socket]'); 270 }); 271} 272 273function recv(e) { 274 var handle = parseInt($('recvHandle').value, 10); 275 var bufferSize = parseInt($('recvBufferSize').value, 10); 276 postCall('recv', handle, bufferSize, function(messageLen, message) { 277 common.logMessage("received " + messageLen + ' bytes: ' + message); 278 }); 279} 280 281function send(e) { 282 var handle = parseInt($('sendHandle').value, 10); 283 var message = $('sendMessage').value; 284 postCall('send', handle, message, function(sentBytes) { 285 common.logMessage("sent bytes: " + sentBytes); 286 }); 287} 288 289function close(e) { 290 var handle = parseInt($('closeHandle').value, 10); 291 postCall('close', handle, function(sock) { 292 removeNameFromSelectElements('.sock-handle', sock, "[socket]"); 293 common.logMessage("closed socket: " + sock); 294 }); 295} 296 297var funcToCallback = {}; 298 299function postCall(func) { 300 var callback = arguments[arguments.length - 1]; 301 funcToCallback[func] = callback; 302 303 nacl_module.postMessage({ 304 cmd: func, 305 args: Array.prototype.slice.call(arguments, 1, -1) 306 }); 307} 308 309function ArrayBufferToString(buf) { 310 return String.fromCharCode.apply(null, new Uint16Array(buf)); 311} 312 313// Called by the common.js module. 314function handleMessage(message_event) { 315 var data = message_event.data; 316 if ((typeof(data) === 'string' || data instanceof String)) { 317 common.logMessage(data); 318 } else if (data instanceof Object) { 319 var pipeName = data['pipe'] 320 if (pipeName !== undefined) { 321 // Message for JavaScript I/O pipe 322 var operation = data['operation']; 323 if (operation == 'write') { 324 $('pipe_output').value += ArrayBufferToString(data['payload']); 325 } else if (operation == 'ack') { 326 common.logMessage(pipeName + ": ack:" + data['payload']); 327 } else { 328 common.logMessage('Got unexpected pipe operation: ' + operation); 329 } 330 } else { 331 // Result from a function call. 332 var params = data.args; 333 var funcName = data.cmd; 334 var callback = funcToCallback[funcName]; 335 336 if (!callback) { 337 common.logMessage('Error: Bad message ' + funcName + 338 ' received from NaCl module.'); 339 return; 340 } 341 342 delete funcToCallback[funcName]; 343 callback.apply(null, params); 344 } 345 } else { 346 common.logMessage('Error: Unknow message `' + data + 347 '` received from NaCl module.'); 348 } 349} 350