mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-06-01 18:10:17 +12:00
code review of request headers processing code
- drop needless overhead now that legacy support is dropped - output extra information about the headers which are modified and their value before/after modification
This commit is contained in:
parent
ff5789d4ac
commit
c4c0d450fd
|
@ -55,9 +55,7 @@ var noopFunc = function(){};
|
|||
|
||||
// https://github.com/gorhill/uMatrix/issues/234
|
||||
// https://developer.chrome.com/extensions/privacy#property-network
|
||||
chrome.privacy.network.networkPredictionEnabled.set({
|
||||
value: false
|
||||
});
|
||||
chrome.privacy.network.networkPredictionEnabled.set({ value: false });
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -125,9 +123,7 @@ vAPI.tabs.registerListeners = function() {
|
|||
|
||||
var onCreatedNavigationTarget = function(details) {
|
||||
//console.debug('onCreatedNavigationTarget: tab id %d = "%s"', details.tabId, details.url);
|
||||
if ( reGoodForWebRequestAPI.test(details.url) ) {
|
||||
return;
|
||||
}
|
||||
if ( reGoodForWebRequestAPI.test(details.url) ) { return; }
|
||||
details.tabId = details.tabId.toString();
|
||||
onNavigationClient(details);
|
||||
};
|
||||
|
@ -563,78 +559,7 @@ vAPI.net = {};
|
|||
/******************************************************************************/
|
||||
|
||||
vAPI.net.registerListeners = function() {
|
||||
var µm = µMatrix,
|
||||
reNetworkURL = /^(?:https?|wss?):\/\//,
|
||||
httpRequestHeadersJunkyard = [];
|
||||
|
||||
// Abstraction layer to deal with request headers
|
||||
// >>>>>>>>
|
||||
var httpRequestHeadersFactory = function(headers) {
|
||||
var entry = httpRequestHeadersJunkyard.pop();
|
||||
if ( entry ) {
|
||||
return entry.init(headers);
|
||||
}
|
||||
return new HTTPRequestHeaders(headers);
|
||||
};
|
||||
|
||||
var HTTPRequestHeaders = function(headers) {
|
||||
this.init(headers);
|
||||
};
|
||||
|
||||
HTTPRequestHeaders.prototype.init = function(headers) {
|
||||
this.modified = false;
|
||||
this.headers = headers;
|
||||
return this;
|
||||
};
|
||||
|
||||
HTTPRequestHeaders.prototype.dispose = function() {
|
||||
var r = this.modified ? this.headers : null;
|
||||
this.headers = null;
|
||||
httpRequestHeadersJunkyard.push(this);
|
||||
return r;
|
||||
};
|
||||
|
||||
HTTPRequestHeaders.prototype.getHeader = function(target) {
|
||||
var headers = this.headers;
|
||||
var header, name;
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
header = headers[i];
|
||||
name = header.name.toLowerCase();
|
||||
if ( name === target ) {
|
||||
return header.value;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
HTTPRequestHeaders.prototype.setHeader = function(target, value, create) {
|
||||
var headers = this.headers;
|
||||
var header, name;
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
header = headers[i];
|
||||
name = header.name.toLowerCase();
|
||||
if ( name === target ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( i < 0 && !create ) { // Header not found, don't add it
|
||||
return false;
|
||||
}
|
||||
if ( i < 0 ) { // Header not found, add it
|
||||
headers.push({ name: target, value: value });
|
||||
} else if ( value === '' ) { // Header found, remove it
|
||||
headers.splice(i, 1);
|
||||
} else { // Header found, modify it
|
||||
header.value = value;
|
||||
}
|
||||
this.modified = true;
|
||||
return true;
|
||||
};
|
||||
// <<<<<<<<
|
||||
// End of: Abstraction layer to deal with request headers
|
||||
|
||||
var µm = µMatrix;
|
||||
|
||||
// Normalizing request types
|
||||
// >>>>>>>>
|
||||
|
@ -647,30 +572,17 @@ vAPI.net.registerListeners = function() {
|
|||
var normalizeRequestDetails = function(details) {
|
||||
details.tabId = details.tabId.toString();
|
||||
|
||||
var type = details.type;
|
||||
|
||||
if ( type === 'imageset' ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
|
||||
// The rest of the function code is to normalize request type
|
||||
if ( type !== 'other' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( details.requestHeaders instanceof HTTPRequestHeaders ) {
|
||||
if ( details.requestHeaders.getHeader('ping-to') !== '' ) {
|
||||
details.type = 'ping';
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( details.type !== 'other' ) { return; }
|
||||
|
||||
// Try to map known "extension" part of URL to request type.
|
||||
var path = µm.URI.pathFromURI(details.url),
|
||||
pos = path.indexOf('.', path.length - 6);
|
||||
if ( pos !== -1 && (type = extToTypeMap.get(path.slice(pos + 1))) ) {
|
||||
details.type = type;
|
||||
if ( pos !== -1 ) {
|
||||
var type = extToTypeMap.get(path.slice(pos + 1));
|
||||
if ( type !== undefined ) {
|
||||
details.type = type;
|
||||
}
|
||||
}
|
||||
};
|
||||
// <<<<<<<<
|
||||
|
@ -681,17 +593,9 @@ vAPI.net.registerListeners = function() {
|
|||
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
||||
chrome.webRequest.onBeforeRequest.addListener(
|
||||
function(details) {
|
||||
if ( reNetworkURL.test(details.url) ) {
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
}
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
},
|
||||
//function(details) {
|
||||
// quickProfiler.start('onBeforeRequest');
|
||||
// var r = onBeforeRequest(details);
|
||||
// quickProfiler.stop();
|
||||
// return r;
|
||||
//},
|
||||
{
|
||||
'urls': this.onBeforeRequest.urls || [ '<all_urls>' ],
|
||||
'types': this.onBeforeRequest.types || undefined
|
||||
|
@ -701,16 +605,8 @@ vAPI.net.registerListeners = function() {
|
|||
|
||||
var onBeforeSendHeadersClient = this.onBeforeSendHeaders.callback;
|
||||
var onBeforeSendHeaders = function(details) {
|
||||
details.requestHeaders = httpRequestHeadersFactory(details.requestHeaders);
|
||||
normalizeRequestDetails(details);
|
||||
var result = onBeforeSendHeadersClient(details);
|
||||
if ( typeof result === 'object' ) {
|
||||
return result;
|
||||
}
|
||||
var modifiedHeaders = details.requestHeaders.dispose();
|
||||
if ( modifiedHeaders !== null ) {
|
||||
return { requestHeaders: modifiedHeaders };
|
||||
}
|
||||
return onBeforeSendHeadersClient(details);
|
||||
};
|
||||
chrome.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
|
|
|
@ -49,6 +49,11 @@ var prettyRequestTypes = {
|
|||
'xmlhttprequest': 'xhr'
|
||||
};
|
||||
|
||||
var dontEmphasizeSet = new Set([
|
||||
'COOKIE',
|
||||
'REFERER'
|
||||
]);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Adjust top padding of content table, to match that of toolbar height.
|
||||
|
@ -245,7 +250,9 @@ var renderLogEntry = function(entry) {
|
|||
tr.cells[fvdc].textContent = '';
|
||||
}
|
||||
tr.cells[fvdc+1].textContent = (prettyRequestTypes[entry.d2] || entry.d2);
|
||||
if ( entry.d2 === 'cookie' ) {
|
||||
if ( dontEmphasizeSet.has(entry.d2) ) {
|
||||
tr.cells[fvdc+2].textContent = entry.d1;
|
||||
} else if ( entry.d2 === 'cookie' ) {
|
||||
tr.cells[fvdc+2].appendChild(emphasizeCookie(entry.d1));
|
||||
} else {
|
||||
tr.cells[fvdc+2].appendChild(emphasizeHostname(entry.d1));
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
Home: https://github.com/gorhill/uMatrix
|
||||
*/
|
||||
|
||||
/* jshint boss: true */
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -75,6 +73,13 @@ var onBeforeRootFrameRequestHandler = function(details) {
|
|||
// Intercept and filter web requests according to white and black lists.
|
||||
|
||||
var onBeforeRequestHandler = function(details) {
|
||||
var µm = µMatrix,
|
||||
µmuri = µm.URI,
|
||||
requestURL = details.url,
|
||||
requestScheme = µmuri.schemeFromURI(requestURL);
|
||||
|
||||
if ( µmuri.isNetworkScheme(requestScheme) === false ) { return; }
|
||||
|
||||
var requestType = requestTypeNormalizer[details.type] || 'other';
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/303
|
||||
|
@ -84,17 +89,6 @@ var onBeforeRequestHandler = function(details) {
|
|||
return onBeforeRootFrameRequestHandler(details);
|
||||
}
|
||||
|
||||
var µm = µMatrix,
|
||||
µmuri = µm.URI,
|
||||
requestURL = details.url,
|
||||
requestScheme = µmuri.schemeFromURI(requestURL);
|
||||
|
||||
// Ignore non-network schemes
|
||||
if ( µmuri.isNetworkScheme(requestScheme) === false ) {
|
||||
µm.logger.writeOne('', 'info', 'request not processed: ' + requestURL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-classify orphan HTTP requests as behind-the-scene requests. There is
|
||||
// not much else which can be done, because there are URLs
|
||||
// which cannot be handled by µMatrix, i.e. `opera://startpage`,
|
||||
|
@ -148,12 +142,13 @@ var onBeforeRequestHandler = function(details) {
|
|||
// Sanitize outgoing headers as per user settings.
|
||||
|
||||
var onBeforeSendHeadersHandler = function(details) {
|
||||
var µm = µMatrix;
|
||||
var µm = µMatrix,
|
||||
µmuri = µm.URI,
|
||||
requestURL = details.url,
|
||||
requestScheme = µmuri.schemeFromURI(requestURL);
|
||||
|
||||
// Ignore non-network schemes
|
||||
if ( µm.URI.isNetworkScheme(details.url) === false ) {
|
||||
return;
|
||||
}
|
||||
if ( µmuri.isNetworkScheme(requestScheme) === false ) { return; }
|
||||
|
||||
// Re-classify orphan HTTP requests as behind-the-scene requests. There is
|
||||
// not much else which can be done, because there are URLs
|
||||
|
@ -162,8 +157,11 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
// to scope on unknown scheme? Etc.
|
||||
// https://github.com/gorhill/httpswitchboard/issues/191
|
||||
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
||||
var pageStore = µm.mustPageStoreFromTabId(details.tabId);
|
||||
var tabId = pageStore.tabId;
|
||||
var tabId = details.tabId,
|
||||
pageStore = µm.mustPageStoreFromTabId(tabId),
|
||||
requestType = requestTypeNormalizer[details.type] || 'other',
|
||||
requestHeaders = details.requestHeaders,
|
||||
headerIndex, headerValue;
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/342
|
||||
// Is this hyperlink auditing?
|
||||
|
@ -186,13 +184,12 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
// With hyperlink-auditing, removing header(s) is pointless, the whole
|
||||
// request must be cancelled.
|
||||
|
||||
var requestURL = details.url;
|
||||
var requestType = requestTypeNormalizer[details.type] || 'other';
|
||||
if ( requestType === 'ping' ) {
|
||||
var linkAuditor = details.requestHeaders.getHeader('ping-to');
|
||||
if ( linkAuditor !== '' ) {
|
||||
headerIndex = headerIndexFromName('ping-to', requestHeaders);
|
||||
if ( headerIndex !== -1 ) {
|
||||
headerValue = requestHeaders[headerIndex].value;
|
||||
if ( headerValue !== '' ) {
|
||||
var block = µm.userSettings.processHyperlinkAuditing;
|
||||
pageStore.recordRequest('other', requestURL + '{Ping-To:' + linkAuditor + '}', block);
|
||||
pageStore.recordRequest('other', requestURL + '{Ping-To:' + headerValue + '}', block);
|
||||
µm.logger.writeOne(tabId, 'net', '', requestURL, 'ping', block);
|
||||
if ( block ) {
|
||||
µm.hyperlinkAuditingFoiledCounter += 1;
|
||||
|
@ -203,42 +200,30 @@ var onBeforeSendHeadersHandler = function(details) {
|
|||
|
||||
// If we reach this point, request is not blocked, so what is left to do
|
||||
// is to sanitize headers.
|
||||
var requestHostname = µm.URI.hostnameFromURI(requestURL);
|
||||
|
||||
if ( µm.mustBlock(pageStore.pageHostname, requestHostname, 'cookie') ) {
|
||||
if ( details.requestHeaders.setHeader('cookie', '') ) {
|
||||
µm.cookieHeaderFoiledCounter++;
|
||||
var rootHostname = pageStore.pageHostname,
|
||||
requestHostname = µmuri.hostnameFromURI(requestURL),
|
||||
modified = false;
|
||||
|
||||
// Process `Cookie` header.
|
||||
|
||||
headerIndex = headerIndexFromName('cookie', requestHeaders);
|
||||
if (
|
||||
headerIndex !== -1 &&
|
||||
µm.mustBlock(rootHostname, requestHostname, 'cookie')
|
||||
) {
|
||||
headerValue = requestHeaders[headerIndex].value;
|
||||
requestHeaders.splice(headerIndex, 1);
|
||||
modified = true;
|
||||
µm.cookieHeaderFoiledCounter++;
|
||||
if ( requestType === 'doc' ) {
|
||||
µm.logger.writeOne(tabId, 'net', '', headerValue, 'COOKIE', true);
|
||||
}
|
||||
}
|
||||
|
||||
if ( µm.tMatrix.evaluateSwitchZ('referrer-spoof', pageStore.pageHostname) ) {
|
||||
foilRefererHeaders(µm, requestHostname, details);
|
||||
}
|
||||
};
|
||||
// Process `Referer` header.
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var foilRefererHeaders = function(µm, toHostname, details) {
|
||||
var foiled = false;
|
||||
var µmuri = µm.URI;
|
||||
var scheme = '';
|
||||
var toDomain = '';
|
||||
|
||||
var referer = details.requestHeaders.getHeader('referer');
|
||||
if ( referer !== '' ) {
|
||||
toDomain = toDomain || µmuri.domainFromHostname(toHostname);
|
||||
if ( toDomain !== µmuri.domainFromURI(referer) ) {
|
||||
scheme = scheme || µmuri.schemeFromURI(details.url);
|
||||
//console.debug('foilRefererHeaders()> foiled referer for "%s"', details.url);
|
||||
//console.debug('\treferrer "%s"', header.value);
|
||||
// https://github.com/gorhill/httpswitchboard/issues/222#issuecomment-44828402
|
||||
details.requestHeaders.setHeader(
|
||||
'referer',
|
||||
scheme + '://' + toHostname + '/'
|
||||
);
|
||||
foiled = true;
|
||||
}
|
||||
}
|
||||
// https://github.com/gorhill/httpswitchboard/issues/222#issuecomment-44828402
|
||||
|
||||
// https://github.com/gorhill/uMatrix/issues/320
|
||||
// http://tools.ietf.org/html/rfc6454#section-7.3
|
||||
|
@ -253,23 +238,29 @@ var foilRefererHeaders = function(µm, toHostname, details) {
|
|||
// https://github.com/gorhill/uMatrix/issues/358
|
||||
// Do not spoof `Origin` header for the time being. This will be revisited.
|
||||
|
||||
//var origin = details.requestHeaders.getHeader('origin');
|
||||
//if ( origin !== '' && origin !== 'null' ) {
|
||||
// toDomain = toDomain || µmuri.domainFromHostname(toHostname);
|
||||
// if ( toDomain !== µmuri.domainFromURI(origin) ) {
|
||||
// scheme = scheme || µmuri.schemeFromURI(details.url);
|
||||
// //console.debug('foilRefererHeaders()> foiled origin for "%s"', details.url);
|
||||
// //console.debug('\torigin "%s"', header.value);
|
||||
// details.requestHeaders.setHeader(
|
||||
// 'origin',
|
||||
// scheme + '://' + toHostname
|
||||
// );
|
||||
// foiled = true;
|
||||
// }
|
||||
//}
|
||||
headerIndex = headerIndexFromName('referer', requestHeaders);
|
||||
if ( headerIndex !== -1 ) {
|
||||
headerValue = requestHeaders[headerIndex].value;
|
||||
if (
|
||||
headerValue !== '' &&
|
||||
µm.tMatrix.evaluateSwitchZ('referrer-spoof', rootHostname)
|
||||
) {
|
||||
var toDomain = µmuri.domainFromHostname(requestHostname);
|
||||
if ( toDomain !== '' && toDomain !== µmuri.domainFromURI(headerValue) ) {
|
||||
var newValue = requestScheme + '://' + requestHostname + '/';
|
||||
requestHeaders[headerIndex].value = newValue;
|
||||
modified = true;
|
||||
µm.refererHeaderFoiledCounter++;
|
||||
if ( requestType === 'doc' ) {
|
||||
µm.logger.writeOne(tabId, 'net', '', headerValue, 'REFERER', true);
|
||||
µm.logger.writeOne(tabId, 'net', '', newValue, 'REFERER', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( foiled ) {
|
||||
µm.refererHeaderFoiledCounter++;
|
||||
if ( modified ) {
|
||||
return { requestHeaders: requestHeaders };
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue