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 /* globals lib, NaClProcessManager, hterm */ |
| 8 |
7 'use strict'; | 9 'use strict'; |
8 | 10 |
9 lib.rtdep('lib.f', | 11 lib.rtdep('lib.f', |
10 'hterm', | 12 'hterm', |
11 'NaClProcessManager'); | 13 'NaClProcessManager'); |
12 | 14 |
13 // CSP means that we can't kick off the initialization from the html file, | 15 // CSP means that we can't kick off the initialization from the html file, |
14 // so we do it like this instead. | 16 // so we do it like this instead. |
15 window.onload = function() { | 17 window.onload = function() { |
16 lib.init(function() { | 18 lib.init(function() { |
(...skipping 20 matching lines...) Expand all Loading... |
37 // Has the initial process finished loading? | 39 // Has the initial process finished loading? |
38 this.loaded = false; | 40 this.loaded = false; |
39 | 41 |
40 this.print = this.io.print.bind(this.io); | 42 this.print = this.io.print.bind(this.io); |
41 | 43 |
42 var mgr = this.processManager = new NaClProcessManager(); | 44 var mgr = this.processManager = new NaClProcessManager(); |
43 mgr.setStdoutListener(this.handleStdout_.bind(this)); | 45 mgr.setStdoutListener(this.handleStdout_.bind(this)); |
44 mgr.setErrorListener(this.handleError_.bind(this)); | 46 mgr.setErrorListener(this.handleError_.bind(this)); |
45 mgr.setRootProgressListener(this.handleRootProgress_.bind(this)); | 47 mgr.setRootProgressListener(this.handleRootProgress_.bind(this)); |
46 mgr.setRootLoadListener(this.handleRootLoad_.bind(this)); | 48 mgr.setRootLoadListener(this.handleRootLoad_.bind(this)); |
47 }; | 49 } |
48 | 50 |
49 /** | 51 /** |
50 * Flag for cyan coloring in the terminal. | 52 * Flag for cyan coloring in the terminal. |
51 * @const | 53 * @const |
52 */ | 54 */ |
53 NaClTerm.ANSI_CYAN = '\x1b[36m'; | 55 NaClTerm.ANSI_CYAN = '\x1b[36m'; |
54 | 56 |
55 /** | 57 /** |
56 * Flag for color reset in the terminal. | 58 * Flag for color reset in the terminal. |
57 * @const | 59 * @const |
58 */ | 60 */ |
59 NaClTerm.ANSI_RESET = '\x1b[0m'; | 61 NaClTerm.ANSI_RESET = '\x1b[0m'; |
60 | 62 |
61 /* | 63 /* |
62 * Character code for Control+C in the terminal. | 64 * Character code for Control+C in the terminal. |
63 * @type {number} | 65 * @type {number} |
64 */ | 66 */ |
65 NaClTerm.CONTROL_C = 3; | 67 NaClTerm.CONTROL_C = 3; |
66 | 68 |
67 /** | 69 /** |
68 * Add the appropriate hooks to HTerm to start the session. | 70 * Add the appropriate hooks to HTerm to start the session. |
69 */ | 71 */ |
70 NaClTerm.prototype.run = function() { | 72 NaClTerm.prototype.run = function() { |
71 this.io.onVTKeystroke = this.onVTKeystroke_.bind(this); | 73 this.io.onVTKeystroke = this.onVTKeystroke_.bind(this); |
72 this.io.sendString = this.onVTKeystroke_.bind(this); | 74 this.io.sendString = this.onVTKeystroke_.bind(this); |
73 this.io.onTerminalResize = this.onTerminalResize_.bind(this); | 75 this.io.onTerminalResize = this.onTerminalResize_.bind(this); |
74 | 76 |
75 this.print(NaClTerm.ANSI_CYAN); | 77 this.print(NaClTerm.ANSI_CYAN); |
76 } | 78 }; |
77 | 79 |
78 /** | 80 /** |
79 * Static initializer called from index.html. | 81 * Static initializer called from index.html. |
80 * | 82 * |
81 * This constructs a new Terminal instance and instructs it to run a NaClTerm. | 83 * This constructs a new Terminal instance and instructs it to run a NaClTerm. |
82 */ | 84 */ |
83 NaClTerm.init = function() { | 85 NaClTerm.init = function() { |
84 var profileName = lib.f.parseQuery(document.location.search)['profile']; | 86 var profileName = lib.f.parseQuery(document.location.search)['profile']; |
85 var terminal = new hterm.Terminal(profileName); | 87 var terminal = new hterm.Terminal(profileName); |
86 terminal.decorate(document.querySelector('#terminal')); | 88 terminal.decorate(document.querySelector('#terminal')); |
(...skipping 25 matching lines...) Expand all Loading... |
112 * Handle stdout event from NaClProcessManager. | 114 * Handle stdout event from NaClProcessManager. |
113 * @private | 115 * @private |
114 * @param {string} msg The string sent to stdout. | 116 * @param {string} msg The string sent to stdout. |
115 */ | 117 */ |
116 NaClTerm.prototype.handleStdout_ = function(msg) { | 118 NaClTerm.prototype.handleStdout_ = function(msg) { |
117 if (!this.loaded) { | 119 if (!this.loaded) { |
118 this.bufferedOutput += msg; | 120 this.bufferedOutput += msg; |
119 } else { | 121 } else { |
120 this.print(msg); | 122 this.print(msg); |
121 } | 123 } |
122 } | 124 }; |
123 | 125 |
124 /** | 126 /** |
125 * Handle error event from NaCl. | 127 * Handle error event from NaCl. |
126 * @private | 128 * @private |
127 * @param {string} cmd The name of the process with the error. | 129 * @param {string} cmd The name of the process with the error. |
128 * @param {string} err The error message. | 130 * @param {string} err The error message. |
129 */ | 131 */ |
130 NaClTerm.prototype.handleError_ = function(cmd, err) { | 132 NaClTerm.prototype.handleError_ = function(cmd, err) { |
131 this.print(cmd + ': ' + err + '\n'); | 133 this.print(cmd + ': ' + err + '\n'); |
132 } | 134 }; |
133 | 135 |
134 /** | 136 /** |
135 * Notify the user when we are done loading a URL. | 137 * Notify the user when we are done loading a URL. |
136 * @private | 138 * @private |
137 */ | 139 */ |
138 NaClTerm.prototype.doneLoadingUrl_ = function() { | 140 NaClTerm.prototype.doneLoadingUrl_ = function() { |
139 var width = this.width; | 141 var width = this.width; |
140 this.print('\r' + Array(width+1).join(' ')); | 142 this.print('\r' + new Array(width+1).join(' ')); |
141 var message = '\rLoaded ' + this.lastUrl; | 143 var message = '\rLoaded ' + this.lastUrl; |
142 if (this.lastTotal) { | 144 if (this.lastTotal) { |
143 var kbsize = Math.round(this.lastTotal/1024) | 145 var kbsize = Math.round(this.lastTotal/1024); |
144 message += ' ['+ kbsize + ' KiB]'; | 146 message += ' ['+ kbsize + ' KiB]'; |
145 } | 147 } |
146 this.print(message.slice(0, width) + '\n') | 148 this.print(message.slice(0, width) + '\n'); |
147 } | 149 }; |
148 | 150 |
149 /** | 151 /** |
150 * Handle load progress event from NaCl for the root process. | 152 * Handle load progress event from NaCl for the root process. |
151 * @private | 153 * @private |
152 * @param {string} url The URL that is being loaded. | 154 * @param {string} url The URL that is being loaded. |
153 * @param {boolean} lengthComputable Is our progress quantitatively measurable? | 155 * @param {boolean} lengthComputable Is our progress quantitatively measurable? |
154 * @param {number} loaded The number of bytes that have been loaded. | 156 * @param {number} loaded The number of bytes that have been loaded. |
155 * @param {number} total The total number of bytes to be loaded. | 157 * @param {number} total The total number of bytes to be loaded. |
156 */ | 158 */ |
157 NaClTerm.prototype.handleRootProgress_ = function( | 159 NaClTerm.prototype.handleRootProgress_ = function( |
158 url, lengthComputable, loaded, total) { | 160 url, lengthComputable, loaded, total) { |
159 if (url !== undefined) | 161 if (url !== undefined) |
160 url = url.substring(url.lastIndexOf('/') + 1); | 162 url = url.substring(url.lastIndexOf('/') + 1); |
161 | 163 |
162 if (this.lastUrl && this.lastUrl !== url) | 164 if (this.lastUrl && this.lastUrl !== url) |
163 this.doneLoadingUrl_() | 165 this.doneLoadingUrl_(); |
164 | 166 |
165 if (!url) | 167 if (!url) |
166 return; | 168 return; |
167 | 169 |
168 this.lastUrl = url; | 170 this.lastUrl = url; |
169 this.lastTotal = total; | 171 this.lastTotal = total; |
170 | 172 |
171 var message = 'Loading ' + url; | 173 var message = 'Loading ' + url; |
172 if (lengthComputable && total) { | 174 if (lengthComputable && total) { |
173 var percent = Math.round(loaded * 100 / total); | 175 var percent = Math.round(loaded * 100 / total); |
174 var kbloaded = Math.round(loaded / 1024); | 176 var kbloaded = Math.round(loaded / 1024); |
175 var kbtotal = Math.round(total / 1024); | 177 var kbtotal = Math.round(total / 1024); |
176 message += ' [' + kbloaded + ' KiB/' + kbtotal + ' KiB ' + percent + '%]'; | 178 message += ' [' + kbloaded + ' KiB/' + kbtotal + ' KiB ' + percent + '%]'; |
177 } | 179 } |
178 | 180 |
179 this.print('\r' + message.slice(-this.width)); | 181 this.print('\r' + message.slice(-this.width)); |
180 } | 182 }; |
181 | 183 |
182 /** | 184 /** |
183 * Handle load end event from NaCl for the root process. | 185 * Handle load end event from NaCl for the root process. |
184 * @private | 186 * @private |
185 */ | 187 */ |
186 NaClTerm.prototype.handleRootLoad_ = function() { | 188 NaClTerm.prototype.handleRootLoad_ = function() { |
187 if (this.lastUrl) | 189 if (this.lastUrl) |
188 this.doneLoadingUrl_(); | 190 this.doneLoadingUrl_(); |
189 else | 191 else |
190 this.print('Loaded.\n'); | 192 this.print('Loaded.\n'); |
191 | 193 |
192 this.print(NaClTerm.ANSI_RESET); | 194 this.print(NaClTerm.ANSI_RESET); |
193 | 195 |
194 // Now that have completed loading and displaying | 196 // Now that have completed loading and displaying |
195 // loading messages we output any messages from the | 197 // loading messages we output any messages from the |
196 // NaCl module that were buffered up unto this point | 198 // NaCl module that were buffered up unto this point |
197 this.loaded = true; | 199 this.loaded = true; |
198 this.print(this.bufferedOutput); | 200 this.print(this.bufferedOutput); |
199 this.bufferedOutput = ''; | 201 this.bufferedOutput = ''; |
200 } | 202 }; |
201 | 203 |
202 /** | 204 /** |
203 * Clean up once the root process exits. | 205 * Clean up once the root process exits. |
204 * @private | 206 * @private |
205 * @param {number} pid The PID of the process that exited. | 207 * @param {number} pid The PID of the process that exited. |
206 * @param {number} status The exit code of the process. | 208 * @param {number} status The exit code of the process. |
207 */ | 209 */ |
208 NaClTerm.prototype.handleExit_ = function(pid, status) { | 210 NaClTerm.prototype.handleExit_ = function(pid, status) { |
209 this.print(NaClTerm.ANSI_CYAN) | 211 this.print(NaClTerm.ANSI_CYAN); |
210 | 212 |
211 // The root process finished. | 213 // The root process finished. |
212 if (status === -1) { | 214 if (status === -1) { |
213 this.print('Program (' + NaClTerm.nmf + | 215 this.print('Program (' + NaClTerm.nmf + |
214 ') crashed (exit status -1)\n'); | 216 ') crashed (exit status -1)\n'); |
215 } else { | 217 } else { |
216 this.print('Program (' + NaClTerm.nmf + ') exited ' + | 218 this.print('Program (' + NaClTerm.nmf + ') exited ' + |
217 '(status=' + status + ')\n'); | 219 '(status=' + status + ')\n'); |
218 } | 220 } |
219 this.argv.io.pop(); | 221 this.argv.io.pop(); |
220 // Remove window close handler. | 222 // Remove window close handler. |
221 window.onbeforeunload = function() { return null; }; | 223 window.onbeforeunload = function() { return null; }; |
222 if (this.argv.onExit) { | 224 if (this.argv.onExit) { |
223 this.argv.onExit(status); | 225 this.argv.onExit(status); |
224 } | 226 } |
225 } | 227 }; |
226 | 228 |
227 /** | 229 /** |
228 * Spawn the root process (usually bash). | 230 * Spawn the root process (usually bash). |
229 * @private | 231 * @private |
230 * | 232 * |
231 * We delay this call until the first terminal resize event so that we start | 233 * We delay this call until the first terminal resize event so that we start |
232 * with the correct size. | 234 * with the correct size. |
233 */ | 235 */ |
234 NaClTerm.prototype.spawnRootProcess_ = function() { | 236 NaClTerm.prototype.spawnRootProcess_ = function() { |
235 var self = this; | 237 var self = this; |
(...skipping 17 matching lines...) Expand all Loading... |
253 var handleFailure = function(message) { | 255 var handleFailure = function(message) { |
254 self.print(message); | 256 self.print(message); |
255 }; | 257 }; |
256 self.processManager.checkUrlNaClManifestType( | 258 self.processManager.checkUrlNaClManifestType( |
257 NaClTerm.nmf, handleSuccess, handleFailure); | 259 NaClTerm.nmf, handleSuccess, handleFailure); |
258 } catch (e) { | 260 } catch (e) { |
259 self.print(e.message); | 261 self.print(e.message); |
260 } | 262 } |
261 | 263 |
262 self.started = true; | 264 self.started = true; |
263 } | 265 }; |
264 | 266 |
265 /** | 267 /** |
266 * Handle hterm terminal resize events. | 268 * Handle hterm terminal resize events. |
267 * @private | 269 * @private |
268 * @param {number} width The width of the terminal. | 270 * @param {number} width The width of the terminal. |
269 * @param {number} height The height of the terminal. | 271 * @param {number} height The height of the terminal. |
270 */ | 272 */ |
271 NaClTerm.prototype.onTerminalResize_ = function(width, height) { | 273 NaClTerm.prototype.onTerminalResize_ = function(width, height) { |
272 this.processManager.onTerminalResize(width, height); | 274 this.processManager.onTerminalResize(width, height); |
273 if (!this.started) { | 275 if (!this.started) { |
274 this.spawnRootProcess_(); | 276 this.spawnRootProcess_(); |
275 } | 277 } |
276 } | 278 }; |
277 | 279 |
278 /** | 280 /** |
279 * Handle hterm keystroke events. | 281 * Handle hterm keystroke events. |
280 * @private | 282 * @private |
281 * @param {string} str The characters sent by hterm. | 283 * @param {string} str The characters sent by hterm. |
282 */ | 284 */ |
283 NaClTerm.prototype.onVTKeystroke_ = function(str) { | 285 NaClTerm.prototype.onVTKeystroke_ = function(str) { |
284 try { | 286 try { |
285 if (str.charCodeAt(0) === NaClTerm.CONTROL_C) { | 287 if (str.charCodeAt(0) === NaClTerm.CONTROL_C) { |
286 if (this.processManager.sigint()) { | 288 if (this.processManager.sigint()) { |
287 this.print('\n'); | 289 this.print('\n'); |
288 return; | 290 return; |
289 } | 291 } |
290 } | 292 } |
291 this.processManager.sendStdinForeground(str); | 293 this.processManager.sendStdinForeground(str); |
292 } catch (e) { | 294 } catch (e) { |
293 this.print(e.message); | 295 this.print(e.message); |
294 } | 296 } |
295 } | 297 }; |
OLD | NEW |