|
@ -73,11 +73,10 @@ var onBeforeRootFrameRequestHandler = function(details) { |
|
|
|
|
|
|
|
|
var onBeforeRequestHandler = function(details) { |
|
|
var onBeforeRequestHandler = function(details) { |
|
|
var µm = µMatrix; |
|
|
var µm = µMatrix; |
|
|
var µmuri = µm.URI.set(details.url); |
|
|
|
|
|
var requestScheme = µmuri.scheme; |
|
|
|
|
|
|
|
|
|
|
|
// rhill 2014-02-17: Ignore 'filesystem:': this can happen when listening
|
|
|
// rhill 2014-02-17: Ignore 'filesystem:': this can happen when listening
|
|
|
// to 'chrome-extension://'.
|
|
|
// to 'chrome-extension://'.
|
|
|
|
|
|
var requestScheme = µm.URI.schemeFromURI(details.url); |
|
|
if ( requestScheme === 'filesystem' ) { |
|
|
if ( requestScheme === 'filesystem' ) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
@ -96,7 +95,7 @@ var onBeforeRequestHandler = function(details) { |
|
|
var requestURL = details.url; |
|
|
var requestURL = details.url; |
|
|
|
|
|
|
|
|
// Ignore non-http schemes
|
|
|
// Ignore non-http schemes
|
|
|
if ( requestScheme.indexOf('http') !== 0 ) { |
|
|
|
|
|
|
|
|
if ( requestScheme.lastIndexOf('http', 0) !== 0 ) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -115,10 +114,21 @@ var onBeforeRequestHandler = function(details) { |
|
|
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
|
|
var tabContext = µm.tabContextManager.mustLookup(details.tabId); |
|
|
var tabContext = µm.tabContextManager.mustLookup(details.tabId); |
|
|
var tabId = tabContext.tabId; |
|
|
var tabId = tabContext.tabId; |
|
|
var requestHostname = µmuri.hostname; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Enforce strict secure connection?
|
|
|
|
|
|
var block = false; |
|
|
|
|
|
if ( |
|
|
|
|
|
tabContext.secure && |
|
|
|
|
|
µm.URI.isSecureScheme(requestScheme) === false && |
|
|
|
|
|
µm.tMatrix.evaluateSwitchZ('https-strict', tabContext.rootHostname) |
|
|
|
|
|
) { |
|
|
|
|
|
block = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Disallow request as per temporary matrix?
|
|
|
// Disallow request as per temporary matrix?
|
|
|
var block = µm.mustBlock(tabContext.rootHostname, requestHostname, requestType); |
|
|
|
|
|
|
|
|
if ( block === false ) { |
|
|
|
|
|
block = µm.mustBlock(tabContext.rootHostname, details.hostname, requestType); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Record request.
|
|
|
// Record request.
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/342
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/342
|
|
@ -126,16 +136,16 @@ var onBeforeRequestHandler = function(details) { |
|
|
// processing has already been performed, and that a synthetic URL has
|
|
|
// processing has already been performed, and that a synthetic URL has
|
|
|
// been constructed for logging purpose. Use this synthetic URL if
|
|
|
// been constructed for logging purpose. Use this synthetic URL if
|
|
|
// it is available.
|
|
|
// it is available.
|
|
|
var pageStore = µm.mustPageStoreFromTabId(details.tabId); |
|
|
|
|
|
|
|
|
var pageStore = µm.mustPageStoreFromTabId(tabContext.tabId); |
|
|
pageStore.recordRequest(requestType, requestURL, block); |
|
|
pageStore.recordRequest(requestType, requestURL, block); |
|
|
|
|
|
|
|
|
// whitelisted?
|
|
|
|
|
|
|
|
|
// Allowed?
|
|
|
if ( !block ) { |
|
|
if ( !block ) { |
|
|
// console.debug('onBeforeRequestHandler()> ALLOW "%s": %o', details.url, details);
|
|
|
// console.debug('onBeforeRequestHandler()> ALLOW "%s": %o', details.url, details);
|
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// blacklisted
|
|
|
|
|
|
|
|
|
// Blocked
|
|
|
// console.debug('onBeforeRequestHandler()> BLOCK "%s": %o', details.url, details);
|
|
|
// console.debug('onBeforeRequestHandler()> BLOCK "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
return { 'cancel': true }; |
|
|
return { 'cancel': true }; |
|
@ -198,16 +208,14 @@ var onBeforeSendHeadersHandler = function(details) { |
|
|
// If we reach this point, request is not blocked, so what is left to do
|
|
|
// If we reach this point, request is not blocked, so what is left to do
|
|
|
// is to sanitize headers.
|
|
|
// is to sanitize headers.
|
|
|
|
|
|
|
|
|
var reqHostname = µm.hostnameFromURL(requestURL); |
|
|
|
|
|
|
|
|
|
|
|
if ( µm.mustBlock(pageStore.pageHostname, reqHostname, 'cookie') ) { |
|
|
|
|
|
|
|
|
if ( µm.mustBlock(pageStore.pageHostname, details.hostname, 'cookie') ) { |
|
|
if ( details.requestHeaders.setHeader('cookie', '') ) { |
|
|
if ( details.requestHeaders.setHeader('cookie', '') ) { |
|
|
µm.cookieHeaderFoiledCounter++; |
|
|
µm.cookieHeaderFoiledCounter++; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( µm.tMatrix.evaluateSwitchZ('referrer-spoof', pageStore.pageHostname) ) { |
|
|
if ( µm.tMatrix.evaluateSwitchZ('referrer-spoof', pageStore.pageHostname) ) { |
|
|
foilRefererHeaders(µm, reqHostname, details); |
|
|
|
|
|
|
|
|
foilRefererHeaders(µm, details.hostname, details); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( µm.tMatrix.evaluateSwitchZ('ua-spoof', pageStore.pageHostname) ) { |
|
|
if ( µm.tMatrix.evaluateSwitchZ('ua-spoof', pageStore.pageHostname) ) { |
|
@ -267,83 +275,63 @@ var onHeadersReceived = function(details) { |
|
|
|
|
|
|
|
|
var onMainDocHeadersReceived = function(details) { |
|
|
var onMainDocHeadersReceived = function(details) { |
|
|
var µm = µMatrix; |
|
|
var µm = µMatrix; |
|
|
|
|
|
var tabId = details.tabId; |
|
|
|
|
|
var requestURL = details.url; |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/uMatrix/issues/145
|
|
|
// https://github.com/gorhill/uMatrix/issues/145
|
|
|
// Check if the main_frame is a download
|
|
|
// Check if the main_frame is a download
|
|
|
if ( headerValue(details.responseHeaders, 'content-disposition').lastIndexOf('attachment', 0) === 0 ) { |
|
|
|
|
|
µm.tabContextManager.unpush(details.tabId, details.url); |
|
|
|
|
|
|
|
|
if ( headerValue(details.responseHeaders, 'content-type').lastIndexOf('application/x-', 0) === 0 ) { |
|
|
|
|
|
µm.tabContextManager.unpush(tabId, requestURL); |
|
|
|
|
|
} else { |
|
|
|
|
|
µm.tabContextManager.push(tabId, requestURL); |
|
|
} |
|
|
} |
|
|
var tabContext = µm.tabContextManager.lookup(details.tabId); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var tabContext = µm.tabContextManager.lookup(tabId); |
|
|
if ( tabContext === null ) { |
|
|
if ( tabContext === null ) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// console.debug('onMainDocHeadersReceived()> "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
|
|
|
// rhill 2013-12-07:
|
|
|
|
|
|
// Apparently in Opera, onBeforeRequest() is triggered while the
|
|
|
|
|
|
// URL is not yet bound to a tab (-1), which caused the code here
|
|
|
|
|
|
// to not be able to lookup the page store. So let the code here bind
|
|
|
|
|
|
// the page to a tab if not done yet.
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/75
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: check this works fine on Opera
|
|
|
|
|
|
|
|
|
|
|
|
// 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 HTTP Switchboard, i.e. `opera://startpage`,
|
|
|
|
|
|
// as this would lead to complications with no obvious solution, like how
|
|
|
|
|
|
// 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 headers = details.responseHeaders; |
|
|
|
|
|
|
|
|
// console.debug('onMainDocHeadersReceived()> "%s": %o', requestURL, details);
|
|
|
|
|
|
|
|
|
// Maybe modify inbound headers
|
|
|
|
|
|
var csp = ''; |
|
|
|
|
|
|
|
|
var blockScript = µm.mustBlock(tabContext.rootHostname, tabContext.rootHostname, 'script'); |
|
|
|
|
|
|
|
|
// Enforce strict HTTPS?
|
|
|
|
|
|
var requestScheme = µm.URI.schemeFromURI(details.url); |
|
|
|
|
|
if ( requestScheme === 'https' && µm.tMatrix.evaluateSwitchZ('https-strict', tabContext.rootHostname) ) { |
|
|
|
|
|
csp += "default-src chrome-search: data: https: wss: 'unsafe-eval' 'unsafe-inline';"; |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/181
|
|
|
|
|
|
var pageStore = µm.pageStoreFromTabId(tabId); |
|
|
|
|
|
if ( pageStore ) { |
|
|
|
|
|
pageStore.pageScriptBlocked = blockScript; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/181
|
|
|
|
|
|
pageStore.pageScriptBlocked = µm.mustBlock(tabContext.rootHostname, tabContext.rootHostname, 'script'); |
|
|
|
|
|
if ( pageStore.pageScriptBlocked ) { |
|
|
|
|
|
// If javascript not allowed, say so through a `Content-Security-Policy` directive.
|
|
|
|
|
|
// console.debug('onMainDocHeadersReceived()> PAGE CSP "%s": %o', details.url, details);
|
|
|
|
|
|
csp += " script-src 'none'"; |
|
|
|
|
|
|
|
|
if ( !blockScript ) { |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/181
|
|
|
|
|
|
if ( csp !== '' ) { |
|
|
|
|
|
headers.push({ |
|
|
|
|
|
|
|
|
µm.logger.writeOne(tabId, 'net', '---', 'inline-script', requestURL); |
|
|
|
|
|
|
|
|
|
|
|
// If javascript not allowed, say so through a `Content-Security-Policy` directive.
|
|
|
|
|
|
details.responseHeaders.push({ |
|
|
'name': 'Content-Security-Policy', |
|
|
'name': 'Content-Security-Policy', |
|
|
'value': csp.trim() |
|
|
|
|
|
|
|
|
'value': "script-src 'none'" |
|
|
}); |
|
|
}); |
|
|
return { responseHeaders: headers }; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return { responseHeaders: details.responseHeaders }; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
var onSubDocHeadersReceived = function(details) { |
|
|
var onSubDocHeadersReceived = function(details) { |
|
|
|
|
|
var µm = µMatrix; |
|
|
|
|
|
var tabId = details.tabId; |
|
|
|
|
|
|
|
|
// console.debug('onSubDocHeadersReceived()> "%s": %o', details.url, details);
|
|
|
// console.debug('onSubDocHeadersReceived()> "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
var µm = µMatrix; |
|
|
|
|
|
|
|
|
|
|
|
// Do not ignore traffic outside tabs.
|
|
|
// Do not ignore traffic outside tabs.
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/91#issuecomment-37180275
|
|
|
var tabId = details.tabId; |
|
|
|
|
|
var tabContext = µm.tabContextManager.lookup(tabId); |
|
|
var tabContext = µm.tabContextManager.lookup(tabId); |
|
|
if ( tabContext === null ) { |
|
|
if ( tabContext === null ) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Evaluate
|
|
|
// Evaluate
|
|
|
if ( µm.mustAllow(tabContext.rootHostname, µm.hostnameFromURL(details.url), 'script') ) { |
|
|
|
|
|
|
|
|
if ( µm.mustAllow(tabContext.rootHostname, details.hostname, 'script') ) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -368,6 +356,9 @@ var onSubDocHeadersReceived = function(details) { |
|
|
|
|
|
|
|
|
// console.debug('onSubDocHeadersReceived()> FRAME CSP "%s": %o, scope="%s"', details.url, details, pageURL);
|
|
|
// console.debug('onSubDocHeadersReceived()> FRAME CSP "%s": %o, scope="%s"', details.url, details, pageURL);
|
|
|
|
|
|
|
|
|
|
|
|
µm.logger.writeOne(tabId, 'net', '---', 'inline-script', details.url); |
|
|
|
|
|
|
|
|
|
|
|
// If javascript not allowed, say so through a `Content-Security-Policy` directive.
|
|
|
details.responseHeaders.push({ |
|
|
details.responseHeaders.push({ |
|
|
'name': 'Content-Security-Policy', |
|
|
'name': 'Content-Security-Policy', |
|
|
'value': "script-src 'none'" |
|
|
'value': "script-src 'none'" |
|
|