this probably fixes #453

This commit is contained in:
gorhill 2015-07-07 11:03:26 -04:00
parent 7a00310934
commit 32d2ae0e11
2 changed files with 68 additions and 11 deletions

View File

@ -40,7 +40,7 @@ if ( vAPI.vapiClientInjected ) {
} }
vAPI.vapiClientInjected = true; vAPI.vapiClientInjected = true;
vAPI.sessionId = String.fromCharCode(Date.now() % 25 + 97) + vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
Math.random().toString(36).slice(2); Math.random().toString(36).slice(2);
vAPI.chrome = true; vAPI.chrome = true;
@ -77,22 +77,44 @@ vAPI.messaging = {
port: null, port: null,
channels: {}, channels: {},
pending: {}, pending: {},
pendingCount: 0,
auxProcessId: 1, auxProcessId: 1,
setup: function() { setup: function() {
try {
this.port = chrome.runtime.connect({name: vAPI.sessionId}); this.port = chrome.runtime.connect({name: vAPI.sessionId});
} catch (ex) {
}
if ( this.port === null ) {
console.error("uBlock> Can't patch things up. It's over.");
vAPI.shutdown.exec();
return false;
}
this.port.onMessage.addListener(messagingConnector); this.port.onMessage.addListener(messagingConnector);
return true;
}, },
close: function() { close: function() {
if ( this.port === null ) { var port = this.port;
if ( port === null ) {
return; return;
} }
this.port.disconnect();
this.port.onMessage.removeListener(messagingConnector);
this.port = null; this.port = null;
port.disconnect();
port.onMessage.removeListener(messagingConnector);
this.channels = {}; this.channels = {};
// service pending callbacks
var pending = this.pending, listener;
this.pending = {}; this.pending = {};
this.pendingCount = 0;
for ( var auxId in pending ) {
if ( this.pending.hasOwnProperty(auxId) ) {
listener = pending[auxId];
if ( typeof listener === 'function' ) {
listener(null);
}
}
}
}, },
channel: function(channelName, callback) { channel: function(channelName, callback) {
@ -138,6 +160,7 @@ var messagingConnector = function(details) {
delete messaging.pending[details.auxProcessId]; delete messaging.pending[details.auxProcessId];
delete details.auxProcessId; // TODO: why? delete details.auxProcessId; // TODO: why?
if ( listener ) { if ( listener ) {
messaging.pendingCount -= 1;
listener(details.msg); listener(details.msg);
return; return;
} }
@ -161,11 +184,11 @@ var messagingConnector = function(details) {
/******************************************************************************/ /******************************************************************************/
var MessagingChannel = function(name, callback) { var MessagingChannel = function(name, listener) {
this.channelName = name; this.channelName = name;
this.listeners = typeof callback === 'function' ? [callback] : []; this.listeners = typeof listener === 'function' ? [listener] : [];
this.refCount = 1; this.refCount = 1;
if ( typeof callback === 'function' ) { if ( typeof listener === 'function' ) {
var messaging = vAPI.messaging; var messaging = vAPI.messaging;
if ( messaging.port === null ) { if ( messaging.port === null ) {
messaging.setup(); messaging.setup();
@ -179,13 +202,27 @@ MessagingChannel.prototype.send = function(message, callback) {
MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) { MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) {
var messaging = vAPI.messaging; var messaging = vAPI.messaging;
// Too large a gap between the last request and the last response means
// the main process is no longer reachable: memory leaks and bad
// performance become a risk -- especially for long-lived, dynamic
// pages. Guard against this.
if ( messaging.pendingCount > 25 ) {
console.error('uBlock> Sigh. Main process is sulking. Will try to patch things up.');
messaging.close();
}
if ( messaging.port === null ) { if ( messaging.port === null ) {
messaging.setup(); if ( messaging.setup() === false ) {
if ( typeof callback === 'function' ) {
callback();
}
return;
}
} }
var auxProcessId; var auxProcessId;
if ( callback ) { if ( callback ) {
auxProcessId = messaging.auxProcessId++; auxProcessId = messaging.auxProcessId++;
messaging.pending[auxProcessId] = callback; messaging.pending[auxProcessId] = callback;
messaging.pendingCount += 1;
} }
messaging.port.postMessage({ messaging.port.postMessage({
channelName: this.channelName, channelName: this.channelName,

View File

@ -70,6 +70,7 @@ vAPI.shutdown = (function() {
vAPI.messaging = { vAPI.messaging = {
channels: {}, channels: {},
pending: {}, pending: {},
pendingCount: 0,
auxProcessId: 1, auxProcessId: 1,
connected: false, connected: false,
connector: function(msg) { connector: function(msg) {
@ -114,11 +115,20 @@ vAPI.messaging = {
}, },
close: function() { close: function() {
window.removeEventListener('pagehide', this.toggleListener, true);
window.removeEventListener('pageshow', this.toggleListener, true);
this.disconnect(); this.disconnect();
this.channels = {}; this.channels = {};
// service pending callbacks
var pending = this.pending, listener;
this.pending = {}; this.pending = {};
this.pendingCount = 0;
for ( var auxId in pending ) {
if ( this.pending.hasOwnProperty(auxId) ) {
listener = pending[auxId];
if ( typeof listener === 'function' ) {
listener(null);
}
}
}
}, },
channel: function(channelName, callback) { channel: function(channelName, callback) {
@ -205,6 +215,7 @@ var messagingConnector = function(details) {
delete messaging.pending[details.auxProcessId]; delete messaging.pending[details.auxProcessId];
delete details.auxProcessId; // TODO: why? delete details.auxProcessId; // TODO: why?
if ( listener ) { if ( listener ) {
messaging.pendingCount -= 1;
listener(details.msg); listener(details.msg);
return; return;
} }
@ -243,11 +254,20 @@ MessagingChannel.prototype.send = function(message, callback) {
MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) { MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) {
var messaging = vAPI.messaging; var messaging = vAPI.messaging;
// Too large a gap between the last request and the last response means
// the main process is no longer reachable: memory leaks and bad
// performance become a risk -- especially for long-lived, dynamic
// pages. Guard against this.
if ( messaging.pendingCount > 25 ) {
console.error('uBlock> Sigh. Main process is sulking. Will try to patch things up.');
messaging.close();
}
messaging.connect(); messaging.connect();
var auxProcessId; var auxProcessId;
if ( callback ) { if ( callback ) {
auxProcessId = messaging.auxProcessId++; auxProcessId = messaging.auxProcessId++;
messaging.pending[auxProcessId] = callback; messaging.pending[auxProcessId] = callback;
messaging.pendingCount += 1;
} }
sendAsyncMessage('ublock0:background', { sendAsyncMessage('ublock0:background', {
channelName: self._sandboxId_ + '|' + this.channelName, channelName: self._sandboxId_ + '|' + this.channelName,