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() { sandbox.removeMessageListener = function() {
if ( !sandbox._messageListener_ ) {
return;
}
try { try {
messager.removeMessageListener( messager.removeMessageListener(
sandbox._sandboxId_, sandbox._sandboxId_,
@ -280,6 +283,22 @@ const contentObserver = {
sandbox._messageListener_ = null; 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; return sandbox;
}, },

View File

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

View File

@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock Home: https://github.com/gorhill/uBlock
*/ */
/* global addMessageListener, removeMessageListener, sendAsyncMessage */ /* global addMessageListener, removeMessageListener, sendAsyncMessage, shutdownSandbox */
// For non background pages // For non background pages
@ -76,32 +76,43 @@ vAPI.messaging = {
messagingConnector(JSON.parse(msg)); messagingConnector(JSON.parse(msg));
}, },
setup: function() { builtinChannelHandler: function(msg) {
addMessageListener(this.connector); if ( msg.cmd === 'injectScript' ) {
this.connected = true; var details = msg.details;
this.channels['vAPI'] = new MessagingChannel('vAPI', function(msg) { if ( !details.allFrames && window !== window.top ) {
if ( msg.cmd === 'injectScript' ) { return;
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);
}
} }
}); // 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() { close: function() {
if ( !this.connected ) { window.removeEventListener('pagehide', this.toggleListener, true);
return; window.removeEventListener('pageshow', this.toggleListener, true);
} this.disconnect();
removeMessageListener();
this.connected = false;
this.channels = {}; this.channels = {};
this.pending = {}; this.pending = {};
}, },
@ -120,25 +131,36 @@ vAPI.messaging = {
return channel; 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}) { toggleListener: function({type, persisted}) {
if ( !vAPI.messaging.connected ) { if ( !vAPI.messaging ) {
return; return;
} }
if ( type === 'pagehide' ) { if ( type === 'pagehide' ) {
removeMessageListener(); vAPI.messaging.disconnect();
return; return;
} }
if ( persisted ) { 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) { var messagingConnector = function(details) {
@ -147,6 +169,12 @@ var messagingConnector = function(details) {
} }
var messaging = vAPI.messaging; var messaging = vAPI.messaging;
// Sandbox might have been shutdown
if ( !messaging ) {
return;
}
var channels = messaging.channels; var channels = messaging.channels;
var channel; var channel;
@ -195,10 +223,7 @@ var MessagingChannel = function(name, callback) {
this.listeners = typeof callback === 'function' ? [callback] : []; this.listeners = typeof callback === 'function' ? [callback] : [];
this.refCount = 1; this.refCount = 1;
if ( typeof callback === 'function' ) { if ( typeof callback === 'function' ) {
var messaging = vAPI.messaging; vAPI.messaging.connect();
if ( !messaging.connected ) {
messaging.setup();
}
} }
}; };
@ -208,9 +233,7 @@ 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;
if ( !messaging.connected ) { messaging.connect();
messaging.setup();
}
var auxProcessId; var auxProcessId;
if ( callback ) { if ( callback ) {
auxProcessId = messaging.auxProcessId++; auxProcessId = messaging.auxProcessId++;
@ -241,10 +264,7 @@ MessagingChannel.prototype.addListener = function(callback) {
throw new Error('Duplicate listener.'); throw new Error('Duplicate listener.');
} }
this.listeners.push(callback); this.listeners.push(callback);
var messaging = vAPI.messaging; vAPI.messaging.connect();
if ( !messaging.connected ) {
messaging.setup();
}
}; };
MessagingChannel.prototype.removeListener = function(callback) { 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 // No need to have vAPI client linger around after shutdown if
// we are not a top window (because element picker can still // we are not a top window (because element picker can still
// be injected in top window). // be injected in top window).