From be3e86e055f05e80bdc7c98804e9c2cb1a616872 Mon Sep 17 00:00:00 2001 From: gorhill Date: Sat, 2 May 2015 18:33:55 -0400 Subject: [PATCH] user is responsible to reload + fixed cleanup of stale tabs --- platform/chromium/vapi-background.js | 10 +- src/js/background.js | 1 - src/js/commands.js | 5 +- src/js/messaging.js | 16 --- src/js/popup.js | 4 + src/js/settings.js | 4 - src/js/storage.js | 8 -- src/js/tab.js | 200 ++++++--------------------- 8 files changed, 54 insertions(+), 194 deletions(-) diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 6323c67..fba1a25 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -105,6 +105,7 @@ vAPI.tabs.registerListeners = function() { var onNavigationClient = this.onNavigation || noopFunc; var onPopupClient = this.onPopup || noopFunc; var onUpdatedClient = this.onUpdated || noopFunc; + var onClosedClient = this.onClosed || noopFunc; // https://developer.chrome.com/extensions/webNavigation // [onCreatedNavigationTarget ->] @@ -211,14 +212,15 @@ vAPI.tabs.registerListeners = function() { popupCandidateDestroy(details); }; + var onClosed = function(tabId) { + onClosedClient(tabId.toString()); + }; + chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget); chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate); chrome.webNavigation.onCommitted.addListener(onCommitted); chrome.tabs.onUpdated.addListener(onUpdated); - - if ( typeof this.onClosed === 'function' ) { - chrome.tabs.onRemoved.addListener(this.onClosed); - } + chrome.tabs.onRemoved.addListener(onClosed); }; /******************************************************************************/ diff --git a/src/js/background.js b/src/js/background.js index 314df4b..3c00487 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -70,7 +70,6 @@ return { processBehindTheSceneRequests: false, processHyperlinkAuditing: true, processReferer: false, - smartAutoReload: 'current', spoofUserAgent: false, spoofUserAgentEvery: 5, spoofUserAgentWith: defaultUserAgentStrings, diff --git a/src/js/commands.js b/src/js/commands.js index b474d88..aa84182 100644 --- a/src/js/commands.js +++ b/src/js/commands.js @@ -33,10 +33,7 @@ var whitelistAll = function(tabs) { if ( !tab.url ) { return; } - var µm = µMatrix; - if ( µm.autoWhitelistAllTemporarily(tab.url) ) { - µm.smartReloadTab(tab.id); - } + µMatrix.autoWhitelistAllTemporarily(tab.url); }; /******************************************************************************/ diff --git a/src/js/messaging.js b/src/js/messaging.js index 205fe26..3b58069 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -117,15 +117,6 @@ var µm = µMatrix; /******************************************************************************/ -var smartReload = function(tabs) { - var i = tabs.length; - while ( i-- ) { - µm.smartReloadTabs(µm.userSettings.smartAutoReload, tabs[i].id); - } -}; - -/******************************************************************************/ - // Constructor is faster than object literal var RowSnapshot = function(srcHostname, desHostname, desDomain) { @@ -305,13 +296,6 @@ var onMessage = function(request, sender, callback) { var response; switch ( request.what ) { - case 'disconnected': - // https://github.com/gorhill/httpswitchboard/issues/94 - if ( µm.userSettings.smartAutoReload ) { - vAPI.tabs.get(null, smartReload); - } - break; - case 'toggleMatrixSwitch': µm.tMatrix.setSwitchZ( request.switchName, diff --git a/src/js/popup.js b/src/js/popup.js index f74082a..bb1db40 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1157,6 +1157,10 @@ var onMatrixSnapshotReady = function(response) { uDom('#noNetTrafficPrompt').text(vAPI.i18n('matrixNoNetTrafficPrompt')); uDom('#noNetTrafficPrompt').css('display', ''); } + + // Create a hash to find out whether the reload button needs to be + // highlighted. + // TODO: }; diff --git a/src/js/settings.js b/src/js/settings.js index d88a29b..53b44f3 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -61,9 +61,6 @@ var installEventHandlers = function() { uDom('input[name="displayTextSize"]').on('change', function(){ changeUserSettings('displayTextSize', this.value); }); - uDom('#smart-auto-reload').on('change', function(){ - changeUserSettings('smartAutoReload', this.value); - }); // https://github.com/gorhill/httpswitchboard/issues/197 uDom(window).on('beforeunload', prepareToDie); @@ -85,7 +82,6 @@ uDom.onLoad(function() { uDom('input[name="displayTextSize"]').forEach(function(elem) { elem.prop('checked', elem.val() === userSettings.displayTextSize); }); - uDom('#smart-auto-reload').val(userSettings.smartAutoReload); installEventHandlers(); }; diff --git a/src/js/storage.js b/src/js/storage.js index 356ac6e..c5b11a4 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -53,14 +53,6 @@ var settingsLoaded = function(store) { // console.log('storage.js > loaded user settings'); - // Ensure backward-compatibility - // https://github.com/gorhill/httpswitchboard/issues/229 - if ( store.smartAutoReload === true ) { - store.smartAutoReload = 'all'; - } else if ( store.smartAutoReload === false ) { - store.smartAutoReload = 'none'; - } - µm.userSettings = store; // https://github.com/gorhill/uMatrix/issues/47 diff --git a/src/js/tab.js b/src/js/tab.js index ce0dbc0..2df3c5b 100644 --- a/src/js/tab.js +++ b/src/js/tab.js @@ -414,31 +414,12 @@ vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) { µm.tabContextManager.commit(tabId, changeInfo.url); µm.bindTabToPageStats(tabId, 'updated'); } - - // rhill 2013-12-23: Compute state after whole page is loaded. This is - // better than building a state snapshot dynamically when requests are - // recorded, because here we are not afflicted by the browser cache - // mechanism. - - // rhill 2014-03-05: Use tab id instead of page URL: this allows a - // blocked page using µMatrix internal data URI-based page to be properly - // unblocked when user un-blacklist the hostname. - // https://github.com/gorhill/httpswitchboard/issues/198 - if ( changeInfo.status === 'complete' ) { - var pageStats = µm.pageStoreFromTabId(tabId); - if ( pageStats ) { - pageStats.state = µm.computeTabState(tabId); - } - } }; /******************************************************************************/ vAPI.tabs.onClosed = function(tabId) { - // I could incinerate all the page stores in the crypt associated with the - // tab id, but this will be done anyway once all incineration timers - // elapse. Let's keep it simple: they can all just rot a bit more before - // incineration. + µm.unbindTabFromPageStats(tabId); }; /******************************************************************************/ @@ -623,7 +604,7 @@ vAPI.tabs.registerListeners(); µm.onPageLoadCompleted = function(tabId) { var pageStore = this.pageStoreFromTabId(tabId); - if ( !pageStore ) { + if ( pageStore === null ) { return; } @@ -631,7 +612,7 @@ vAPI.tabs.registerListeners(); if ( pageStore.thirdpartyScript ) { pageStore.recordRequest( 'script', - pageStore.pageURL + '{3rd-party_scripts}', + pageStore.pageUrl + '{3rd-party_scripts}', pageStore.pageScriptBlocked ); } @@ -639,141 +620,6 @@ vAPI.tabs.registerListeners(); /******************************************************************************/ -// Reload content of one or more tabs. - -µm.smartReloadTabs = function(which, tabId) { - if ( which === 'none' ) { - return; - } - - if ( which === 'current' && typeof tabId === 'number' ) { - this.smartReloadTab(tabId); - return; - } - - // which === 'all' - var reloadTabs = function(chromeTabs) { - var tabId; - var i = chromeTabs.length; - while ( i-- ) { - tabId = chromeTabs[i].id; - if ( µm.pageStores.hasOwnProperty(tabId) ) { - µm.smartReloadTab(tabId); - } - } - }; - - var getTabs = function() { - vAPI.tabs.getAll(reloadTabs); - }; - - this.asyncJobs.add('smartReloadTabs', null, getTabs, 500); -}; - -/******************************************************************************/ - -// Reload content of a tab - -µm.smartReloadTab = function(tabId) { - var pageStats = this.pageStoreFromTabId(tabId); - if ( !pageStats ) { - //console.error('HTTP Switchboard> µMatrix.smartReloadTab(): page stats for tab id %d not found', tabId); - return; - } - - // rhill 2013-12-23: Reload only if something previously blocked is now - // unblocked. - var blockRule; - var oldState = pageStats.state; - var newState = this.computeTabState(tabId); - var mustReload = false; - for ( blockRule in oldState ) { - if ( !oldState.hasOwnProperty(blockRule) ) { - continue; - } - // General rule, reload... - // If something previously blocked is no longer blocked. - if ( !newState[blockRule] ) { - // console.debug('tab.js > µMatrix.smartReloadTab(): will reload because "%s" is no longer blocked', blockRule); - mustReload = true; - break; - } - } - // Exceptions: blocking these previously unblocked types must result in a - // reload: - // - a script - // - a frame - // Related issues: - // https://github.com/gorhill/httpswitchboard/issues/94 - // https://github.com/gorhill/httpswitchboard/issues/141 - if ( !mustReload ) { - var reloadNewlyBlockedTypes = { - 'doc': true, - 'script' : true, - 'frame': true - }; - var blockRuleType; - for ( blockRule in newState ) { - if ( !newState.hasOwnProperty(blockRule) ) { - continue; - } - blockRuleType = blockRule.slice(0, blockRule.indexOf('|')); - if ( !reloadNewlyBlockedTypes[blockRuleType] ) { - continue; - } - if ( !oldState[blockRule] ) { - // console.debug('tab.js > µMatrix.smartReloadTab(): will reload because "%s" is now blocked', blockRule); - mustReload = true; - break; - } - } - } - - // console.log('old state: %o\nnew state: %o', oldState, newState); - - if ( mustReload ) { - vAPI.tabs.reload(tabId); - } - // pageStats.state = newState; -}; - -/******************************************************************************/ - -µm.computeTabState = function(tabId) { - var pageStats = this.pageStoreFromTabId(tabId); - if ( !pageStats ) { - //console.error('tab.js > µMatrix.computeTabState(): page stats for tab id %d not found', tabId); - return {}; - } - // Go through all recorded requests, apply filters to create state - // It is a critical error for a tab to not be defined here - var pageURL = pageStats.pageUrl; - var srcHostname = this.scopeFromURL(pageURL); - var requestDict = pageStats.requests.getRequestDict(); - var computedState = {}; - var desHostname, type; - for ( var reqKey in requestDict ) { - if ( !requestDict.hasOwnProperty(reqKey) ) { - continue; - } - - // The evaluation code here needs to reflect the evaluation code in - // beforeRequestHandler() - desHostname = this.PageRequestStats.hostnameFromRequestKey(reqKey); - - // rhill 2013-12-10: mind how stylesheets are to be evaluated: - // `stylesheet` or `other`? Depends of domain of request. - // https://github.com/gorhill/httpswitchboard/issues/85 - type = this.PageRequestStats.typeFromRequestKey(reqKey); - if ( this.mustBlock(srcHostname, desHostname, type) ) { - computedState[type + '|' + desHostname] = true; - } - } - return computedState; -}; - -/******************************************************************************/ - µm.resizeLogBuffers = function(size) { var pageStores = this.pageStores; for ( var pageURL in pageStores ) { @@ -791,4 +637,44 @@ vAPI.tabs.registerListeners(); /******************************************************************************/ +// Stale page store entries janitor +// https://github.com/chrisaljoudi/uBlock/issues/455 + +(function() { + var cleanupPeriod = 7 * 60 * 1000; + var cleanupSampleAt = 0; + var cleanupSampleSize = 11; + + var cleanup = function() { + var vapiTabs = vAPI.tabs; + var tabIds = Object.keys(µb.pageStores).sort(); + var checkTab = function(tabId) { + vapiTabs.get(tabId, function(tab) { + if ( !tab ) { + µb.unbindTabFromPageStats(tabId); + } + }); + }; + if ( cleanupSampleAt >= tabIds.length ) { + cleanupSampleAt = 0; + } + var tabId; + var n = Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length); + for ( var i = cleanupSampleAt; i < n; i++ ) { + tabId = tabIds[i]; + if ( vAPI.isBehindTheSceneTabId(tabId) ) { + continue; + } + checkTab(tabId); + } + cleanupSampleAt = n; + + setTimeout(cleanup, cleanupPeriod); + }; + + setTimeout(cleanup, cleanupPeriod); +})(); + +/******************************************************************************/ + })();