|
@ -202,7 +202,7 @@ var onBeforeRootFrameRequestHandler = function(details) { |
|
|
if ( tabId < 0 ) { |
|
|
if ( tabId < 0 ) { |
|
|
tabId = µm.behindTheSceneTabId; |
|
|
tabId = µm.behindTheSceneTabId; |
|
|
} |
|
|
} |
|
|
// It's a root frame, bind to a new page stats store
|
|
|
|
|
|
|
|
|
// It's a root frame, bind to a new page store
|
|
|
else { |
|
|
else { |
|
|
µm.bindTabToPageStats(tabId, details.url); |
|
|
µm.bindTabToPageStats(tabId, details.url); |
|
|
} |
|
|
} |
|
@ -255,20 +255,53 @@ var onBeforeRootFrameRequestHandler = function(details) { |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
// Process a request.
|
|
|
|
|
|
//
|
|
|
|
|
|
// This can be called from the context of onBeforeSendRequest() or
|
|
|
|
|
|
// onBeforeSendHeaders().
|
|
|
|
|
|
|
|
|
// Intercept and filter web requests according to white and black lists.
|
|
|
|
|
|
|
|
|
|
|
|
var onBeforeRequestHandler = function(details) { |
|
|
|
|
|
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
|
|
|
|
|
|
// to 'chrome-extension://'.
|
|
|
|
|
|
if ( requestScheme === 'filesystem' ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// console.debug('onBeforeRequestHandler()> "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
|
|
|
var requestType = requestTypeNormalizer[details.type]; |
|
|
|
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/303
|
|
|
|
|
|
// Wherever the main doc comes from, create a receiver page URL: synthetize
|
|
|
|
|
|
// one if needed.
|
|
|
|
|
|
if ( requestType === 'doc' && details.parentFrameId < 0 ) { |
|
|
|
|
|
return onBeforeRootFrameRequestHandler(details); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var requestURL = details.url; |
|
|
|
|
|
|
|
|
|
|
|
// Is it µMatrix's noop css file?
|
|
|
|
|
|
if ( requestType === 'css' && requestURL.slice(0, µm.noopCSSURL.length) === µm.noopCSSURL ) { |
|
|
|
|
|
return onBeforeChromeExtensionRequestHandler(details); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Ignore non-http schemes
|
|
|
|
|
|
if ( requestScheme.indexOf('http') !== 0 ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Do not block myself from updating assets
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/202
|
|
|
|
|
|
if ( requestType === 'xhr' && requestURL.slice(0, µm.projectServerRoot.length) === µm.projectServerRoot ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var processRequest = function(µm, details) { |
|
|
|
|
|
var µmuri = µm.URI; |
|
|
|
|
|
var requestURL = µmuri.set(details.url).normalizedURI(); |
|
|
|
|
|
var requestHostname = µmuri.hostname; |
|
|
var requestHostname = µmuri.hostname; |
|
|
|
|
|
|
|
|
// rhill 2013-12-15:
|
|
|
// rhill 2013-12-15:
|
|
|
// Try to transpose generic `other` category into something more
|
|
|
// Try to transpose generic `other` category into something more
|
|
|
// meaningful.
|
|
|
// meaningful.
|
|
|
var requestType = requestTypeNormalizer[details.type]; |
|
|
|
|
|
if ( requestType === 'other' ) { |
|
|
if ( requestType === 'other' ) { |
|
|
requestType = µm.transposeType(requestType, µmuri.path); |
|
|
requestType = µm.transposeType(requestType, µmuri.path); |
|
|
} |
|
|
} |
|
@ -294,7 +327,7 @@ var processRequest = function(µm, 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.
|
|
|
pageStore.recordRequest(requestType, details.µmRequestURL || requestURL, block); |
|
|
|
|
|
|
|
|
pageStore.recordRequest(requestType, requestURL, block); |
|
|
|
|
|
|
|
|
// whitelisted?
|
|
|
// whitelisted?
|
|
|
if ( !block ) { |
|
|
if ( !block ) { |
|
@ -323,64 +356,6 @@ var processRequest = function(µm, details) { |
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
// Intercept and filter web requests according to white and black lists.
|
|
|
|
|
|
|
|
|
|
|
|
var onBeforeRequestHandler = function(details) { |
|
|
|
|
|
var µm = µMatrix; |
|
|
|
|
|
var µmuri = µm.URI; |
|
|
|
|
|
var requestURL = details.url; |
|
|
|
|
|
var requestScheme = µmuri.schemeFromURI(requestURL); |
|
|
|
|
|
|
|
|
|
|
|
// rhill 2014-02-17: Ignore 'filesystem:': this can happen when listening
|
|
|
|
|
|
// to 'chrome-extension://'.
|
|
|
|
|
|
if ( requestScheme === 'filesystem' ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// console.debug('onBeforeRequestHandler()> "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
|
|
|
var requestType = requestTypeNormalizer[details.type]; |
|
|
|
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/303
|
|
|
|
|
|
// Wherever the main doc comes from, create a receiver page URL: synthetize
|
|
|
|
|
|
// one if needed.
|
|
|
|
|
|
if ( requestType === 'doc' && details.parentFrameId < 0 ) { |
|
|
|
|
|
return onBeforeRootFrameRequestHandler(details); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Is it µMatrix's noop css file?
|
|
|
|
|
|
if ( requestType === 'css' && requestURL.slice(0, µm.noopCSSURL.length) === µm.noopCSSURL ) { |
|
|
|
|
|
return onBeforeChromeExtensionRequestHandler(details); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Ignore non-http schemes
|
|
|
|
|
|
if ( requestScheme.indexOf('http') !== 0 ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Do not block myself from updating assets
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/202
|
|
|
|
|
|
if ( requestType === 'xhr' && requestURL.slice(0, µm.projectServerRoot.length) === µm.projectServerRoot ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/342
|
|
|
|
|
|
// If the request cannot be bound to a specific tab, delay request
|
|
|
|
|
|
// handling to onBeforeSendHeaders(), maybe there the referrer
|
|
|
|
|
|
// information will allow us to properly bind the request to the tab
|
|
|
|
|
|
// from which it originates.
|
|
|
|
|
|
// Important: since it is not possible to redirect requests at
|
|
|
|
|
|
// onBeforeSendHeaders() point, we can't delay when the request type is
|
|
|
|
|
|
// `sub_frame`.
|
|
|
|
|
|
if ( requestType !== 'frame' && details.tabId < 0 ) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return processRequest(µm, details); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/ |
|
|
|
|
|
|
|
|
|
|
|
// This is where tabless requests are processed, as here there may be a chance
|
|
|
// This is where tabless requests are processed, as here there may be a chance
|
|
|
// we can bind a request to a specific tab, as headers may contain useful
|
|
|
// we can bind a request to a specific tab, as headers may contain useful
|
|
|
// information to accomplish this.
|
|
|
// information to accomplish this.
|
|
@ -390,76 +365,45 @@ var onBeforeRequestHandler = function(details) { |
|
|
var onBeforeSendHeadersHandler = function(details) { |
|
|
var onBeforeSendHeadersHandler = function(details) { |
|
|
|
|
|
|
|
|
var µm = µMatrix; |
|
|
var µm = µMatrix; |
|
|
var requestURL = details.url; |
|
|
|
|
|
|
|
|
|
|
|
// console.debug('onBeforeSendHeadersHandler()> "%s": %o', details.url, details);
|
|
|
// console.debug('onBeforeSendHeadersHandler()> "%s": %o', details.url, details);
|
|
|
|
|
|
|
|
|
// Do not block myself from updating assets
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/202
|
|
|
|
|
|
var requestType = requestTypeNormalizer[details.type]; |
|
|
|
|
|
if ( requestType === 'xhr' && requestURL.slice(0, µm.projectServerRoot.length) === µm.projectServerRoot ) { |
|
|
|
|
|
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 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 tabId = details.tabId; |
|
|
|
|
|
var pageStore = µm.pageStatsFromTabId(tabId); |
|
|
|
|
|
if ( !pageStore ) { |
|
|
|
|
|
tabId = µm.behindTheSceneTabId; |
|
|
|
|
|
pageStore = µm.pageStatsFromTabId(tabId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/342
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/342
|
|
|
// Is this hyperlink auditing?
|
|
|
// Is this hyperlink auditing?
|
|
|
// If yes, create a synthetic URL for reporting hyperlink auditing
|
|
|
// If yes, create a synthetic URL for reporting hyperlink auditing
|
|
|
// record requests. This way the user is better informed of what went
|
|
|
|
|
|
|
|
|
// in request log. This way the user is better informed of what went
|
|
|
// on.
|
|
|
// on.
|
|
|
|
|
|
var requestURL = details.url; |
|
|
|
|
|
var requestType = requestTypeNormalizer[details.type]; |
|
|
|
|
|
if ( requestType === 'other' ) { |
|
|
var linkAuditor = hyperlinkAuditorFromHeaders(details.requestHeaders); |
|
|
var linkAuditor = hyperlinkAuditorFromHeaders(details.requestHeaders); |
|
|
if ( linkAuditor ) { |
|
|
if ( linkAuditor ) { |
|
|
details.µmRequestURL = requestURL + '{Ping-To:' + linkAuditor + '}'; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If we are dealing with a behind-the-scene request, make a last attempt
|
|
|
|
|
|
// to bind the request to a specific tab by using the referrer or the
|
|
|
|
|
|
// `Ping-From` header if any of these exists.
|
|
|
|
|
|
var r; |
|
|
|
|
|
if ( details.tabId < 0 ) { |
|
|
|
|
|
details.tabId = tabIdFromHeaders(µm, details.requestHeaders) || -1; |
|
|
|
|
|
// Do not process `main_frame`/`sub_frame` requests, these were handled
|
|
|
|
|
|
// unconditionally at onBeforeRequest() time (because of potential
|
|
|
|
|
|
// need to redirect).
|
|
|
|
|
|
if ( requestType !== 'doc' && requestType !== 'frame' ) { |
|
|
|
|
|
r = processRequest(µm, details); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If the request was not cancelled above, check whether hyperlink auditing
|
|
|
|
|
|
// is globally forbidden.
|
|
|
|
|
|
if ( !r ) { |
|
|
|
|
|
if ( linkAuditor && µm.userSettings.processHyperlinkAuditing ) { |
|
|
|
|
|
r = { 'cancel': true }; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Block request?
|
|
|
|
|
|
if ( r ) { |
|
|
|
|
|
// Count number of hyperlink auditing foiled, even attempts blocked
|
|
|
|
|
|
// through the matrix.
|
|
|
|
|
|
if ( linkAuditor ) { |
|
|
|
|
|
|
|
|
var block = µm.userSettings.processHyperlinkAuditing; |
|
|
|
|
|
pageStore.recordRequest('other', requestURL + '{Ping-To:' + linkAuditor + '}', block); |
|
|
|
|
|
if ( block ) { |
|
|
µm.hyperlinkAuditingFoiledCounter += 1; |
|
|
µm.hyperlinkAuditingFoiledCounter += 1; |
|
|
|
|
|
return { 'cancel': true }; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
return r; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
// 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 tabId = details.tabId; |
|
|
|
|
|
var pageStore = µm.pageStatsFromTabId(tabId); |
|
|
|
|
|
if ( !pageStore ) { |
|
|
|
|
|
tabId = µm.behindTheSceneTabId; |
|
|
|
|
|
pageStore = µm.pageStatsFromTabId(tabId); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var reqHostname = µm.hostnameFromURL(requestURL); |
|
|
var reqHostname = µm.hostnameFromURL(requestURL); |
|
|
var changed = false; |
|
|
var changed = false; |
|
|
|
|
|
|
|
@ -710,7 +654,7 @@ var onMainDocHeadersReceived = function(details) { |
|
|
|
|
|
|
|
|
// Enforce strict HTTPS?
|
|
|
// Enforce strict HTTPS?
|
|
|
if ( requestScheme === 'https' && µm.tMatrix.evaluateSwitchZ('https-strict', pageStats.pageHostname) ) { |
|
|
if ( requestScheme === 'https' && µm.tMatrix.evaluateSwitchZ('https-strict', pageStats.pageHostname) ) { |
|
|
csp += "default-src https: data: 'unsafe-inline' 'unsafe-eval'"; |
|
|
|
|
|
|
|
|
csp += "default-src https: data: chrome-search: 'unsafe-inline' 'unsafe-eval'"; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/181
|
|
|
// https://github.com/gorhill/httpswitchboard/issues/181
|
|
|