OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2014 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
| 7 /* jshint evil: true */ |
| 8 /* globals PipeServer */ |
| 9 |
7 'use strict'; | 10 'use strict'; |
8 | 11 |
9 // TODO(gdeepti): extend to multiple mounts. | 12 // TODO(gdeepti): extend to multiple mounts. |
10 /** | 13 /** |
11 * Mount object contains the state of the local mount. | 14 * Mount object contains the state of the local mount. |
12 */ | 15 */ |
13 var g_mount = { | 16 var g_mount = { |
14 // DirectoryEntry specified by the user | 17 // DirectoryEntry specified by the user |
15 entry: undefined, | 18 entry: undefined, |
16 | 19 |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 callback(getNaClArch.naclArch_); | 284 callback(getNaClArch.naclArch_); |
282 }); | 285 }); |
283 return; | 286 return; |
284 } else { | 287 } else { |
285 getNaClArch.naclArch_ = null; | 288 getNaClArch.naclArch_ = null; |
286 } | 289 } |
287 } | 290 } |
288 setTimeout(function() { | 291 setTimeout(function() { |
289 callback(getNaClArch.naclArch_); | 292 callback(getNaClArch.naclArch_); |
290 }, 0); | 293 }, 0); |
291 }; | 294 } |
292 | 295 |
293 /** | 296 /** |
294 * Handles a stdout event. | 297 * Handles a stdout event. |
295 * @callback stdoutCallback | 298 * @callback stdoutCallback |
296 * @param {string} msg The string sent to stdout. | 299 * @param {string} msg The string sent to stdout. |
297 */ | 300 */ |
298 | 301 |
299 /** | 302 /** |
300 * Listen for stdout from the spawned processes. | 303 * Listen for stdout from the spawned processes. |
301 * @param {stdoutCallback} callback The callback to be called on a stdout write. | 304 * @param {stdoutCallback} callback The callback to be called on a stdout write. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 } | 399 } |
397 return result; | 400 return result; |
398 }; | 401 }; |
399 | 402 |
400 /** | 403 /** |
401 * Makes the path in a NMF entry to fully specified path. | 404 * Makes the path in a NMF entry to fully specified path. |
402 * @private | 405 * @private |
403 */ | 406 */ |
404 NaClProcessManager.prototype.adjustNmfEntry_ = function(entry) { | 407 NaClProcessManager.prototype.adjustNmfEntry_ = function(entry) { |
405 for (var arch in entry) { | 408 for (var arch in entry) { |
| 409 var path; |
406 if (arch === 'portable') { | 410 if (arch === 'portable') { |
407 if (entry[arch]['pnacl-translate'] === undefined || | 411 if (entry[arch]['pnacl-translate'] === undefined || |
408 entry[arch]['pnacl-translate']['url'] === undefined) { | 412 entry[arch]['pnacl-translate']['url'] === undefined) { |
409 return; | 413 return; |
410 } | 414 } |
411 var path = entry[arch]['pnacl-translate']['url']; | 415 path = entry[arch]['pnacl-translate']['url']; |
412 } else { | 416 } else { |
413 if (entry[arch]['url'] === undefined) { | 417 if (entry[arch]['url'] === undefined) { |
414 return; | 418 return; |
415 } | 419 } |
416 var path = entry[arch]['url']; | 420 path = entry[arch]['url']; |
417 } | 421 } |
418 | 422 |
419 // Convert 'path' from the NaCl VFS into an HTML5 filesystem: URL | 423 // Convert 'path' from the NaCl VFS into an HTML5 filesystem: URL |
420 var tmpMountPoint = '/tmp/'; | 424 var tmpMountPoint = '/tmp/'; |
421 var httpMountPoint = '/mnt/http/'; | 425 var httpMountPoint = '/mnt/http/'; |
422 var fsname = '/persistent/'; | 426 var fsname = '/persistent/'; |
423 if (path.indexOf(tmpMountPoint) === 0) { | 427 if (path.indexOf(tmpMountPoint) === 0) { |
424 // Strip the /tmp/ prefix | 428 // Strip the /tmp/ prefix |
425 path = path.replace(tmpMountPoint, ''); | 429 path = path.replace(tmpMountPoint, ''); |
426 fsname = '/temporary/'; | 430 fsname = '/temporary/'; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 nacl_apipe_close: [this.pipeServer, | 475 nacl_apipe_close: [this.pipeServer, |
472 this.pipeServer.handleMessageAPipeClose], | 476 this.pipeServer.handleMessageAPipeClose], |
473 nacl_jseval: [this, this.handleMessageJSEval_], | 477 nacl_jseval: [this, this.handleMessageJSEval_], |
474 nacl_deadpid: [this, this.handleMessageDeadPid_], | 478 nacl_deadpid: [this, this.handleMessageDeadPid_], |
475 nacl_mountfs: [this,this.handleMessageMountFs_], | 479 nacl_mountfs: [this,this.handleMessageMountFs_], |
476 }; | 480 }; |
477 | 481 |
478 // TODO(channingh): Once pinned applications support "result" instead of | 482 // TODO(channingh): Once pinned applications support "result" instead of |
479 // "pid", change calls to reply() to set "result." | 483 // "pid", change calls to reply() to set "result." |
480 function reply(contents) { | 484 function reply(contents) { |
481 var reply = {}; | 485 var message = {}; |
482 reply[msg['id']] = contents; | 486 message[msg['id']] = contents; |
483 // Enable to debug message stream (disabled for speed). | 487 // Enable to debug message stream (disabled for speed). |
484 // console.log(src.pid + '> reply: ' + JSON.stringify(reply)); | 488 // console.log(src.pid + '> reply: ' + JSON.stringify(reply)); |
485 src.postMessage(reply); | 489 src.postMessage(message); |
486 } | 490 } |
487 | 491 |
488 if (msg['command'] && handlers[msg['command']]) { | 492 if (msg['command'] && handlers[msg['command']]) { |
489 // Enable to debug message stream (disabled for speed). | 493 // Enable to debug message stream (disabled for speed). |
490 //console.log(src.pid + '> ' + msg['command'] + ': ' + JSON.stringify(msg)); | 494 //console.log(src.pid + '> ' + msg['command'] + ': ' + JSON.stringify(msg)); |
491 var handler = handlers[msg['command']]; | 495 var handler = handlers[msg['command']]; |
492 handler[1].call(handler[0], msg, reply, src); | 496 handler[1].call(handler[0], msg, reply, src); |
493 } else if (msg['mount_status'] == 'success') { | 497 } else if (msg['mount_status'] == 'success') { |
494 // TODO(gdeepti): Remove monitoring mount status with strings. | 498 // TODO(gdeepti): Remove monitoring mount status with strings. |
495 this.processes[src.pid].mounted = true; | 499 this.processes[src.pid].mounted = true; |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 * @param {number} sid The session ID of the session to which the process | 808 * @param {number} sid The session ID of the session to which the process |
805 * group belongs. | 809 * group belongs. |
806 */ | 810 */ |
807 NaClProcessManager.prototype.createProcessGroup_ = function(pid, sid) { | 811 NaClProcessManager.prototype.createProcessGroup_ = function(pid, sid) { |
808 if (this.processGroups[pid] !== undefined) { | 812 if (this.processGroups[pid] !== undefined) { |
809 throw new Error('createProcessGroup_(): process group already exists'); | 813 throw new Error('createProcessGroup_(): process group already exists'); |
810 } | 814 } |
811 this.processGroups[pid] = { | 815 this.processGroups[pid] = { |
812 sid: sid, | 816 sid: sid, |
813 processes: {} | 817 processes: {} |
814 } | 818 }; |
815 this.processGroups[pid].processes[pid] = true; | 819 this.processGroups[pid].processes[pid] = true; |
816 }; | 820 }; |
817 | 821 |
818 /** | 822 /** |
819 * Delete a process from the process group table. If a group has no more | 823 * Delete a process from the process group table. If a group has no more |
820 * processes, delete the group as well. | 824 * processes, delete the group as well. |
821 * @private | 825 * @private |
822 * @param {number} pid The process to be deleted. | 826 * @param {number} pid The process to be deleted. |
823 */ | 827 */ |
824 NaClProcessManager.prototype.deleteProcessFromGroup_ = function(pid) { | 828 NaClProcessManager.prototype.deleteProcessFromGroup_ = function(pid) { |
(...skipping 28 matching lines...) Expand all Loading... |
853 var pid = element.pid; | 857 var pid = element.pid; |
854 var ppid = this.processes[pid].ppid; | 858 var ppid = this.processes[pid].ppid; |
855 var pgid = this.processes[pid].pgid; | 859 var pgid = this.processes[pid].pgid; |
856 | 860 |
857 this.pipeServer.deleteProcess(pid); | 861 this.pipeServer.deleteProcess(pid); |
858 this.deleteProcessFromGroup_(pid); | 862 this.deleteProcessFromGroup_(pid); |
859 | 863 |
860 // Reply to processes waiting on the exited process. | 864 // Reply to processes waiting on the exited process. |
861 var waitersToCheck = [pid, -1, -pgid]; | 865 var waitersToCheck = [pid, -1, -pgid]; |
862 var reaped = false; | 866 var reaped = false; |
863 for (var i = 0; i < waitersToCheck.length; i++) { | 867 var waiters = this.waiters; |
864 var currPid = waitersToCheck[i]; | 868 waitersToCheck.forEach(function(currPid) { |
865 if (this.waiters[currPid] === undefined) { | 869 if (waiters[currPid] === undefined) { |
866 continue; | 870 return; |
867 } | 871 } |
868 var currPidWaiters = this.waiters[currPid]; | 872 var currPidWaiters = waiters[currPid]; |
869 for (var j = 0; j < currPidWaiters.length; j++) { | 873 for (var j = 0; j < currPidWaiters.length; j++) { |
870 var waiter = currPidWaiters[j]; | 874 var waiter = currPidWaiters[j]; |
871 if (waiter.srcPid === ppid) { | 875 if (waiter.srcPid === ppid) { |
872 waiter.reply(pid, code); | 876 waiter.reply(pid, code); |
873 reaped = true; | 877 reaped = true; |
874 } | 878 } |
875 } | 879 } |
876 this.waiters[currPid] = currPidWaiters.filter(function(waiter) { | 880 waiters[currPid] = currPidWaiters.filter(function(waiter) { |
877 return waiter.srcPid !== ppid; | 881 return waiter.srcPid !== ppid; |
878 }); | 882 }); |
879 if (this.waiters[currPid].length === 0) { | 883 if (waiters[currPid].length === 0) { |
880 delete this.waiters[currPid]; | 884 delete waiters[currPid]; |
881 } | 885 } |
882 } | 886 }); |
883 if (reaped) { | 887 if (reaped) { |
884 this.deleteProcessEntry_(pid); | 888 this.deleteProcessEntry_(pid); |
885 } else { | 889 } else { |
886 this.processes[pid].exitCode = code; | 890 this.processes[pid].exitCode = code; |
887 } | 891 } |
888 | 892 |
889 // Mark as terminated. | 893 // Mark as terminated. |
890 element.pid = -1; | 894 element.pid = -1; |
891 | 895 |
892 // Clean up HTML elements. | 896 // Clean up HTML elements. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 * @param {string} url The url to download and parse. | 939 * @param {string} url The url to download and parse. |
936 * @callback typeCallback Called with 'nacl' or 'pnacl' on success. | 940 * @callback typeCallback Called with 'nacl' or 'pnacl' on success. |
937 * @callback errorCallback Called with error message on failure. | 941 * @callback errorCallback Called with error message on failure. |
938 */ | 942 */ |
939 NaClProcessManager.prototype.checkUrlNaClManifestType = function( | 943 NaClProcessManager.prototype.checkUrlNaClManifestType = function( |
940 url, typeCallback, errorCallback) { | 944 url, typeCallback, errorCallback) { |
941 var self = this; | 945 var self = this; |
942 var request = new XMLHttpRequest(); | 946 var request = new XMLHttpRequest(); |
943 request.open('GET', url, true); | 947 request.open('GET', url, true); |
944 request.onload = function() { | 948 request.onload = function() { |
| 949 var manifest; |
945 try { | 950 try { |
946 var manifest = JSON.parse(request.responseText); | 951 manifest = JSON.parse(request.responseText); |
947 } catch(e) { | 952 } catch(e) { |
948 errorCallback('NaCl Manifest is not valid JSON at ' + url); | 953 errorCallback('NaCl Manifest is not valid JSON at ' + url); |
949 return; | 954 return; |
950 } | 955 } |
951 var kind = self.checkNaClManifestType_(manifest); | 956 var kind = self.checkNaClManifestType_(manifest); |
952 if (kind === null) { | 957 if (kind === null) { |
953 errorCallback('NaCl Manifest has bad format at ' + url); | 958 errorCallback('NaCl Manifest has bad format at ' + url); |
954 } else { | 959 } else { |
955 typeCallback(kind); | 960 typeCallback(kind); |
956 } | 961 } |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 | 1134 |
1130 // If the application has set NaClTerm.argv and there were | 1135 // If the application has set NaClTerm.argv and there were |
1131 // no arguments set in the query parameters then add the default | 1136 // no arguments set in the query parameters then add the default |
1132 // NaClTerm.argv arguments. | 1137 // NaClTerm.argv arguments. |
1133 // TODO(bradnelson): Consider dropping this method of passing in parameters. | 1138 // TODO(bradnelson): Consider dropping this method of passing in parameters. |
1134 if (args['arg0'] === undefined && args['arg1'] === undefined && argv) { | 1139 if (args['arg0'] === undefined && args['arg1'] === undefined && argv) { |
1135 var argn = 0; | 1140 var argn = 0; |
1136 argv.forEach(function(arg) { | 1141 argv.forEach(function(arg) { |
1137 var argname = 'arg' + argn; | 1142 var argname = 'arg' + argn; |
1138 addParam(argname, arg); | 1143 addParam(argname, arg); |
1139 argn = argn + 1 | 1144 argn = argn + 1; |
1140 }) | 1145 }); |
1141 } | 1146 } |
1142 | 1147 |
1143 self.pipeServer.addProcessPipes(fg.pid, params); | 1148 self.pipeServer.addProcessPipes(fg.pid, params); |
1144 | 1149 |
1145 if (params[NaClProcessManager.ENV_SPAWN_MODE] === | 1150 if (params[NaClProcessManager.ENV_SPAWN_MODE] === |
1146 NaClProcessManager.ENV_SPAWN_POPUP_VALUE) { | 1151 NaClProcessManager.ENV_SPAWN_POPUP_VALUE) { |
1147 var popup = new GraphicalPopup( | 1152 var popup = new GraphicalPopup( |
1148 fg, | 1153 fg, |
1149 parseInt(params[NaClProcessManager.ENV_POPUP_WIDTH] || | 1154 parseInt(params[NaClProcessManager.ENV_POPUP_WIDTH] || |
1150 NaClProcessManager.POPUP_WIDTH_DEFAULT), | 1155 NaClProcessManager.POPUP_WIDTH_DEFAULT), |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1255 } | 1260 } |
1256 } | 1261 } |
1257 | 1262 |
1258 if (finishedPid !== null) { | 1263 if (finishedPid !== null) { |
1259 reply(finishedPid, this.processes[finishedPid].exitCode); | 1264 reply(finishedPid, this.processes[finishedPid].exitCode); |
1260 this.deleteProcessEntry_(finishedPid); | 1265 this.deleteProcessEntry_(finishedPid); |
1261 return; | 1266 return; |
1262 } | 1267 } |
1263 } | 1268 } |
1264 | 1269 |
1265 if ((options & NaClProcessManager.WNOHANG) != 0) { | 1270 if ((options & NaClProcessManager.WNOHANG) !== 0) { |
1266 reply(0, 0); | 1271 reply(0, 0); |
1267 return; | 1272 return; |
1268 } | 1273 } |
1269 | 1274 |
1270 // Add the waitpid call to the waiter list. | 1275 // Add the waitpid call to the waiter list. |
1271 if (!this.waiters[pid]) { | 1276 if (!this.waiters[pid]) { |
1272 this.waiters[pid] = []; | 1277 this.waiters[pid] = []; |
1273 } | 1278 } |
1274 this.waiters[pid].push({ | 1279 this.waiters[pid].push({ |
1275 reply: reply, | 1280 reply: reply, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 * The (empty) HTML file to which the NaCl module is added. | 1364 * The (empty) HTML file to which the NaCl module is added. |
1360 * @const | 1365 * @const |
1361 */ | 1366 */ |
1362 GraphicalPopup.HTML_FILE = 'graphical.html'; | 1367 GraphicalPopup.HTML_FILE = 'graphical.html'; |
1363 | 1368 |
1364 /** | 1369 /** |
1365 * Focus the window in which this code is run. | 1370 * Focus the window in which this code is run. |
1366 */ | 1371 */ |
1367 GraphicalPopup.focusCurrentWindow = function() { | 1372 GraphicalPopup.focusCurrentWindow = function() { |
1368 chrome.app.window.current().focus(); | 1373 chrome.app.window.current().focus(); |
1369 } | 1374 }; |
1370 | 1375 |
1371 /** | 1376 /** |
1372 * This callback is called when the popup is closed. | 1377 * This callback is called when the popup is closed. |
1373 * @callback closedCallback | 1378 * @callback closedCallback |
1374 */ | 1379 */ |
1375 | 1380 |
1376 /** | 1381 /** |
1377 * Set a function to be called as a callback when the popup is closed. | 1382 * Set a function to be called as a callback when the popup is closed. |
1378 * @param {closedCallback} listener | 1383 * @param {closedCallback} listener |
1379 */ | 1384 */ |
1380 GraphicalPopup.prototype.setClosedListener = function(listener) { | 1385 GraphicalPopup.prototype.setClosedListener = function(listener) { |
1381 if (this.win) { | 1386 if (this.win) { |
1382 throw new Error("Cannot set closed listener after creating window."); | 1387 throw new Error("Cannot set closed listener after creating window."); |
1383 } | 1388 } |
1384 this.onClosed = listener; | 1389 this.onClosed = listener; |
1385 } | 1390 }; |
1386 | 1391 |
1387 /** | 1392 /** |
1388 * Create the window. | 1393 * Create the window. |
1389 */ | 1394 */ |
1390 GraphicalPopup.prototype.create = function() { | 1395 GraphicalPopup.prototype.create = function() { |
1391 var self = this; | 1396 var self = this; |
1392 chrome.app.window.create('graphical.html', { | 1397 chrome.app.window.create('graphical.html', { |
1393 'bounds': { | 1398 'bounds': { |
1394 'width': self.width, | 1399 'width': self.width, |
1395 'height': self.height | 1400 'height': self.height |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 GraphicalPopup.prototype.destroy = function() { | 1434 GraphicalPopup.prototype.destroy = function() { |
1430 if (this.win.contentWindow.focused) { | 1435 if (this.win.contentWindow.focused) { |
1431 GraphicalPopup.focusCurrentWindow(); | 1436 GraphicalPopup.focusCurrentWindow(); |
1432 } | 1437 } |
1433 this.win.onClosed.removeListener(this.onClosed); | 1438 this.win.onClosed.removeListener(this.onClosed); |
1434 this.win.close(); | 1439 this.win.close(); |
1435 | 1440 |
1436 this.process = null; | 1441 this.process = null; |
1437 this.win = null; | 1442 this.win = null; |
1438 }; | 1443 }; |
OLD | NEW |