Skip to content

Commit 614f717

Browse files
committed
Merge pull request #27 from c-f-h/fix-chrome-starttls
Fix native STARTTLS for Chrome Apps
2 parents a7fa84c + 6e00b2c commit 614f717

File tree

1 file changed

+54
-3
lines changed

1 file changed

+54
-3
lines changed

src/emailjs-tcp-socket.js

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,49 @@
386386
}
387387

388388
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+
389432
TCPSocket = function(config) {
390433
var self = this;
391434

@@ -561,7 +604,7 @@
561604
// invoked after chrome.socket.secure or chrome.sockets.tcp.secure have been upgraded
562605
function onUpgraded(tlsResult) {
563606
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));
565608
self.close();
566609
return;
567610
}
@@ -619,8 +662,16 @@
619662
// process the data available on the socket
620663
self._onData(readInfo.data);
621664

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+
}
624675
});
625676
};
626677

0 commit comments

Comments
 (0)