Browse Source

user is responsible to reload + fixed cleanup of stale tabs

pull/2/head
gorhill 10 years ago
parent
commit
be3e86e055
  1. 10
      platform/chromium/vapi-background.js
  2. 1
      src/js/background.js
  3. 5
      src/js/commands.js
  4. 16
      src/js/messaging.js
  5. 4
      src/js/popup.js
  6. 4
      src/js/settings.js
  7. 8
      src/js/storage.js
  8. 190
      src/js/tab.js

10
platform/chromium/vapi-background.js

@ -105,6 +105,7 @@ vAPI.tabs.registerListeners = function() {
var onNavigationClient = this.onNavigation || noopFunc; var onNavigationClient = this.onNavigation || noopFunc;
var onPopupClient = this.onPopup || noopFunc; var onPopupClient = this.onPopup || noopFunc;
var onUpdatedClient = this.onUpdated || noopFunc; var onUpdatedClient = this.onUpdated || noopFunc;
var onClosedClient = this.onClosed || noopFunc;
// https://developer.chrome.com/extensions/webNavigation // https://developer.chrome.com/extensions/webNavigation
// [onCreatedNavigationTarget ->] // [onCreatedNavigationTarget ->]
@ -211,14 +212,15 @@ vAPI.tabs.registerListeners = function() {
popupCandidateDestroy(details); popupCandidateDestroy(details);
}; };
var onClosed = function(tabId) {
onClosedClient(tabId.toString());
};
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget); chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate); chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
chrome.webNavigation.onCommitted.addListener(onCommitted); chrome.webNavigation.onCommitted.addListener(onCommitted);
chrome.tabs.onUpdated.addListener(onUpdated); chrome.tabs.onUpdated.addListener(onUpdated);
if ( typeof this.onClosed === 'function' ) {
chrome.tabs.onRemoved.addListener(this.onClosed);
}
chrome.tabs.onRemoved.addListener(onClosed);
}; };
/******************************************************************************/ /******************************************************************************/

1
src/js/background.js

@ -70,7 +70,6 @@ return {
processBehindTheSceneRequests: false, processBehindTheSceneRequests: false,
processHyperlinkAuditing: true, processHyperlinkAuditing: true,
processReferer: false, processReferer: false,
smartAutoReload: 'current',
spoofUserAgent: false, spoofUserAgent: false,
spoofUserAgentEvery: 5, spoofUserAgentEvery: 5,
spoofUserAgentWith: defaultUserAgentStrings, spoofUserAgentWith: defaultUserAgentStrings,

5
src/js/commands.js

@ -33,10 +33,7 @@ var whitelistAll = function(tabs) {
if ( !tab.url ) { if ( !tab.url ) {
return; return;
} }
var µm = µMatrix;
if ( µm.autoWhitelistAllTemporarily(tab.url) ) {
µm.smartReloadTab(tab.id);
}
µMatrix.autoWhitelistAllTemporarily(tab.url);
}; };
/******************************************************************************/ /******************************************************************************/

16
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 // Constructor is faster than object literal
var RowSnapshot = function(srcHostname, desHostname, desDomain) { var RowSnapshot = function(srcHostname, desHostname, desDomain) {
@ -305,13 +296,6 @@ var onMessage = function(request, sender, callback) {
var response; var response;
switch ( request.what ) { switch ( request.what ) {
case 'disconnected':
// https://github.com/gorhill/httpswitchboard/issues/94
if ( µm.userSettings.smartAutoReload ) {
vAPI.tabs.get(null, smartReload);
}
break;
case 'toggleMatrixSwitch': case 'toggleMatrixSwitch':
µm.tMatrix.setSwitchZ( µm.tMatrix.setSwitchZ(
request.switchName, request.switchName,

4
src/js/popup.js

@ -1157,6 +1157,10 @@ var onMatrixSnapshotReady = function(response) {
uDom('#noNetTrafficPrompt').text(vAPI.i18n('matrixNoNetTrafficPrompt')); uDom('#noNetTrafficPrompt').text(vAPI.i18n('matrixNoNetTrafficPrompt'));
uDom('#noNetTrafficPrompt').css('display', ''); uDom('#noNetTrafficPrompt').css('display', '');
} }
// Create a hash to find out whether the reload button needs to be
// highlighted.
// TODO:
}; };

4
src/js/settings.js

@ -61,9 +61,6 @@ var installEventHandlers = function() {
uDom('input[name="displayTextSize"]').on('change', function(){ uDom('input[name="displayTextSize"]').on('change', function(){
changeUserSettings('displayTextSize', this.value); changeUserSettings('displayTextSize', this.value);
}); });
uDom('#smart-auto-reload').on('change', function(){
changeUserSettings('smartAutoReload', this.value);
});
// https://github.com/gorhill/httpswitchboard/issues/197 // https://github.com/gorhill/httpswitchboard/issues/197
uDom(window).on('beforeunload', prepareToDie); uDom(window).on('beforeunload', prepareToDie);
@ -85,7 +82,6 @@ uDom.onLoad(function() {
uDom('input[name="displayTextSize"]').forEach(function(elem) { uDom('input[name="displayTextSize"]').forEach(function(elem) {
elem.prop('checked', elem.val() === userSettings.displayTextSize); elem.prop('checked', elem.val() === userSettings.displayTextSize);
}); });
uDom('#smart-auto-reload').val(userSettings.smartAutoReload);
installEventHandlers(); installEventHandlers();
}; };

8
src/js/storage.js

@ -53,14 +53,6 @@
var settingsLoaded = function(store) { var settingsLoaded = function(store) {
// console.log('storage.js > loaded user settings'); // 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; µm.userSettings = store;
// https://github.com/gorhill/uMatrix/issues/47 // https://github.com/gorhill/uMatrix/issues/47

190
src/js/tab.js

@ -414,31 +414,12 @@ vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) {
µm.tabContextManager.commit(tabId, changeInfo.url); µm.tabContextManager.commit(tabId, changeInfo.url);
µm.bindTabToPageStats(tabId, 'updated'); µ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) { 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) { µm.onPageLoadCompleted = function(tabId) {
var pageStore = this.pageStoreFromTabId(tabId); var pageStore = this.pageStoreFromTabId(tabId);
if ( !pageStore ) {
if ( pageStore === null ) {
return; return;
} }
@ -631,7 +612,7 @@ vAPI.tabs.registerListeners();
if ( pageStore.thirdpartyScript ) { if ( pageStore.thirdpartyScript ) {
pageStore.recordRequest( pageStore.recordRequest(
'script', 'script',
pageStore.pageURL + '{3rd-party_scripts}',
pageStore.pageUrl + '{3rd-party_scripts}',
pageStore.pageScriptBlocked pageStore.pageScriptBlocked
); );
} }
@ -639,155 +620,60 @@ 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);
µm.resizeLogBuffers = function(size) {
var pageStores = this.pageStores;
for ( var pageURL in pageStores ) {
if ( pageStores.hasOwnProperty(pageURL) ) {
pageStores[pageURL].requests.resizeLogBuffer(size);
} }
} }
}; };
var getTabs = function() {
vAPI.tabs.getAll(reloadTabs);
};
/******************************************************************************/
this.asyncJobs.add('smartReloadTabs', null, getTabs, 500);
µm.forceReload = function(tabId) {
vAPI.tabs.reload(tabId, { bypassCache: true });
}; };
/******************************************************************************/ /******************************************************************************/
// Reload content of a tab
// Stale page store entries janitor
// https://github.com/chrisaljoudi/uBlock/issues/455
µ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);
(function() {
var cleanupPeriod = 7 * 60 * 1000;
var cleanupSampleAt = 0;
var cleanupSampleSize = 11;
if ( mustReload ) {
vAPI.tabs.reload(tabId);
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);
} }
// 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;
if ( cleanupSampleAt >= tabIds.length ) {
cleanupSampleAt = 0;
} }
// 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;
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);
} }
return computedState;
};
cleanupSampleAt = n;
/******************************************************************************/
µm.resizeLogBuffers = function(size) {
var pageStores = this.pageStores;
for ( var pageURL in pageStores ) {
if ( pageStores.hasOwnProperty(pageURL) ) {
pageStores[pageURL].requests.resizeLogBuffer(size);
}
}
setTimeout(cleanup, cleanupPeriod);
}; };
/******************************************************************************/
µm.forceReload = function(tabId) {
vAPI.tabs.reload(tabId, { bypassCache: true });
};
setTimeout(cleanup, cleanupPeriod);
})();
/******************************************************************************/ /******************************************************************************/

Loading…
Cancel
Save