Self-destruct orphaned content scripts

This commit is contained in:
tophf 2017-03-15 16:11:33 +03:00
parent e658255c36
commit 59e0f3f45e

View File

@ -1,3 +1,6 @@
// using ES5 syntax because ES6 is fast only since around Chrome 55
// so we'll wait until Chrome 60 arguably before converting
var g_disableAll = false;
var g_styleElements = {};
var iframeObserver;
@ -266,7 +269,13 @@ function replaceAll(newStyles, doc, pass2) {
// Observe dynamic IFRAMEs being added
function initObserver() {
var orphanCheckTimer;
iframeObserver = new MutationObserver(function(mutations) {
clearTimeout(orphanCheckTimer);
// MutationObserver runs as a microtask so the timer won't fire until all queued mutations are fired
orphanCheckTimer = setTimeout(orphanCheck, 0);
if (mutations.length > 1000) {
// use a much faster method for very complex pages with 100,000 mutations
// (observer usually receives 1k-10k mutations per call)
@ -297,4 +306,31 @@ function initObserver() {
// will be ignored by browser if already observing
iframeObserver.observe(document, {childList: true, subtree: true});
}
function orphanCheck() {
orphanCheckTimer = 0;
var port = chrome.runtime.connect();
if (port) {
port.disconnect();
return;
}
// we're orphaned due to an extension update
// we can detach the mutation observer
// we can't detach chrome.runtime.onMessage because it's no longer connected internally
iframeObserver.disconnect();
// we can destroy global functions in this context to free up memory
var globals = Object.keys(window);
for (var i = 0, len = globals.length; i < len; i++) {
var key = globals[i];
var obj = window[key];
if (typeof obj == 'function' && !/native code/.test(obj)) {
window[key] = null;
}
}
// we can destroy global variables
g_styleElements = iframeObserver = retiredStyleIds = null;
}
}