diff --git a/js/contentscript-end.js b/js/contentscript-end.js index bafa2bdb9..4c1801f83 100644 --- a/js/contentscript-end.js +++ b/js/contentscript-end.js @@ -30,7 +30,6 @@ var uBlockMessaging = (function(name){ var port = null; - var dangling = false; var requestId = 1; var requestIdToCallbackMap = {}; var listenCallback = null; @@ -50,9 +49,10 @@ var uBlockMessaging = (function(name){ if ( !callback ) { return; } - callback(details.msg); + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. delete requestIdToCallbackMap[details.id]; - checkDisconnect(); + callback(details.msg); }; var start = function(name) { @@ -67,20 +67,30 @@ var uBlockMessaging = (function(name){ ) }); port.onMessage.addListener(onPortMessage); - }; - if ( typeof name === 'string' && name.length > 0 ) { - start(name); - } + // https://github.com/gorhill/uBlock/issues/193 + port.onDisconnect.addListener(stop); + }; var stop = function() { listenCallback = null; - dangling = true; - checkDisconnect(); + port.disconnect(); + port = null; + flushCallbacks(); }; + if ( typeof name === 'string' && name !== '' ) { + start(name); + } + var ask = function(msg, callback) { - if ( !callback ) { + if ( port === null ) { + if ( typeof callback === 'function' ) { + callback(); + } + return; + } + if ( callback === undefined ) { tell(msg); return; } @@ -90,22 +100,30 @@ var uBlockMessaging = (function(name){ }; var tell = function(msg) { - port.postMessage({ id: 0, msg: msg }); + if ( port !== null ) { + port.postMessage({ id: 0, msg: msg }); + } }; var listen = function(callback) { listenCallback = callback; }; - var checkDisconnect = function() { - if ( !dangling ) { - return; + var flushCallbacks = function() { + var callback; + for ( id in requestIdToCallbackMap ) { + if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) { + continue; + } + callback = requestIdToCallbackMap[id]; + if ( !callback ) { + continue; + } + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. + delete requestIdToCallbackMap[id]; + callback(); } - if ( Object.keys(requestIdToCallbackMap).length ) { - return; - } - port.disconnect(); - port = null; }; return { diff --git a/js/contentscript-start.js b/js/contentscript-start.js index 2554bd19f..627205100 100644 --- a/js/contentscript-start.js +++ b/js/contentscript-start.js @@ -38,9 +38,8 @@ // https://github.com/gorhill/httpswitchboard/issues/345 -var messaging = (function(name){ +var uBlockMessaging = (function(name){ var port = null; - var dangling = false; var requestId = 1; var requestIdToCallbackMap = {}; var listenCallback = null; @@ -60,9 +59,10 @@ var messaging = (function(name){ if ( !callback ) { return; } - callback(details.msg); + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. delete requestIdToCallbackMap[details.id]; - checkDisconnect(); + callback(details.msg); }; var start = function(name) { @@ -77,20 +77,30 @@ var messaging = (function(name){ ) }); port.onMessage.addListener(onPortMessage); - }; - if ( typeof name === 'string' && name.length > 0 ) { - start(name); - } + // https://github.com/gorhill/uBlock/issues/193 + port.onDisconnect.addListener(stop); + }; var stop = function() { listenCallback = null; - dangling = true; - checkDisconnect(); + port.disconnect(); + port = null; + flushCallbacks(); }; + if ( typeof name === 'string' && name !== '' ) { + start(name); + } + var ask = function(msg, callback) { - if ( !callback ) { + if ( port === null ) { + if ( typeof callback === 'function' ) { + callback(); + } + return; + } + if ( callback === undefined ) { tell(msg); return; } @@ -100,22 +110,30 @@ var messaging = (function(name){ }; var tell = function(msg) { - port.postMessage({ id: 0, msg: msg }); + if ( port !== null ) { + port.postMessage({ id: 0, msg: msg }); + } }; var listen = function(callback) { listenCallback = callback; }; - var checkDisconnect = function() { - if ( !dangling ) { - return; + var flushCallbacks = function() { + var callback; + for ( id in requestIdToCallbackMap ) { + if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) { + continue; + } + callback = requestIdToCallbackMap[id]; + if ( !callback ) { + continue; + } + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. + delete requestIdToCallbackMap[id]; + callback(); } - if ( Object.keys(requestIdToCallbackMap).length ) { - return; - } - port.disconnect(); - port = null; }; return { @@ -189,6 +207,9 @@ var netFilters = function(details) { }; var filteringHandler = function(details) { + // The port will never be used again at this point, disconnecting allows + // the browser to flush this script from memory. + uBlockMessaging.stop(); if ( !details ) { return; } @@ -213,7 +234,7 @@ var hideElements = function(selectors) { } }; -messaging.ask( +uBlockMessaging.ask( { what: 'retrieveDomainCosmeticSelectors', pageURL: window.location.href, @@ -225,14 +246,6 @@ messaging.ask( /******************************************************************************/ /******************************************************************************/ -// The port will never be used again at this point, disconnecting allows -// the browser to flush this script from memory. - -messaging.stop(); - -/******************************************************************************/ -/******************************************************************************/ - })(); /******************************************************************************/ diff --git a/js/element-picker.js b/js/element-picker.js index be05c0269..c818a296b 100644 --- a/js/element-picker.js +++ b/js/element-picker.js @@ -117,7 +117,6 @@ var messaging = (function(name){ var port = null; - var dangling = false; var requestId = 1; var requestIdToCallbackMap = {}; var listenCallback = null; @@ -137,9 +136,10 @@ var messaging = (function(name){ if ( !callback ) { return; } - callback(details.msg); + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. delete requestIdToCallbackMap[details.id]; - checkDisconnect(); + callback(details.msg); }; var start = function(name) { @@ -154,20 +154,30 @@ var messaging = (function(name){ ) }); port.onMessage.addListener(onPortMessage); - }; - if ( typeof name === 'string' && name.length > 0 ) { - start(name); - } + // https://github.com/gorhill/uBlock/issues/193 + port.onDisconnect.addListener(stop); + }; var stop = function() { listenCallback = null; - dangling = true; - checkDisconnect(); + port.disconnect(); + port = null; + flushCallbacks(); }; + if ( typeof name === 'string' && name !== '' ) { + start(name); + } + var ask = function(msg, callback) { - if ( !callback ) { + if ( port === null ) { + if ( typeof callback === 'function' ) { + callback(); + } + return; + } + if ( callback === undefined ) { tell(msg); return; } @@ -177,22 +187,30 @@ var messaging = (function(name){ }; var tell = function(msg) { - port.postMessage({ id: 0, msg: msg }); + if ( port !== null ) { + port.postMessage({ id: 0, msg: msg }); + } }; var listen = function(callback) { listenCallback = callback; }; - var checkDisconnect = function() { - if ( !dangling ) { - return; + var flushCallbacks = function() { + var callback; + for ( id in requestIdToCallbackMap ) { + if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) { + continue; + } + callback = requestIdToCallbackMap[id]; + if ( !callback ) { + continue; + } + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. + delete requestIdToCallbackMap[id]; + callback(); } - if ( Object.keys(requestIdToCallbackMap).length ) { - return; - } - port.disconnect(); - port = null; }; return { diff --git a/js/messaging-client.js b/js/messaging-client.js index 740c53a5b..a9313f0be 100644 --- a/js/messaging-client.js +++ b/js/messaging-client.js @@ -42,7 +42,6 @@ var messaging = (function(name){ var port = null; - var dangling = false; var requestId = 1; var requestIdToCallbackMap = {}; var listenCallback = null; @@ -62,9 +61,10 @@ var messaging = (function(name){ if ( !callback ) { return; } - callback(details.msg); + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. delete requestIdToCallbackMap[details.id]; - checkDisconnect(); + callback(details.msg); }; var start = function(name) { @@ -79,20 +79,30 @@ var messaging = (function(name){ ) }); port.onMessage.addListener(onPortMessage); - }; - if ( typeof name === 'string' && name.length > 0 ) { - start(name); - } + // https://github.com/gorhill/uBlock/issues/193 + port.onDisconnect.addListener(stop); + }; var stop = function() { listenCallback = null; - dangling = true; - checkDisconnect(); + port.disconnect(); + port = null; + flushCallbacks(); }; + if ( typeof name === 'string' && name !== '' ) { + start(name); + } + var ask = function(msg, callback) { - if ( !callback ) { + if ( port === null ) { + if ( typeof callback === 'function' ) { + callback(); + } + return; + } + if ( callback === undefined ) { tell(msg); return; } @@ -102,22 +112,30 @@ var messaging = (function(name){ }; var tell = function(msg) { - port.postMessage({ id: 0, msg: msg }); + if ( port !== null ) { + port.postMessage({ id: 0, msg: msg }); + } }; var listen = function(callback) { listenCallback = callback; }; - var checkDisconnect = function() { - if ( !dangling ) { - return; + var flushCallbacks = function() { + var callback; + for ( id in requestIdToCallbackMap ) { + if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) { + continue; + } + callback = requestIdToCallbackMap[id]; + if ( !callback ) { + continue; + } + // Must be removed before calling client to be sure to not execute + // callback again if the client stops the messaging service. + delete requestIdToCallbackMap[id]; + callback(); } - if ( Object.keys(requestIdToCallbackMap).length ) { - return; - } - port.disconnect(); - port = null; }; return {