addressing all small details

This commit is contained in:
gorhill 2015-01-24 12:06:22 -05:00
parent d5fdd84da4
commit 8dcc994371
6 changed files with 155 additions and 43 deletions

View File

@ -71,6 +71,16 @@ return {
netExceptionList: {}, // TODO: remove once all users are up to date
netWhitelist: {},
netWhitelistModifyTime: 0,
netWhitelistDefault: [
'about-scheme',
'behind-the-scene',
'chrome-extension-scheme',
'chrome-scheme',
'data-scheme',
'file-scheme',
'opera-scheme',
''
].join('\n').trim(),
localSettings: {
blockedRequestCount: 0,

View File

@ -616,8 +616,11 @@ PageStore.prototype.toggleNetFilteringSwitch = function(url, scope, state) {
/******************************************************************************/
PageStore.prototype.filterRequest = function(context) {
if ( this.getNetFilteringSwitch() === false ) {
this.cacheResult(context, '');
if ( collapsibleRequestTypes.indexOf(context.requestType) !== -1 ) {
this.netFilteringCache.add(context, '');
}
return '';
}
@ -648,16 +651,53 @@ PageStore.prototype.filterRequest = function(context) {
}
//console.debug('cache MISS: PageStore.filterRequest("%s")', context.requestURL);
this.cacheResult(context, result);
if ( collapsibleRequestTypes.indexOf(context.requestType) !== -1 ) {
this.netFilteringCache.add(context, result);
}
// console.debug('[%s, %s] = "%s"', context.requestHostname, context.requestType, result);
return result;
};
// Cache only what is worth it if logging is disabled
// http://jsperf.com/string-indexof-vs-object
var collapsibleRequestTypes = 'image sub_frame object';
/******************************************************************************/
PageStore.prototype.cacheResult = function(context, result) {
PageStore.prototype.filterRequestNoCache = function(context) {
if ( this.getNetFilteringSwitch() === false ) {
return '';
}
var result = '';
// Given that:
// - Dynamic filtering override static filtering
// - Evaluating dynamic filtering is much faster than static filtering
// We evaluate dynamic filtering first, and hopefully we can skip
// evaluation of static filtering.
if ( µb.userSettings.advancedUserEnabled ) {
var df = µb.dynamicNetFilteringEngine.clearRegisters();
df.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType);
if ( df.mustBlockOrAllow() ) {
result = df.toFilterString();
}
}
// Static filtering never override dynamic filtering
if ( result === '' ) {
result = µb.staticNetFilteringEngine.matchString(context);
}
return result;
};
/******************************************************************************/
PageStore.prototype.logRequest = function(context, result) {
var requestHostname = context.requestHostname;
if ( this.hostnameToCountMap.hasOwnProperty(requestHostname) === false ) {
this.hostnameToCountMap[requestHostname] = 0;
@ -666,18 +706,16 @@ PageStore.prototype.cacheResult = function(context, result) {
var c = result.charAt(1);
if ( c === '' || c === 'a' ) {
this.hostnameToCountMap[requestHostname] += 0x00010000;
this.perLoadAllowedRequestCount++;
µb.localSettings.allowedRequestCount++;
} else /* if ( c === 'b' ) */ {
this.hostnameToCountMap[requestHostname] += 0x00000001;
this.perLoadBlockedRequestCount++;
µb.localSettings.blockedRequestCount++;
}
if ( collapsibleRequestTypes.indexOf(context.requestType) !== -1 ) {
this.netFilteringCache.add(context, result);
}
this.logBuffer.writeOne(context, result);
};
// Cache only what is worth it if logging is disabled
// http://jsperf.com/string-indexof-vs-object
var collapsibleRequestTypes = 'image sub_frame object';
/******************************************************************************/
PageStore.prototype.toMirrorURL = function(requestURL) {

View File

@ -89,6 +89,12 @@ var cachePopupData = function(data) {
/******************************************************************************/
var hashFromPopupData = function(reset) {
// It makes no sense to offer to refresh the behind-the-scene scope
if ( popupData.pageHostname === 'behind-the-scene' ) {
uDom('body').toggleClass('dirty', false);
return;
}
var hasher = [];
var rules = popupData.dynamicFilterRules;
var rule;
@ -299,7 +305,13 @@ var renderPopup = function() {
uDom('#appname').text(popupData.appName);
uDom('#version').text(popupData.appVersion);
uDom('body').toggleClass('advancedUser', popupData.advancedUserEnabled);
uDom('#switch').toggleClass('off', popupData.pageURL === '' || !popupData.netFilteringSwitch);
uDom('#switch').toggleClass(
'off',
(popupData.pageURL === '') ||
(!popupData.netFilteringSwitch) ||
(popupData.pageHostname === 'behind-the-scene' && !popupData.advancedUserEnabled)
);
// If you think the `=== true` is pointless, you are mistaken
uDom('#gotoLog').toggleClass('enabled', popupData.canRequestLog === true)
@ -359,6 +371,9 @@ var toggleNetFilteringSwitch = function(ev) {
if ( !popupData || !popupData.pageURL ) {
return;
}
if ( popupData.pageHostname === 'behind-the-scene' && !popupData.advancedUserEnabled ) {
return;
}
messager.send({
what: 'toggleNetFiltering',
url: popupData.pageURL,

View File

@ -124,7 +124,7 @@
};
var bin = {
'netWhitelist': 'behind-the-scene',
'netWhitelist': this.netWhitelistDefault,
'netExceptionList': ''
};
vAPI.storage.get(bin, onWhitelistLoaded);
@ -641,10 +641,17 @@
// To bring older versions up to date
var onVersionReady = function(bin) {
var lastVersion = bin.version || '0.0.0.0';
// Whitelist behind-the-scene scope by default
// Whitelist some key scopes by default
if ( lastVersion.localeCompare('0.8.6.0') < 0 ) {
µb.toggleNetFilteringSwitch('http://behind-the-scene/', 'site', false);
µb.netWhitelist = µb.whitelistFromString(
µb.stringFromWhitelist(µb.netWhitelist) +
'\n' +
µb.netWhitelistDefault
);
µb.saveWhitelist();
}
vAPI.storage.set({ version: vAPI.app.version });
onAllReady();
};

View File

@ -88,7 +88,7 @@ vAPI.tabs.onPopup = function(details) {
requestHostname: µb.URI.hostnameFromURI(requestURL),
requestType: 'popup'
};
pageStore.logBuffer.writeOne(context, result);
pageStore.logRequest(context, result);
}
// Not blocked
@ -131,11 +131,13 @@ vAPI.tabs.registerListeners();
return uri.normalizedURI();
}
var url = 'http://' + scheme + '-scheme/';
if ( uri.hostname !== '' ) {
return 'http://' + scheme + '-' + uri.hostname + uri.path;
url += uri.hostname + '/';
}
return 'http://' + scheme + '-scheme/';
return url;
};
/******************************************************************************/
@ -169,7 +171,8 @@ vAPI.tabs.registerListeners();
return pageStore;
}
if ( context === 'afterNavigate' ) {
// Rebind according to context
if ( pageURL !== pageStore.pageURL ) {
pageStore.reuse(pageURL, context);
}

View File

@ -34,10 +34,15 @@
// Intercept and filter web requests.
var onBeforeRequest = function(details) {
//console.debug('onBeforeRequest()> "%s": %o', details.url, details);
//console.debug('traffic.js > onBeforeRequest(): "%s": %o', details.url, details);
// Do not block behind the scene requests.
var tabId = details.tabId;
// Special treatment: behind-the-scene requests
if ( vAPI.isNoTabId(tabId) ) {
return onBeforeBehindTheSceneRequest(details);
}
var µb = µBlock;
var requestURL = details.url;
var requestType = details.type;
@ -51,7 +56,7 @@ var onBeforeRequest = function(details) {
pageStore.requestURL = requestURL;
pageStore.requestHostname = pageStore.pageHostname;
pageStore.requestType = 'main_frame';
pageStore.logBuffer.writeOne(pageStore, '');
pageStore.logRequest(pageStore, '');
}
return;
}
@ -83,10 +88,7 @@ var onBeforeRequest = function(details) {
// Not blocked
if ( µb.isAllowResult(result) ) {
//console.debug('onBeforeRequest()> ALLOW "%s" (%o) because "%s"', details.url, details, result);
pageStore.perLoadAllowedRequestCount++;
µb.localSettings.allowedRequestCount++;
//console.debug('traffic.js > onBeforeRequest(): ALLOW "%s" (%o) because "%s"', details.url, details, result);
// https://github.com/gorhill/uBlock/issues/114
if ( frameId > 0 && frameStore === undefined ) {
@ -99,23 +101,21 @@ var onBeforeRequest = function(details) {
// Disabling local mirroring for the time being
//var redirectURL = pageStore.toMirrorURL(requestURL);
//if ( redirectURL !== '' ) {
// pageStore.logBuffer.writeOne(requestContext, 'ma:');
//console.debug('"%s" redirected to "%s..."', requestURL.slice(0, 50), redirectURL.slice(0, 50));
// pageStore.logRequest(requestContext, 'ma:');
//console.debug('traffic.js > "%s" redirected to "%s..."', requestURL.slice(0, 50), redirectURL.slice(0, 50));
// return { redirectUrl: redirectURL };
//}
pageStore.logBuffer.writeOne(requestContext, result);
pageStore.logRequest(requestContext, result);
return;
}
// Blocked
//console.debug('onBeforeRequest()> BLOCK "%s" (%o) because "%s"', details.url, details, result);
//console.debug('traffic.js > onBeforeRequest(): BLOCK "%s" (%o) because "%s"', details.url, details, result);
pageStore.logBuffer.writeOne(requestContext, result);
pageStore.logRequest(requestContext, result);
pageStore.perLoadBlockedRequestCount++;
µb.localSettings.blockedRequestCount++;
µb.updateBadgeAsync(tabId);
// https://github.com/gorhill/uBlock/issues/18
@ -127,6 +127,46 @@ var onBeforeRequest = function(details) {
/******************************************************************************/
// Intercept and filter behind-the-scene requests.
var onBeforeBehindTheSceneRequest = function(details) {
//console.debug('traffic.js > onBeforeBehindTheSceneRequest(): "%s": %o', details.url, details);
var µb = µBlock;
var pageStore = µb.pageStoreFromTabId(vAPI.noTabId);
if ( !pageStore ) {
return;
}
pageStore.requestURL = details.url;
pageStore.requestHostname = details.hostname;
pageStore.requestType = details.type;
// Blocking behind-the-scene requests can break a lot of stuff: prevent
// browser updates, prevent extension updates, prevent extensions from
// working properly, etc.
// So we filter if and only if the "advanced user" mode is selected
var result = '';
if ( µb.userSettings.advancedUserEnabled ) {
result = pageStore.filterRequestNoCache(pageStore);
}
pageStore.logRequest(pageStore, result);
// Not blocked
if ( µb.isAllowResult(result) ) {
//console.debug('traffic.js > onBeforeBehindTheSceneRequest(): ALLOW "%s" (%o) because "%s"', details.url, details, result);
return;
}
// Blocked
//console.debug('traffic.js > onBeforeBehindTheSceneRequest(): BLOCK "%s" (%o) because "%s"', details.url, details, result);
return { 'cancel': true };
};
/******************************************************************************/
// Intercept root frame requests. This is where we identify and block popups.
var onBeforeSendHeaders = function(details) {
@ -134,11 +174,11 @@ var onBeforeSendHeaders = function(details) {
// the tab id could be -1, despite the request not really being a
// behind-the-scene request. If true, the test below would prevent
// the popup blocker from working. Need to check this.
//console.debug('onBeforeSendHeaders()> "%s" (%o) because "%s"', details.url, details, result);
//console.debug('traffic.js > onBeforeSendHeaders(): "%s" (%o) because "%s"', details.url, details, result);
// Do not block behind the scene requests.
var tabId = details.tabId;
if ( tabId < 0 ) {
if ( vAPI.isNoTabId(tabId) ) {
return;
}
@ -193,7 +233,7 @@ var onBeforeSendHeaders = function(details) {
};
pageDetails.rootHostname = pageDetails.pageHostname;
pageDetails.rootDomain = pageDetails.pageDomain;
//console.debug('Referrer="%s"', referrer);
//console.debug('traffic.js > Referrer="%s"', referrer);
var result = µb.staticNetFilteringEngine.matchStringExactType(pageDetails, requestURL, 'popup');
// Not blocked?
@ -215,7 +255,7 @@ var onBeforeSendHeaders = function(details) {
var onHeadersReceived = function(details) {
// Do not interfere with behind-the-scene requests.
var tabId = details.tabId;
if ( tabId < 0 ) {
if ( vAPI.isNoTabId(tabId) ) {
return;
}
@ -265,17 +305,16 @@ var onHeadersReceived = function(details) {
context.requestType = 'inline-script';
var result = pageStore.filterRequest(context);
if ( µb.isBlockResult(result) === false ) {
pageStore.logRequest(context, result);
// Don't block
if ( µb.isAllowResult(result) ) {
return;
}
// Blocked
pageStore.perLoadBlockedRequestCount++;
µb.localSettings.blockedRequestCount++;
µb.updateBadgeAsync(tabId);
pageStore.logBuffer.writeOne(context, result);
details.responseHeaders.push({
'name': 'Content-Security-Policy',
'value': "script-src 'unsafe-eval' *"
@ -368,7 +407,7 @@ vAPI.net.onHeadersReceived = {
vAPI.net.registerListeners();
//console.log('µBlock> Beginning to intercept net requests at %s', (new Date()).toISOString());
//console.log('traffic.js > Beginning to intercept net requests at %s', (new Date()).toISOString());
/******************************************************************************/