mirror of https://github.com/gorhill/uBlock.git
fix #2950
This commit is contained in:
parent
c0f42c5021
commit
a0c595d02d
|
@ -930,295 +930,6 @@ vAPI.messaging.broadcast = function(message) {
|
|||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net.registerListeners = function() {
|
||||
var µb = µBlock,
|
||||
µburi = µb.URI,
|
||||
wrApi = chrome.webRequest;
|
||||
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=410382
|
||||
// Between Chromium 38-48, plug-ins' network requests were reported as
|
||||
// type "other" instead of "object".
|
||||
var is_v38_48 = /\bChrom[a-z]+\/(?:3[89]|4[0-8])\.[\d.]+\b/.test(navigator.userAgent);
|
||||
|
||||
// legacy Chromium understands only these network request types.
|
||||
var validTypes = {
|
||||
main_frame: true,
|
||||
sub_frame: true,
|
||||
stylesheet: true,
|
||||
script: true,
|
||||
image: true,
|
||||
object: true,
|
||||
xmlhttprequest: true,
|
||||
other: true
|
||||
};
|
||||
// modern Chromium/WebExtensions: more types available.
|
||||
if ( wrApi.ResourceType ) {
|
||||
(function() {
|
||||
for ( var typeKey in wrApi.ResourceType ) {
|
||||
if ( wrApi.ResourceType.hasOwnProperty(typeKey) ) {
|
||||
validTypes[wrApi.ResourceType[typeKey]] = true;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
var extToTypeMap = new Map([
|
||||
['eot','font'],['otf','font'],['svg','font'],['ttf','font'],['woff','font'],['woff2','font'],
|
||||
['mp3','media'],['mp4','media'],['webm','media'],
|
||||
['gif','image'],['ico','image'],['jpeg','image'],['jpg','image'],['png','image'],['webp','image']
|
||||
]);
|
||||
|
||||
var denormalizeTypes = function(aa) {
|
||||
if ( aa.length === 0 ) {
|
||||
return Object.keys(validTypes);
|
||||
}
|
||||
var out = [];
|
||||
var i = aa.length,
|
||||
type,
|
||||
needOther = true;
|
||||
while ( i-- ) {
|
||||
type = aa[i];
|
||||
if ( validTypes[type] ) {
|
||||
out.push(type);
|
||||
}
|
||||
if ( type === 'other' ) {
|
||||
needOther = false;
|
||||
}
|
||||
}
|
||||
if ( needOther ) {
|
||||
out.push('other');
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
var headerValue = function(headers, name) {
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
if ( headers[i].name.toLowerCase() === name ) {
|
||||
return headers[i].value.trim();
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var normalizeRequestDetails = function(details) {
|
||||
details.tabId = details.tabId.toString();
|
||||
|
||||
var type = details.type;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1493
|
||||
// Chromium 49+/WebExtensions support a new request type: `ping`,
|
||||
// which is fired as a result of using `navigator.sendBeacon`.
|
||||
if ( type === 'ping' ) {
|
||||
details.type = 'beacon';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( type === 'imageset' ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
|
||||
// The rest of the function code is to normalize type
|
||||
if ( type !== 'other' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to map known "extension" part of URL to request type.
|
||||
var path = µburi.pathFromURI(details.url),
|
||||
pos = path.indexOf('.', path.length - 6);
|
||||
if ( pos !== -1 && (type = extToTypeMap.get(path.slice(pos + 1))) ) {
|
||||
details.type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to extract type from response headers if present.
|
||||
if ( details.responseHeaders ) {
|
||||
type = headerValue(details.responseHeaders, 'content-type');
|
||||
if ( type.startsWith('font/') ) {
|
||||
details.type = 'font';
|
||||
return;
|
||||
}
|
||||
if ( type.startsWith('image/') ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
if ( type.startsWith('audio/') || type.startsWith('video/') ) {
|
||||
details.type = 'media';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/862
|
||||
// If no transposition possible, transpose to `object` as per
|
||||
// Chromium bug 410382
|
||||
// https://code.google.com/p/chromium/issues/detail?id=410382
|
||||
if ( is_v38_48 ) {
|
||||
details.type = 'object';
|
||||
}
|
||||
};
|
||||
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=129353
|
||||
// https://github.com/gorhill/uBlock/issues/1497
|
||||
// Expose websocket-based network requests to uBO's filtering engine,
|
||||
// logger, etc.
|
||||
// Counterpart of following block of code is found in "vapi-client.js" --
|
||||
// search for "https://github.com/gorhill/uBlock/issues/1497".
|
||||
//
|
||||
// Once uBO 1.11.1 and uBO-Extra 2.12 are widespread, the image-based
|
||||
// handling code can be removed.
|
||||
var onBeforeWebsocketRequest = function(details) {
|
||||
if ( (details.type !== 'image') &&
|
||||
(details.method !== 'HEAD' || details.type !== 'xmlhttprequest')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
var requestURL = details.url,
|
||||
matches = /[?&]u(?:rl)?=([^&]+)/.exec(requestURL);
|
||||
if ( matches === null ) { return; }
|
||||
details.type = 'websocket';
|
||||
details.url = decodeURIComponent(matches[1]);
|
||||
var r = onBeforeRequestClient(details);
|
||||
if ( r && r.cancel ) { return r; }
|
||||
// Redirect to the provided URL, or a 1x1 data: URI if none provided.
|
||||
matches = /[?&]r=([^&]+)/.exec(requestURL);
|
||||
return {
|
||||
redirectUrl: matches !== null ?
|
||||
decodeURIComponent(matches[1]) :
|
||||
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
|
||||
};
|
||||
};
|
||||
|
||||
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
||||
var onBeforeRequest = validTypes.websocket
|
||||
// modern Chromium/WebExtensions: type 'websocket' is supported
|
||||
? function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
}
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
// https://github.com/gorhill/uBlock/issues/1497
|
||||
if ( details.url.endsWith('ubofix=f41665f3028c7fd10eecf573336216d3') ) {
|
||||
var r = onBeforeWebsocketRequest(details);
|
||||
if ( r !== undefined ) { return r; }
|
||||
}
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
};
|
||||
|
||||
// This is needed for Chromium 49-55.
|
||||
var onBeforeSendHeaders = validTypes.csp_report
|
||||
// modern Chromium/WebExtensions: type 'csp_report' is supported
|
||||
? null
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
if ( details.type !== 'ping' || details.method !== 'POST' ) { return; }
|
||||
var type = headerValue(details.requestHeaders, 'content-type');
|
||||
if ( type === '' ) { return; }
|
||||
if ( type.endsWith('/csp-report') ) {
|
||||
details.type = 'csp_report';
|
||||
return onBeforeRequestClient(details);
|
||||
}
|
||||
};
|
||||
|
||||
var onHeadersReceivedClient = this.onHeadersReceived.callback,
|
||||
onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0),
|
||||
onHeadersReceivedTypes = denormalizeTypes(onHeadersReceivedClientTypes);
|
||||
var onHeadersReceived = validTypes.font
|
||||
// modern Chromium/WebExtensions: type 'font' is supported
|
||||
? function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
if (
|
||||
onHeadersReceivedClientTypes.length !== 0 &&
|
||||
onHeadersReceivedClientTypes.indexOf(details.type) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return onHeadersReceivedClient(details);
|
||||
}
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
// Hack to work around Chromium API limitations, where requests of
|
||||
// type `font` are returned as `other`. For example, our normalization
|
||||
// fail at transposing `other` into `font` for URLs which are outside
|
||||
// what is expected. At least when headers are received we can check
|
||||
// for content type `font/*`. Blocking at onHeadersReceived time is
|
||||
// less worse than not blocking at all. Also, due to Chromium bug,
|
||||
// `other` always becomes `object` when it can't be normalized into
|
||||
// something else. Test case for "unfriendly" font URLs:
|
||||
// https://www.google.com/fonts
|
||||
if ( details.type === 'font' ) {
|
||||
var r = onBeforeRequestClient(details);
|
||||
if ( typeof r === 'object' && r.cancel === true ) {
|
||||
return { cancel: true };
|
||||
}
|
||||
}
|
||||
if (
|
||||
onHeadersReceivedClientTypes.length !== 0 &&
|
||||
onHeadersReceivedClientTypes.indexOf(details.type) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return onHeadersReceivedClient(details);
|
||||
};
|
||||
|
||||
var urls, types;
|
||||
|
||||
if ( onBeforeRequest ) {
|
||||
urls = this.onBeforeRequest.urls || ['<all_urls>'];
|
||||
types = this.onBeforeRequest.types || undefined;
|
||||
if (
|
||||
(validTypes.websocket) &&
|
||||
(types === undefined || types.indexOf('websocket') !== -1) &&
|
||||
(urls.indexOf('<all_urls>') === -1)
|
||||
) {
|
||||
if ( urls.indexOf('ws://*/*') === -1 ) {
|
||||
urls.push('ws://*/*');
|
||||
}
|
||||
if ( urls.indexOf('wss://*/*') === -1 ) {
|
||||
urls.push('wss://*/*');
|
||||
}
|
||||
}
|
||||
wrApi.onBeforeRequest.addListener(
|
||||
onBeforeRequest,
|
||||
{ urls: urls, types: types },
|
||||
this.onBeforeRequest.extra
|
||||
);
|
||||
}
|
||||
|
||||
// Chromium 48 and lower does not support `ping` type.
|
||||
// Chromium 56 and higher does support `csp_report` stype.
|
||||
if ( onBeforeSendHeaders ) {
|
||||
wrApi.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{
|
||||
'urls': [ '<all_urls>' ],
|
||||
'types': [ 'ping' ]
|
||||
},
|
||||
[ 'blocking', 'requestHeaders' ]
|
||||
);
|
||||
}
|
||||
|
||||
if ( onHeadersReceived ) {
|
||||
urls = this.onHeadersReceived.urls || ['<all_urls>'];
|
||||
types = onHeadersReceivedTypes;
|
||||
wrApi.onHeadersReceived.addListener(
|
||||
onHeadersReceived,
|
||||
{ urls: urls, types: types },
|
||||
this.onHeadersReceived.extra
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/contextMenus#Browser_compatibility
|
||||
// Firefox for Android does no support browser.contextMenus.
|
||||
|
||||
|
|
|
@ -0,0 +1,313 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2017 Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
// For background page
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net = {};
|
||||
|
||||
vAPI.net.registerListeners = function() {
|
||||
|
||||
var µb = µBlock,
|
||||
µburi = µb.URI,
|
||||
wrApi = chrome.webRequest;
|
||||
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=410382
|
||||
// Between Chromium 38-48, plug-ins' network requests were reported as
|
||||
// type "other" instead of "object".
|
||||
var is_v38_48 = /\bChrom[a-z]+\/(?:3[89]|4[0-8])\.[\d.]+\b/.test(navigator.userAgent);
|
||||
|
||||
// legacy Chromium understands only these network request types.
|
||||
var validTypes = {
|
||||
main_frame: true,
|
||||
sub_frame: true,
|
||||
stylesheet: true,
|
||||
script: true,
|
||||
image: true,
|
||||
object: true,
|
||||
xmlhttprequest: true,
|
||||
other: true
|
||||
};
|
||||
// modern Chromium/WebExtensions: more types available.
|
||||
if ( wrApi.ResourceType ) {
|
||||
(function() {
|
||||
for ( var typeKey in wrApi.ResourceType ) {
|
||||
if ( wrApi.ResourceType.hasOwnProperty(typeKey) ) {
|
||||
validTypes[wrApi.ResourceType[typeKey]] = true;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
var extToTypeMap = new Map([
|
||||
['eot','font'],['otf','font'],['svg','font'],['ttf','font'],['woff','font'],['woff2','font'],
|
||||
['mp3','media'],['mp4','media'],['webm','media'],
|
||||
['gif','image'],['ico','image'],['jpeg','image'],['jpg','image'],['png','image'],['webp','image']
|
||||
]);
|
||||
|
||||
var denormalizeTypes = function(aa) {
|
||||
if ( aa.length === 0 ) {
|
||||
return Object.keys(validTypes);
|
||||
}
|
||||
var out = [];
|
||||
var i = aa.length,
|
||||
type,
|
||||
needOther = true;
|
||||
while ( i-- ) {
|
||||
type = aa[i];
|
||||
if ( validTypes[type] ) {
|
||||
out.push(type);
|
||||
}
|
||||
if ( type === 'other' ) {
|
||||
needOther = false;
|
||||
}
|
||||
}
|
||||
if ( needOther ) {
|
||||
out.push('other');
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
var headerValue = function(headers, name) {
|
||||
var i = headers.length;
|
||||
while ( i-- ) {
|
||||
if ( headers[i].name.toLowerCase() === name ) {
|
||||
return headers[i].value.trim();
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var normalizeRequestDetails = function(details) {
|
||||
details.tabId = details.tabId.toString();
|
||||
|
||||
var type = details.type;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1493
|
||||
// Chromium 49+/WebExtensions support a new request type: `ping`,
|
||||
// which is fired as a result of using `navigator.sendBeacon`.
|
||||
if ( type === 'ping' ) {
|
||||
details.type = 'beacon';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( type === 'imageset' ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
|
||||
// The rest of the function code is to normalize type
|
||||
if ( type !== 'other' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to map known "extension" part of URL to request type.
|
||||
var path = µburi.pathFromURI(details.url),
|
||||
pos = path.indexOf('.', path.length - 6);
|
||||
if ( pos !== -1 && (type = extToTypeMap.get(path.slice(pos + 1))) ) {
|
||||
details.type = type;
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to extract type from response headers if present.
|
||||
if ( details.responseHeaders ) {
|
||||
type = headerValue(details.responseHeaders, 'content-type');
|
||||
if ( type.startsWith('font/') ) {
|
||||
details.type = 'font';
|
||||
return;
|
||||
}
|
||||
if ( type.startsWith('image/') ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
if ( type.startsWith('audio/') || type.startsWith('video/') ) {
|
||||
details.type = 'media';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/862
|
||||
// If no transposition possible, transpose to `object` as per
|
||||
// Chromium bug 410382
|
||||
// https://code.google.com/p/chromium/issues/detail?id=410382
|
||||
if ( is_v38_48 ) {
|
||||
details.type = 'object';
|
||||
}
|
||||
};
|
||||
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=129353
|
||||
// https://github.com/gorhill/uBlock/issues/1497
|
||||
// Expose websocket-based network requests to uBO's filtering engine,
|
||||
// logger, etc.
|
||||
// Counterpart of following block of code is found in "vapi-client.js" --
|
||||
// search for "https://github.com/gorhill/uBlock/issues/1497".
|
||||
//
|
||||
// Once uBO 1.11.1 and uBO-Extra 2.12 are widespread, the image-based
|
||||
// handling code can be removed.
|
||||
var onBeforeWebsocketRequest = function(details) {
|
||||
if ( (details.type !== 'image') &&
|
||||
(details.method !== 'HEAD' || details.type !== 'xmlhttprequest')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
var requestURL = details.url,
|
||||
matches = /[?&]u(?:rl)?=([^&]+)/.exec(requestURL);
|
||||
if ( matches === null ) { return; }
|
||||
details.type = 'websocket';
|
||||
details.url = decodeURIComponent(matches[1]);
|
||||
var r = onBeforeRequestClient(details);
|
||||
if ( r && r.cancel ) { return r; }
|
||||
// Redirect to the provided URL, or a 1x1 data: URI if none provided.
|
||||
matches = /[?&]r=([^&]+)/.exec(requestURL);
|
||||
return {
|
||||
redirectUrl: matches !== null ?
|
||||
decodeURIComponent(matches[1]) :
|
||||
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
|
||||
};
|
||||
};
|
||||
|
||||
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
||||
var onBeforeRequest = validTypes.websocket
|
||||
// modern Chromium/WebExtensions: type 'websocket' is supported
|
||||
? function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
}
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
// https://github.com/gorhill/uBlock/issues/1497
|
||||
if ( details.url.endsWith('ubofix=f41665f3028c7fd10eecf573336216d3') ) {
|
||||
var r = onBeforeWebsocketRequest(details);
|
||||
if ( r !== undefined ) { return r; }
|
||||
}
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
};
|
||||
|
||||
// This is needed for Chromium 49-55.
|
||||
var onBeforeSendHeaders = validTypes.csp_report
|
||||
// modern Chromium/WebExtensions: type 'csp_report' is supported
|
||||
? null
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
if ( details.type !== 'ping' || details.method !== 'POST' ) { return; }
|
||||
var type = headerValue(details.requestHeaders, 'content-type');
|
||||
if ( type === '' ) { return; }
|
||||
if ( type.endsWith('/csp-report') ) {
|
||||
details.type = 'csp_report';
|
||||
return onBeforeRequestClient(details);
|
||||
}
|
||||
};
|
||||
|
||||
var onHeadersReceivedClient = this.onHeadersReceived.callback,
|
||||
onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0),
|
||||
onHeadersReceivedTypes = denormalizeTypes(onHeadersReceivedClientTypes);
|
||||
var onHeadersReceived = validTypes.font
|
||||
// modern Chromium/WebExtensions: type 'font' is supported
|
||||
? function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
if (
|
||||
onHeadersReceivedClientTypes.length !== 0 &&
|
||||
onHeadersReceivedClientTypes.indexOf(details.type) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return onHeadersReceivedClient(details);
|
||||
}
|
||||
// legacy Chromium
|
||||
: function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
// Hack to work around Chromium API limitations, where requests of
|
||||
// type `font` are returned as `other`. For example, our normalization
|
||||
// fail at transposing `other` into `font` for URLs which are outside
|
||||
// what is expected. At least when headers are received we can check
|
||||
// for content type `font/*`. Blocking at onHeadersReceived time is
|
||||
// less worse than not blocking at all. Also, due to Chromium bug,
|
||||
// `other` always becomes `object` when it can't be normalized into
|
||||
// something else. Test case for "unfriendly" font URLs:
|
||||
// https://www.google.com/fonts
|
||||
if ( details.type === 'font' ) {
|
||||
var r = onBeforeRequestClient(details);
|
||||
if ( typeof r === 'object' && r.cancel === true ) {
|
||||
return { cancel: true };
|
||||
}
|
||||
}
|
||||
if (
|
||||
onHeadersReceivedClientTypes.length !== 0 &&
|
||||
onHeadersReceivedClientTypes.indexOf(details.type) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return onHeadersReceivedClient(details);
|
||||
};
|
||||
|
||||
var urls, types;
|
||||
|
||||
if ( onBeforeRequest ) {
|
||||
urls = this.onBeforeRequest.urls || ['<all_urls>'];
|
||||
types = this.onBeforeRequest.types || undefined;
|
||||
if (
|
||||
(validTypes.websocket) &&
|
||||
(types === undefined || types.indexOf('websocket') !== -1) &&
|
||||
(urls.indexOf('<all_urls>') === -1)
|
||||
) {
|
||||
if ( urls.indexOf('ws://*/*') === -1 ) {
|
||||
urls.push('ws://*/*');
|
||||
}
|
||||
if ( urls.indexOf('wss://*/*') === -1 ) {
|
||||
urls.push('wss://*/*');
|
||||
}
|
||||
}
|
||||
wrApi.onBeforeRequest.addListener(
|
||||
onBeforeRequest,
|
||||
{ urls: urls, types: types },
|
||||
this.onBeforeRequest.extra
|
||||
);
|
||||
}
|
||||
|
||||
// Chromium 48 and lower does not support `ping` type.
|
||||
// Chromium 56 and higher does support `csp_report` stype.
|
||||
if ( onBeforeSendHeaders ) {
|
||||
wrApi.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders,
|
||||
{
|
||||
'urls': [ '<all_urls>' ],
|
||||
'types': [ 'ping' ]
|
||||
},
|
||||
[ 'blocking', 'requestHeaders' ]
|
||||
);
|
||||
}
|
||||
|
||||
if ( onHeadersReceived ) {
|
||||
urls = this.onHeadersReceived.urls || ['<all_urls>'];
|
||||
types = onHeadersReceivedTypes;
|
||||
wrApi.onHeadersReceived.addListener(
|
||||
onHeadersReceived,
|
||||
{ urls: urls, types: types },
|
||||
this.onHeadersReceived.extra
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,184 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uBlock Origin - a browser extension to block requests.
|
||||
Copyright (C) 2017 Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
// For background page
|
||||
|
||||
'use strict';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net = {};
|
||||
|
||||
vAPI.net.registerListeners = function() {
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/2950
|
||||
// Firefox 55 does not normalize URLs to ASCII, uBO must do this itself.
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=945240
|
||||
var belowFirefox56 = false;
|
||||
(function() {
|
||||
if (
|
||||
typeof browser === 'object' &&
|
||||
browser !== null &&
|
||||
browser.runtime instanceof Object &&
|
||||
typeof browser.runtime.getBrowserInfo === 'function'
|
||||
) {
|
||||
browser.runtime.getBrowserInfo().then(info => {
|
||||
belowFirefox56 = info.name === 'Firefox' &&
|
||||
/^5[0-5]\./.test(info.version);
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
var wrApi = browser.webRequest;
|
||||
|
||||
// legacy Chromium understands only these network request types.
|
||||
var validTypes = {
|
||||
main_frame: true,
|
||||
sub_frame: true,
|
||||
stylesheet: true,
|
||||
script: true,
|
||||
image: true,
|
||||
object: true,
|
||||
xmlhttprequest: true,
|
||||
other: true
|
||||
};
|
||||
// modern Chromium/WebExtensions: more types available.
|
||||
if ( wrApi.ResourceType ) {
|
||||
(function() {
|
||||
for ( var typeKey in wrApi.ResourceType ) {
|
||||
if ( wrApi.ResourceType.hasOwnProperty(typeKey) ) {
|
||||
validTypes[wrApi.ResourceType[typeKey]] = true;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
var denormalizeTypes = function(aa) {
|
||||
if ( aa.length === 0 ) {
|
||||
return Object.keys(validTypes);
|
||||
}
|
||||
var out = [];
|
||||
var i = aa.length,
|
||||
type,
|
||||
needOther = true;
|
||||
while ( i-- ) {
|
||||
type = aa[i];
|
||||
if ( validTypes[type] ) {
|
||||
out.push(type);
|
||||
}
|
||||
if ( type === 'other' ) {
|
||||
needOther = false;
|
||||
}
|
||||
}
|
||||
if ( needOther ) {
|
||||
out.push('other');
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
var punycode = self.punycode;
|
||||
var reMustNormalizeHostname = /[^0-9a-z._-]/;
|
||||
var parsedURL = new URL('about:blank');
|
||||
|
||||
var normalizeRequestDetails = function(details) {
|
||||
details.tabId = details.tabId.toString();
|
||||
|
||||
if (
|
||||
belowFirefox56 === true &&
|
||||
reMustNormalizeHostname.test(details.url) === true
|
||||
) {
|
||||
parsedURL.href = details.url;
|
||||
details.url = details.url.replace(
|
||||
parsedURL.hostname,
|
||||
punycode.toASCII(parsedURL.hostname)
|
||||
);
|
||||
}
|
||||
|
||||
var type = details.type;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1493
|
||||
// Chromium 49+/WebExtensions support a new request type: `ping`,
|
||||
// which is fired as a result of using `navigator.sendBeacon`.
|
||||
if ( type === 'ping' ) {
|
||||
details.type = 'beacon';
|
||||
return;
|
||||
}
|
||||
|
||||
if ( type === 'imageset' ) {
|
||||
details.type = 'image';
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
||||
var onBeforeRequest = function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
return onBeforeRequestClient(details);
|
||||
};
|
||||
|
||||
var onHeadersReceivedClient = this.onHeadersReceived.callback,
|
||||
onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0),
|
||||
onHeadersReceivedTypes = denormalizeTypes(onHeadersReceivedClientTypes);
|
||||
var onHeadersReceived = function(details) {
|
||||
normalizeRequestDetails(details);
|
||||
if (
|
||||
onHeadersReceivedClientTypes.length !== 0 &&
|
||||
onHeadersReceivedClientTypes.indexOf(details.type) === -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return onHeadersReceivedClient(details);
|
||||
};
|
||||
|
||||
if ( onBeforeRequest ) {
|
||||
let urls = this.onBeforeRequest.urls || ['<all_urls>'];
|
||||
let types = this.onBeforeRequest.types || undefined;
|
||||
if (
|
||||
(validTypes.websocket) &&
|
||||
(types === undefined || types.indexOf('websocket') !== -1) &&
|
||||
(urls.indexOf('<all_urls>') === -1)
|
||||
) {
|
||||
if ( urls.indexOf('ws://*/*') === -1 ) {
|
||||
urls.push('ws://*/*');
|
||||
}
|
||||
if ( urls.indexOf('wss://*/*') === -1 ) {
|
||||
urls.push('wss://*/*');
|
||||
}
|
||||
}
|
||||
wrApi.onBeforeRequest.addListener(
|
||||
onBeforeRequest,
|
||||
{ urls: urls, types: types },
|
||||
this.onBeforeRequest.extra
|
||||
);
|
||||
}
|
||||
|
||||
if ( onHeadersReceived ) {
|
||||
let urls = this.onHeadersReceived.urls || ['<all_urls>'];
|
||||
let types = onHeadersReceivedTypes;
|
||||
wrApi.onHeadersReceived.addListener(
|
||||
onHeadersReceived,
|
||||
{ urls: urls, types: types },
|
||||
this.onHeadersReceived.extra
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
|
@ -10,6 +10,7 @@
|
|||
<script src="lib/publicsuffixlist.js"></script>
|
||||
<script src="js/vapi-common.js"></script>
|
||||
<script src="js/vapi-background.js"></script>
|
||||
<script src="js/vapi-webrequest.js"></script><!-- Forks can pick the webext, chromium, or their own implementation -->
|
||||
<script src="js/vapi-cachestorage.js"></script><!-- Optional -->
|
||||
<script src="js/background.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
|
|
|
@ -27,6 +27,7 @@ cp LICENSE.txt $DES/
|
|||
cp platform/webext/manifest.json $DES/
|
||||
cp platform/webext/options_ui.html $DES/
|
||||
cp platform/webext/polyfill.js $DES/js/
|
||||
cp platform/webext/vapi-webrequest.js $DES/js/
|
||||
cp platform/webext/vapi-cachestorage.js $DES/js/
|
||||
cp platform/webext/vapi-usercss.js $DES/js/
|
||||
rm $DES/js/options_ui.js
|
||||
|
|
Loading…
Reference in New Issue