| 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 |