Add ability to block early at launch; adapt to changes in Chromium 72+
Related issues: - "Requests bypass uMatrix on Firefox start" <https://github.com/uBlockOrigin/uMatrix-issues/issues/69> Using same approach as with uBO: https://github.com/gorhill/uBloc/commit/41548be6be35 `suspendTabsUntilReady` advanced setting added to "More" pane, useful only for Chromium -- the blocking of early network requests is enforced unconditionally on Firefox (because it supports returning Promises from webRequest handlers). - "Cookies leaking temporarily" <https://github.com/uBlockOrigin/uMatrix-issues/issues/74> Changes in the webRequest API in Chromium 72+ caused uMatrix to fail to process `Cookie` and `Referer` headers on that platform.pull/2/head
parent
3cc56afe63
commit
fb94c85df1
@ -1,234 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uMatrix - 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/uMatrix
|
|
||||||
|
|
||||||
This file has been originally imported from:
|
|
||||||
https://github.com/gorhill/uBlock/tree/master/platform/chromium
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// For background page or non-background pages
|
|
||||||
|
|
||||||
/* exported objectAssign */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1067
|
|
||||||
// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
|
||||||
// Firefox 17/Chromium 41 supports `startsWith`.
|
|
||||||
|
|
||||||
if ( String.prototype.startsWith instanceof Function === false ) {
|
|
||||||
String.prototype.startsWith = function(needle, pos) {
|
|
||||||
if ( typeof pos !== 'number' ) {
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
return this.lastIndexOf(needle, pos) === pos;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1067
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
|
||||||
// Firefox 17/Chromium 41 supports `endsWith`.
|
|
||||||
|
|
||||||
if ( String.prototype.endsWith instanceof Function === false ) {
|
|
||||||
String.prototype.endsWith = function(needle, pos) {
|
|
||||||
if ( typeof pos !== 'number' ) {
|
|
||||||
pos = this.length;
|
|
||||||
}
|
|
||||||
pos -= needle.length;
|
|
||||||
return this.indexOf(needle, pos) === pos;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// As per MDN, Object.assign appeared first in Chromium 45.
|
|
||||||
// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility
|
|
||||||
|
|
||||||
var objectAssign = Object.assign || function(target, source) {
|
|
||||||
var keys = Object.keys(source);
|
|
||||||
for ( var i = 0, n = keys.length, key; i < n; i++ ) {
|
|
||||||
key = keys[i];
|
|
||||||
target[key] = source[key];
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1070
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility
|
|
||||||
// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this
|
|
||||||
// is not an accurate API of the real Set() type.
|
|
||||||
|
|
||||||
if ( self.Set instanceof Function === false ) {
|
|
||||||
self.Set = function(iter) {
|
|
||||||
this.clear();
|
|
||||||
if ( Array.isArray(iter) ) {
|
|
||||||
for ( var i = 0, n = iter.length; i < n; i++ ) {
|
|
||||||
this.add(iter[i]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.polyfill = true;
|
|
||||||
|
|
||||||
self.Set.prototype.clear = function() {
|
|
||||||
this._set = Object.create(null);
|
|
||||||
this.size = 0;
|
|
||||||
// Iterator stuff
|
|
||||||
this._values = undefined;
|
|
||||||
this._i = undefined;
|
|
||||||
this.value = undefined;
|
|
||||||
this.done = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.prototype.add = function(k) {
|
|
||||||
if ( this._set[k] === undefined ) {
|
|
||||||
this._set[k] = true;
|
|
||||||
this.size += 1;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.prototype.delete = function(k) {
|
|
||||||
if ( this._set[k] !== undefined ) {
|
|
||||||
delete this._set[k];
|
|
||||||
this.size -= 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.prototype.has = function(k) {
|
|
||||||
return this._set[k] !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.prototype.next = function() {
|
|
||||||
if ( this._i < this.size ) {
|
|
||||||
this.value = this._values[this._i++];
|
|
||||||
} else {
|
|
||||||
this._values = undefined;
|
|
||||||
this.value = undefined;
|
|
||||||
this.done = true;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Set.prototype.values = function() {
|
|
||||||
this._values = Object.keys(this._set);
|
|
||||||
this._i = 0;
|
|
||||||
this.value = undefined;
|
|
||||||
this.done = false;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1070
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility
|
|
||||||
// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this
|
|
||||||
// is not an accurate API of the real Map() type.
|
|
||||||
|
|
||||||
if ( self.Map instanceof Function === false ) {
|
|
||||||
self.Map = function(iter) {
|
|
||||||
this.clear();
|
|
||||||
if ( Array.isArray(iter) ) {
|
|
||||||
for ( var i = 0, n = iter.length, entry; i < n; i++ ) {
|
|
||||||
entry = iter[i];
|
|
||||||
this.set(entry[0], entry[1]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.polyfill = true;
|
|
||||||
|
|
||||||
self.Map.prototype.clear = function() {
|
|
||||||
this._map = Object.create(null);
|
|
||||||
this.size = 0;
|
|
||||||
// Iterator stuff
|
|
||||||
this._keys = undefined;
|
|
||||||
this._i = undefined;
|
|
||||||
this.value = undefined;
|
|
||||||
this.done = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.delete = function(k) {
|
|
||||||
if ( this._map[k] !== undefined ) {
|
|
||||||
delete this._map[k];
|
|
||||||
this.size -= 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.entries = function() {
|
|
||||||
this._keys = Object.keys(this._map);
|
|
||||||
this._i = 0;
|
|
||||||
this.value = [ undefined, undefined ];
|
|
||||||
this.done = false;
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.get = function(k) {
|
|
||||||
return this._map[k];
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.has = function(k) {
|
|
||||||
return this._map[k] !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.next = function() {
|
|
||||||
if ( this._i < this.size ) {
|
|
||||||
var key = this._keys[this._i++];
|
|
||||||
this.value[0] = key;
|
|
||||||
this.value[1] = this._map[key];
|
|
||||||
} else {
|
|
||||||
this._keys = undefined;
|
|
||||||
this.value = undefined;
|
|
||||||
this.done = true;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.Map.prototype.set = function(k, v) {
|
|
||||||
if ( v !== undefined ) {
|
|
||||||
if ( this._map[k] === undefined ) {
|
|
||||||
this.size += 1;
|
|
||||||
}
|
|
||||||
this._map[k] = v;
|
|
||||||
} else {
|
|
||||||
if ( this._map[k] !== undefined ) {
|
|
||||||
this.size -= 1;
|
|
||||||
}
|
|
||||||
delete this._map[k];
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
@ -0,0 +1,194 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uMatrix - a browser extension to block requests.
|
||||||
|
Copyright (C) 2017-present 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/uMatrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For background page
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const 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']
|
||||||
|
]);
|
||||||
|
|
||||||
|
// https://www.reddit.com/r/uBlockOrigin/comments/9vcrk3/bug_in_ubo_1173_betas_when_saving_files_hosted_on/
|
||||||
|
// Some types can be mapped from 'other', thus include 'other' if and
|
||||||
|
// only if the caller is interested in at least one of those types.
|
||||||
|
const denormalizeTypes = function(aa) {
|
||||||
|
if ( aa.length === 0 ) {
|
||||||
|
return Array.from(vAPI.net.validTypes);
|
||||||
|
}
|
||||||
|
const out = new Set();
|
||||||
|
let i = aa.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
const type = aa[i];
|
||||||
|
if ( vAPI.net.validTypes.has(type) ) {
|
||||||
|
out.add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( out.has('other') === false ) {
|
||||||
|
for ( const type of extToTypeMap.values() ) {
|
||||||
|
if ( out.has(type) ) {
|
||||||
|
out.add('other');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(out);
|
||||||
|
};
|
||||||
|
|
||||||
|
const headerValue = function(headers, name) {
|
||||||
|
let i = headers.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( headers[i].name.toLowerCase() === name ) {
|
||||||
|
return headers[i].value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const parsedURL = new URL('https://www.example.org/');
|
||||||
|
|
||||||
|
vAPI.net.normalizeDetails = function(details) {
|
||||||
|
// Chromium 63+ supports the `initiator` property, which contains
|
||||||
|
// the URL of the origin from which the network request was made.
|
||||||
|
if (
|
||||||
|
typeof details.initiator === 'string' &&
|
||||||
|
details.initiator !== 'null'
|
||||||
|
) {
|
||||||
|
details.documentUrl = details.initiator;
|
||||||
|
}
|
||||||
|
|
||||||
|
let 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.
|
||||||
|
parsedURL.href = details.url;
|
||||||
|
const path = parsedURL.pathname,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vAPI.net.denormalizeFilters = function(filters) {
|
||||||
|
const urls = filters.urls || [ '<all_urls>' ];
|
||||||
|
let types = filters.types;
|
||||||
|
if ( Array.isArray(types) ) {
|
||||||
|
types = denormalizeTypes(types);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(vAPI.net.validTypes.has('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://*/*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { types, urls };
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/2067
|
||||||
|
// Experimental: Block everything until uBO is fully ready.
|
||||||
|
|
||||||
|
vAPI.net.onBeforeReady = (function() {
|
||||||
|
let pendings;
|
||||||
|
|
||||||
|
const handler = function(details) {
|
||||||
|
if ( pendings === undefined ) { return; }
|
||||||
|
if ( details.tabId < 0 ) { return; }
|
||||||
|
|
||||||
|
pendings.add(details.tabId);
|
||||||
|
|
||||||
|
//console.log(`Aborting tab ${details.tabId}: ${details.type} ${details.url}`);
|
||||||
|
|
||||||
|
return { cancel: true };
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
experimental: true,
|
||||||
|
start: function() {
|
||||||
|
pendings = new Set();
|
||||||
|
browser.webRequest.onBeforeRequest.addListener(
|
||||||
|
handler,
|
||||||
|
{ urls: [ 'http://*/*', 'https://*/*' ] },
|
||||||
|
[ 'blocking' ]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// https://github.com/gorhill/uBlock/issues/2067
|
||||||
|
// Force-reload tabs for which network requests were blocked
|
||||||
|
// during launch. This can happen only if tabs were "suspended".
|
||||||
|
stop: function() {
|
||||||
|
if ( pendings === undefined ) { return; }
|
||||||
|
browser.webRequest.onBeforeRequest.removeListener(handler);
|
||||||
|
for ( const tabId of pendings ) {
|
||||||
|
//console.log(`Reloading tab ${tabId}`);
|
||||||
|
vAPI.tabs.reload(tabId);
|
||||||
|
}
|
||||||
|
pendings = undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2016 The uBlock Origin authors
|
|
||||||
|
|
||||||
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 or non-background pages
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var objectAssign = Object.assign;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uMatrix - a browser extension to block requests.
|
||||||
|
Copyright (C) 2017-present 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/uMatrix
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For background page
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/2950
|
||||||
|
// Firefox 56 does not normalize URLs to ASCII, uBO must do this itself.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=945240
|
||||||
|
const evalMustPunycode = function() {
|
||||||
|
return vAPI.webextFlavor.soup.has('firefox') &&
|
||||||
|
vAPI.webextFlavor.major < 57;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mustPunycode = evalMustPunycode();
|
||||||
|
|
||||||
|
// The real actual webextFlavor value may not be set in stone, so listen
|
||||||
|
// for possible future changes.
|
||||||
|
window.addEventListener('webextFlavor', ( ) => {
|
||||||
|
mustPunycode = evalMustPunycode();
|
||||||
|
}, { once: true });
|
||||||
|
|
||||||
|
const denormalizeTypes = function(aa) {
|
||||||
|
if ( aa.length === 0 ) {
|
||||||
|
return Array.from(vAPI.net.validTypes);
|
||||||
|
}
|
||||||
|
const out = new Set();
|
||||||
|
let i = aa.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
let type = aa[i];
|
||||||
|
if ( vAPI.net.validTypes.has(type) ) {
|
||||||
|
out.add(type);
|
||||||
|
}
|
||||||
|
if ( type === 'image' && vAPI.net.validTypes.has('imageset') ) {
|
||||||
|
out.add('imageset');
|
||||||
|
}
|
||||||
|
if ( type === 'sub_frame' ) {
|
||||||
|
out.add('object');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Array.from(out);
|
||||||
|
};
|
||||||
|
|
||||||
|
const punycode = self.punycode;
|
||||||
|
const reAsciiHostname = /^https?:\/\/[0-9a-z_.:@-]+[/?#]/;
|
||||||
|
const parsedURL = new URL('about:blank');
|
||||||
|
|
||||||
|
vAPI.net.normalizeDetails = function(details) {
|
||||||
|
if ( mustPunycode && !reAsciiHostname.test(details.url) ) {
|
||||||
|
parsedURL.href = details.url;
|
||||||
|
details.url = details.url.replace(
|
||||||
|
parsedURL.hostname,
|
||||||
|
punycode.toASCII(parsedURL.hostname)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/345
|
||||||
|
// Re-categorize an embedded object as a `sub_frame` if its
|
||||||
|
// content type is that of a HTML document.
|
||||||
|
if ( type === 'object' && Array.isArray(details.responseHeaders) ) {
|
||||||
|
for ( const header of details.responseHeaders ) {
|
||||||
|
if ( header.name.toLowerCase() === 'content-type' ) {
|
||||||
|
if ( header.value.startsWith('text/html') ) {
|
||||||
|
details.type = 'sub_frame';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vAPI.net.denormalizeFilters = function(filters) {
|
||||||
|
const urls = filters.urls || [ '<all_urls>' ];
|
||||||
|
let types = filters.types;
|
||||||
|
if ( Array.isArray(types) ) {
|
||||||
|
types = denormalizeTypes(types);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(vAPI.net.validTypes.has('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://*/*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { types, urls };
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// Related issues:
|
||||||
|
// - https://github.com/gorhill/uBlock/issues/1327
|
||||||
|
// - https://github.com/uBlockOrigin/uBlock-issues/issues/128
|
||||||
|
// - https://bugzilla.mozilla.org/show_bug.cgi?id=1503721
|
||||||
|
|
||||||
|
vAPI.net.onBeforeReady = (function() {
|
||||||
|
let pendings;
|
||||||
|
|
||||||
|
const handler = function(details) {
|
||||||
|
if ( pendings === undefined ) { return; }
|
||||||
|
if ( details.tabId < 0 ) { return; }
|
||||||
|
|
||||||
|
//console.log(`Deferring tab ${details.tabId}: ${details.type} ${details.url}`);
|
||||||
|
|
||||||
|
const pending = {
|
||||||
|
details: Object.assign({}, details),
|
||||||
|
resolve: undefined,
|
||||||
|
promise: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
pending.promise = new Promise(function(resolve) {
|
||||||
|
pending.resolve = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
pendings.push(pending);
|
||||||
|
|
||||||
|
return pending.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: function() {
|
||||||
|
pendings = [];
|
||||||
|
browser.webRequest.onBeforeRequest.addListener(
|
||||||
|
handler,
|
||||||
|
{ urls: [ 'http://*/*', 'https://*/*' ] },
|
||||||
|
[ 'blocking' ]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
stop: function(resolver) {
|
||||||
|
if ( pendings === undefined ) { return; }
|
||||||
|
for ( const pending of pendings ) {
|
||||||
|
const details = pending.details;
|
||||||
|
vAPI.net.normalizeDetails(details);
|
||||||
|
//console.log(`Processing tab ${details.tabId}: ${details.type} ${details.url}`);
|
||||||
|
pending.resolve(resolver(details));
|
||||||
|
}
|
||||||
|
pendings = undefined;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
Loading…
Reference in New Issue