mirror of https://github.com/gorhill/uBlock.git
This commit is contained in:
parent
5edc5275de
commit
1c8df4a652
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue