This commit is contained in:
gorhill 2015-07-03 07:00:29 -04:00
parent 93c4502acc
commit 352ef808f1
3 changed files with 96 additions and 44 deletions

View file

@ -264,6 +264,9 @@ const contentObserver = {
};
sandbox.removeMessageListener = function() {
if ( !sandbox._messageListener_ ) {
return;
}
try {
messager.removeMessageListener(
sandbox._sandboxId_,
@ -280,6 +283,22 @@ const contentObserver = {
sandbox._messageListener_ = null;
};
// The goal is to have content scripts removed from web pages. This
// helps remove traces of uBlock from memory when disabling/removing
// the addon.
// For example, this takes care of:
// https://github.com/gorhill/uBlock/commit/ea4faff383789053f423498c1f1165c403fde7c7#commitcomment-11964137
// > "gets the whole selected tab flashing"
sandbox.shutdownSandbox = function() {
sandbox.removeMessageListener();
sandbox.addMessageListener =
sandbox.injectScript =
sandbox.removeMessageListener =
sandbox.sendAsyncMessage =
sandbox.shutdownSandbox = null;
messager = null;
};
return sandbox;
},

View file

@ -695,10 +695,6 @@ vAPI.tabs.open = function(details) {
return;
}
if ( details.index === -1 ) {
details.index = tabBrowser.browsers.indexOf(tabBrowser.selectedBrowser) + 1;
}
// Open in a standalone window
if ( details.popup === true ) {
Services.ww.openWindow(
@ -711,6 +707,10 @@ vAPI.tabs.open = function(details) {
return;
}
if ( details.index === -1 ) {
details.index = tabBrowser.browsers.indexOf(tabBrowser.selectedBrowser) + 1;
}
tab = tabBrowser.loadOneTab(details.url, { inBackground: !details.active });
if ( details.index !== undefined ) {
@ -1381,6 +1381,15 @@ vAPI.messaging.setup = function(defaultHandler) {
cleanupTasks.push(function() {
var gmm = vAPI.messaging.globalMessageManager;
gmm.broadcastAsyncMessage(
location.host + ':broadcast',
JSON.stringify({
broadcast: true,
channelName: 'vAPI',
msg: { cmd: 'shutdownSandbox' }
})
);
gmm.removeDelayedFrameScript(vAPI.messaging.frameScript);
gmm.removeMessageListener(
location.host + ':background',

View file

@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
/* global addMessageListener, removeMessageListener, sendAsyncMessage */
/* global addMessageListener, removeMessageListener, sendAsyncMessage, shutdownSandbox */
// For non background pages
@ -76,32 +76,43 @@ vAPI.messaging = {
messagingConnector(JSON.parse(msg));
},
setup: function() {
addMessageListener(this.connector);
this.connected = true;
this.channels['vAPI'] = new MessagingChannel('vAPI', function(msg) {
if ( msg.cmd === 'injectScript' ) {
var details = msg.details;
if ( !details.allFrames && window !== window.top ) {
return;
}
// TODO: investigate why this happens, and if this happens
// legitimately (content scripts not injected I suspect, so
// that would make this legitimate).
// Case: open popup UI from icon in uBlock's logger
if ( typeof self.injectScript === 'function' ) {
self.injectScript(details.file);
}
builtinChannelHandler: function(msg) {
if ( msg.cmd === 'injectScript' ) {
var details = msg.details;
if ( !details.allFrames && window !== window.top ) {
return;
}
});
// TODO: investigate why this happens, and if this happens
// legitimately (content scripts not injected I suspect, so
// that would make this legitimate).
// Case: open popup UI from icon in uBlock's logger
if ( typeof self.injectScript === 'function' ) {
self.injectScript(details.file);
}
return;
}
if ( msg.cmd === 'shutdownSandbox' ) {
vAPI.shutdown.exec();
vAPI.messaging.close();
window.removeEventListener('pagehide', vAPI.messaging.toggleListener, true);
window.removeEventListener('pageshow', vAPI.messaging.toggleListener, true);
vAPI.messaging = null;
vAPI = {};
shutdownSandbox();
return;
}
},
setup: function() {
this.channels['vAPI'] = new MessagingChannel('vAPI', this.builtinChannelHandler);
window.addEventListener('pagehide', this.toggleListener, true);
window.addEventListener('pageshow', this.toggleListener, true);
},
close: function() {
if ( !this.connected ) {
return;
}
removeMessageListener();
this.connected = false;
window.removeEventListener('pagehide', this.toggleListener, true);
window.removeEventListener('pageshow', this.toggleListener, true);
this.disconnect();
this.channels = {};
this.pending = {};
},
@ -120,25 +131,36 @@ vAPI.messaging = {
return channel;
},
connect: function() {
if ( !this.connected ) {
addMessageListener(this.connector);
this.connected = true;
}
},
disconnect: function() {
if ( this.connected ) {
removeMessageListener();
this.connected = false;
}
},
toggleListener: function({type, persisted}) {
if ( !vAPI.messaging.connected ) {
if ( !vAPI.messaging ) {
return;
}
if ( type === 'pagehide' ) {
removeMessageListener();
vAPI.messaging.disconnect();
return;
}
if ( persisted ) {
addMessageListener(vAPI.messaging.connector);
vAPI.messaging.connect();
}
}
};
window.addEventListener('pagehide', vAPI.messaging.toggleListener, true);
window.addEventListener('pageshow', vAPI.messaging.toggleListener, true);
/******************************************************************************/
var messagingConnector = function(details) {
@ -147,6 +169,12 @@ var messagingConnector = function(details) {
}
var messaging = vAPI.messaging;
// Sandbox might have been shutdown
if ( !messaging ) {
return;
}
var channels = messaging.channels;
var channel;
@ -195,10 +223,7 @@ var MessagingChannel = function(name, callback) {
this.listeners = typeof callback === 'function' ? [callback] : [];
this.refCount = 1;
if ( typeof callback === 'function' ) {
var messaging = vAPI.messaging;
if ( !messaging.connected ) {
messaging.setup();
}
vAPI.messaging.connect();
}
};
@ -208,9 +233,7 @@ MessagingChannel.prototype.send = function(message, callback) {
MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) {
var messaging = vAPI.messaging;
if ( !messaging.connected ) {
messaging.setup();
}
messaging.connect();
var auxProcessId;
if ( callback ) {
auxProcessId = messaging.auxProcessId++;
@ -241,10 +264,7 @@ MessagingChannel.prototype.addListener = function(callback) {
throw new Error('Duplicate listener.');
}
this.listeners.push(callback);
var messaging = vAPI.messaging;
if ( !messaging.connected ) {
messaging.setup();
}
vAPI.messaging.connect();
};
MessagingChannel.prototype.removeListener = function(callback) {
@ -278,6 +298,10 @@ MessagingChannel.prototype.sendToListeners = function(msg) {
/******************************************************************************/
vAPI.messaging.setup();
/******************************************************************************/
// No need to have vAPI client linger around after shutdown if
// we are not a top window (because element picker can still
// be injected in top window).