Raymond Hill 2018-05-16 11:50:50 -04:00
parent 5edc5275de
commit 1c8df4a652
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 72 additions and 33 deletions

View File

@ -33,6 +33,31 @@ var exports = {};
/******************************************************************************/ /******************************************************************************/
// Platform-specific behavior.
// https://github.com/uBlockOrigin/uBlock-issues/issues/42
// https://bugzilla.mozilla.org/show_bug.cgi?id=1376932
// Add proper version number detection once issue is fixed in Firefox.
let dontCacheResponseHeaders =
vAPI.webextFlavor.soup.has('firefox');
// https://github.com/gorhill/uMatrix/issues/967#issuecomment-373002011
// This can be removed once Firefox 60 ESR is released.
let cantMergeCSPHeaders =
vAPI.webextFlavor.soup.has('firefox') && vAPI.webextFlavor.major < 59;
// The real actual webextFlavor value may not be set in stone, so listen
// for possible future changes.
window.addEventListener('webextFlavor', function() {
dontCacheResponseHeaders =
vAPI.webextFlavor.soup.has('firefox');
cantMergeCSPHeaders =
vAPI.webextFlavor.soup.has('firefox') && vAPI.webextFlavor.major < 59;
}, { once: true });
/******************************************************************************/
// https://github.com/gorhill/uBlock/issues/2067 // https://github.com/gorhill/uBlock/issues/2067
// Experimental: Block everything until uBO is fully ready. // Experimental: Block everything until uBO is fully ready.
// TODO: re-work vAPI code to match more closely how listeners are // TODO: re-work vAPI code to match more closely how listeners are
@ -523,10 +548,10 @@ onBeforeMaybeSpuriousCSPReport.textDecoder = undefined;
var onHeadersReceived = function(details) { var onHeadersReceived = function(details) {
// Do not interfere with behind-the-scene requests. // Do not interfere with behind-the-scene requests.
var tabId = details.tabId; let tabId = details.tabId;
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; } if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
var µb = µBlock, let µb = µBlock,
requestType = details.type, requestType = details.type,
isRootDoc = requestType === 'main_frame', isRootDoc = requestType === 'main_frame',
isDoc = isRootDoc || requestType === 'sub_frame'; isDoc = isRootDoc || requestType === 'sub_frame';
@ -535,7 +560,7 @@ var onHeadersReceived = function(details) {
µb.tabContextManager.push(tabId, details.url); µb.tabContextManager.push(tabId, details.url);
} }
var pageStore = µb.pageStoreFromTabId(tabId); let pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) { if ( pageStore === null ) {
if ( isRootDoc === false ) { return; } if ( isRootDoc === false ) { return; }
pageStore = µb.bindTabToPageStats(tabId, 'beforeRequest'); pageStore = µb.bindTabToPageStats(tabId, 'beforeRequest');
@ -546,23 +571,50 @@ var onHeadersReceived = function(details) {
return foilLargeMediaElement(pageStore, details); return foilLargeMediaElement(pageStore, details);
} }
if ( isDoc && µb.canFilterResponseBody ) { if ( isDoc === false ) { return; }
filterDocument(pageStore, details);
} // Keep in mind response headers will be modified in-place if needed, so
// `details.responseHeaders` will always point to the modified response
// headers.
let responseHeaders = details.responseHeaders;
// https://github.com/gorhill/uBlock/issues/2813 // https://github.com/gorhill/uBlock/issues/2813
// Disable the blocking of large media elements if the document is itself // Disable the blocking of large media elements if the document is itself
// a media element: the resource was not prevented from loading so no // a media element: the resource was not prevented from loading so no
// point to further block large media elements for the current document. // point to further block large media elements for the current document.
if ( isRootDoc ) { if ( isRootDoc ) {
if ( reMediaContentTypes.test(headerValueFromName('content-type', details.responseHeaders)) ) { let contentType = headerValueFromName('content-type', responseHeaders);
if ( reMediaContentTypes.test(contentType) ) {
pageStore.allowLargeMediaElementsUntil = Date.now() + 86400000; pageStore.allowLargeMediaElementsUntil = Date.now() + 86400000;
return;
} }
return injectCSP(pageStore, details);
} }
if ( isDoc ) { // At this point we have a HTML document.
return injectCSP(pageStore, details);
let filteredHTML = µb.canFilterResponseBody &&
filterDocument(pageStore, details) === true;
let modifiedHeaders = injectCSP(pageStore, details) === true;
// https://bugzilla.mozilla.org/show_bug.cgi?id=1376932
// Prevent document from being cached by the browser if we modified it,
// either through HTML filtering and/or modified response headers.
if ( (filteredHTML || modifiedHeaders) && dontCacheResponseHeaders ) {
let i = headerIndexFromName('cache-control', responseHeaders);
if ( i !== -1 ) {
responseHeaders[i].value = 'no-cache, no-store, must-revalidate';
} else {
responseHeaders[responseHeaders.length] = {
name: 'Cache-Control',
value: 'no-cache, no-store, must-revalidate'
};
}
modifiedHeaders = true;
}
if ( modifiedHeaders ) {
return { responseHeaders: responseHeaders };
} }
}; };
@ -832,20 +884,22 @@ var filterDocument = (function() {
stream.onstop = onStreamStop; stream.onstop = onStreamStop;
stream.onerror = onStreamError; stream.onerror = onStreamError;
filterers.set(stream, request); filterers.set(stream, request);
return true;
}; };
})(); })();
/******************************************************************************/ /******************************************************************************/
var injectCSP = function(pageStore, details) { var injectCSP = function(pageStore, details) {
var µb = µBlock, let µb = µBlock,
tabId = details.tabId, tabId = details.tabId,
requestURL = details.url, requestURL = details.url,
loggerEnabled = µb.logger.isEnabled(), loggerEnabled = µb.logger.isEnabled(),
logger = µb.logger, logger = µb.logger,
cspSubsets = []; cspSubsets = [];
var context = pageStore.createContextFromPage(); let context = pageStore.createContextFromPage();
context.requestHostname = µb.URI.hostnameFromURI(requestURL); context.requestHostname = µb.URI.hostnameFromURI(requestURL);
if ( details.type !== 'main_frame' ) { if ( details.type !== 'main_frame' ) {
context.pageHostname = context.pageDomain = context.requestHostname; context.pageHostname = context.pageDomain = context.requestHostname;
@ -856,7 +910,7 @@ var injectCSP = function(pageStore, details) {
// ======== built-in policies // ======== built-in policies
var builtinDirectives = []; let builtinDirectives = [];
context.requestType = 'inline-script'; context.requestType = 'inline-script';
if ( pageStore.filterRequest(context) === 1 ) { if ( pageStore.filterRequest(context) === 1 ) {
@ -900,7 +954,7 @@ var injectCSP = function(pageStore, details) {
// Static filtering. // Static filtering.
var logDataEntries = []; let logDataEntries = [];
µb.staticNetFilteringEngine.matchAndFetchData( µb.staticNetFilteringEngine.matchAndFetchData(
'csp', 'csp',
@ -953,7 +1007,7 @@ var injectCSP = function(pageStore, details) {
// <<<<<<<< All policies have been collected // <<<<<<<< All policies have been collected
// Static CSP policies will be applied. // Static CSP policies will be applied.
for ( var entry of logDataEntries ) { for ( let entry of logDataEntries ) {
logger.writeOne( logger.writeOne(
tabId, tabId,
'net', 'net',
@ -981,10 +1035,10 @@ var injectCSP = function(pageStore, details) {
// if the current environment does not support merging headers: // if the current environment does not support merging headers:
// Firefox 58/webext and less can't merge CSP headers, so we will merge // Firefox 58/webext and less can't merge CSP headers, so we will merge
// them here. // them here.
var headers = details.responseHeaders; let headers = details.responseHeaders;
if ( cantMergeCSPHeaders ) { if ( cantMergeCSPHeaders ) {
var i = headerIndexFromName('content-security-policy', headers); let i = headerIndexFromName('content-security-policy', headers);
if ( i !== -1 ) { if ( i !== -1 ) {
cspSubsets.unshift(headers[i].value.trim()); cspSubsets.unshift(headers[i].value.trim());
headers.splice(i, 1); headers.splice(i, 1);
@ -996,24 +1050,9 @@ var injectCSP = function(pageStore, details) {
value: cspSubsets.join(', ') value: cspSubsets.join(', ')
}); });
return { 'responseHeaders': headers }; return true;
}; };
// https://github.com/gorhill/uMatrix/issues/967#issuecomment-373002011
// This can be removed once Firefox 60 ESR is released.
var evalCantMergeCSPHeaders = function() {
return vAPI.webextFlavor.soup.has('firefox') &&
vAPI.webextFlavor.major < 59;
};
var cantMergeCSPHeaders = evalCantMergeCSPHeaders();
// The real actual webextFlavor value may not be set in stone, so listen
// for possible future changes.
window.addEventListener('webextFlavor', function() {
cantMergeCSPHeaders = evalCantMergeCSPHeaders();
}, { once: true });
/******************************************************************************/ /******************************************************************************/
// https://github.com/gorhill/uBlock/issues/1163 // https://github.com/gorhill/uBlock/issues/1163