|
386 | 386 | }
|
387 | 387 |
|
388 | 388 | function chromeShim() {
|
| 389 | + |
| 390 | + // setZeroTimeout slightly adapted from |
| 391 | + // https://github.com/shahyar/setZeroTimeout-js (CC BY 3.0). |
| 392 | + // Provides a function similar to setImmediate() on Chrome. |
| 393 | + var setZeroTimeout = (function (w) { |
| 394 | + var timeouts = [], |
| 395 | + msg_name = 'asc0tmot', |
| 396 | + |
| 397 | + // Like setTimeout, but only takes a function argument. There's |
| 398 | + // no time argument (always zero) and no arguments (you have to |
| 399 | + // use a closure). |
| 400 | + _postTimeout = function (fn) { |
| 401 | + timeouts.push(fn); |
| 402 | + postMessage(msg_name, '*'); |
| 403 | + }, |
| 404 | + |
| 405 | + _handleMessage = function (event) { |
| 406 | + if (event.source === w && event.data === msg_name) { |
| 407 | + if (event.stopPropagation) { |
| 408 | + event.stopPropagation(); |
| 409 | + } |
| 410 | + if (timeouts.length) { |
| 411 | + try { |
| 412 | + timeouts.shift()(); |
| 413 | + } catch (e) { |
| 414 | + // Throw in an asynchronous closure to prevent setZeroTimeout from hanging due to error |
| 415 | + setTimeout((function (e) { |
| 416 | + return function () { |
| 417 | + throw e.stack || e; |
| 418 | + }; |
| 419 | + }(e)), 0); |
| 420 | + } |
| 421 | + } |
| 422 | + if (timeouts.length) { // more left? |
| 423 | + postMessage(msg_name, '*'); |
| 424 | + } |
| 425 | + } |
| 426 | + }; |
| 427 | + |
| 428 | + addEventListener('message', _handleMessage, true); |
| 429 | + return _postTimeout; |
| 430 | + }(window)); |
| 431 | + |
389 | 432 | TCPSocket = function(config) {
|
390 | 433 | var self = this;
|
391 | 434 |
|
|
561 | 604 | // invoked after chrome.socket.secure or chrome.sockets.tcp.secure have been upgraded
|
562 | 605 | function onUpgraded(tlsResult) {
|
563 | 606 | if (tlsResult !== 0) {
|
564 |
| - self._emit('error', new Error('TLS handshake failed. Reason: ' + chrome.runtime.lastError)); |
| 607 | + self._emit('error', new Error('TLS handshake failed. Reason: ' + chrome.runtime.lastError.message)); |
565 | 608 | self.close();
|
566 | 609 | return;
|
567 | 610 | }
|
|
619 | 662 | // process the data available on the socket
|
620 | 663 | self._onData(readInfo.data);
|
621 | 664 |
|
622 |
| - // queue the next read |
623 |
| - self._readLegacySocket(); |
| 665 | + // Queue the next read. |
| 666 | + // If a STARTTLS handshake might be upcoming, postpone this onto |
| 667 | + // the task queue so the IMAP client has a chance to call upgradeToSecure; |
| 668 | + // without this, we might eat the beginning of the handshake. |
| 669 | + // If we are already secure, just call it (for performance). |
| 670 | + if (self.ssl) { // are we secure yet? |
| 671 | + self._readLegacySocket(); |
| 672 | + } else { |
| 673 | + setZeroTimeout(self._readLegacySocket.bind(self)); |
| 674 | + } |
624 | 675 | });
|
625 | 676 | };
|
626 | 677 |
|
|
0 commit comments