diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 66c2249bf..7ec139227 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -1049,9 +1049,9 @@ vAPI.messaging.broadcast = function(message) { // https://github.com/gorhill/uBlock/issues/3497 // Prevent web pages from interfering with uBO's element picker // https://github.com/uBlockOrigin/uBlock-issues/issues/550 -// A specific secret can be used for at most one second. +// Support using a new secret for every network request. -vAPI.warSecret = (function() { +vAPI.warSecret = (( ) => { const generateSecret = ( ) => { return Math.floor(Math.random() * 982451653 + 982451653).toString(36) + Math.floor(Math.random() * 982451653 + 982451653).toString(36); @@ -1072,7 +1072,7 @@ vAPI.warSecret = (function() { secrets.splice(pos, 1); }; - chrome.webRequest.onBeforeRequest.addListener( + browser.webRequest.onBeforeRequest.addListener( guard, { urls: [ root + 'web_accessible_resources/*' ] @@ -1095,59 +1095,106 @@ vAPI.warSecret = (function() { }; })(); -vAPI.net = { - listenerMap: new WeakMap(), - // legacy Chromium understands only these network request types. - validTypes: (function() { - let types = new Set([ - 'main_frame', - 'sub_frame', - 'stylesheet', - 'script', - 'image', - 'object', - 'xmlhttprequest', - 'other' - ]); - let wrrt = browser.webRequest.ResourceType; - if ( wrrt instanceof Object ) { - for ( let typeKey in wrrt ) { +/******************************************************************************/ + +vAPI.Net = class { + constructor() { + this.validTypes = new Set(); + { + const wrrt = browser.webRequest.ResourceType; + for ( const typeKey in wrrt ) { if ( wrrt.hasOwnProperty(typeKey) ) { - types.add(wrrt[typeKey]); + this.validTypes.add(wrrt[typeKey]); } } } + this.suspendableListener = undefined; + this.listenerMap = new WeakMap(); + this.suspendDepth = 0; + + browser.webRequest.onBeforeRequest.addListener( + details => { + this.normalizeDetails(details); + if ( this.suspendDepth === 0 ) { + if ( this.suspendableListener === undefined ) { return; } + return this.suspendableListener(details); + } + if ( details.tabId < 0 ) { return; } + return this.suspendOneRequest(details); + }, + this.denormalizeFilters({ urls: [ 'http://*/*', 'https://*/*' ] }), + [ 'blocking' ] + ); + } + normalizeDetails(/* details */) { + } + denormalizeFilters(filters) { + const urls = filters.urls || [ '' ]; + let types = filters.types; + if ( Array.isArray(types) ) { + types = this.denormalizeTypes(types); + } + if ( + (this.validTypes.has('websocket')) && + (types === undefined || types.indexOf('websocket') !== -1) && + (urls.indexOf('') === -1) + ) { + if ( urls.indexOf('ws://*/*') === -1 ) { + urls.push('ws://*/*'); + } + if ( urls.indexOf('wss://*/*') === -1 ) { + urls.push('wss://*/*'); + } + } + return { types, urls }; + } + denormalizeTypes(types) { return types; - })(), - denormalizeFilters: null, - normalizeDetails: null, - addListener: function(which, clientListener, filters, options) { - if ( typeof this.denormalizeFilters === 'function' ) { - filters = this.denormalizeFilters(filters); - } - let actualListener; - if ( typeof this.normalizeDetails === 'function' ) { - actualListener = function(details) { - vAPI.net.normalizeDetails(details); - return clientListener(details); - }; - this.listenerMap.set(clientListener, actualListener); - } + } + addListener(which, clientListener, filters, options) { + const actualFilters = this.denormalizeFilters(filters); + const actualListener = this.makeNewListenerProxy(clientListener); browser.webRequest[which].addListener( - actualListener || clientListener, - filters, + actualListener, + actualFilters, options ); - }, - removeListener: function(which, clientListener) { - let actualListener = this.listenerMap.get(clientListener); - if ( actualListener !== undefined ) { - this.listenerMap.delete(clientListener); + } + setSuspendableListener(listener) { + this.suspendableListener = listener; + } + removeListener(which, clientListener) { + const actualListener = this.listenerMap.get(clientListener); + if ( actualListener === undefined ) { return; } + this.listenerMap.delete(clientListener); + browser.webRequest[which].removeListener(actualListener); + } + makeNewListenerProxy(clientListener) { + const actualListener = details => { + this.normalizeDetails(details); + return clientListener(details); + }; + this.listenerMap.set(clientListener, actualListener); + return actualListener; + } + suspendOneRequest() { + } + unsuspendAllRequests() { + } + suspend(force = false) { + if ( this.canSuspend() || force ) { + this.suspendDepth += 1; } - browser.webRequest[which].removeListener( - actualListener || clientListener - ); - }, + } + unsuspend() { + if ( this.suspendDepth === 0 ) { return; } + this.suspendDepth -= 1; + if ( this.suspendDepth !== 0 ) { return; } + this.unsuspendAllRequests(this.suspendableListener); + } + canSuspend() { + return false; + } }; /******************************************************************************/ diff --git a/platform/chromium/vapi-webrequest.js b/platform/chromium/vapi-webrequest.js index 7f9026ef8..14fe851ee 100644 --- a/platform/chromium/vapi-webrequest.js +++ b/platform/chromium/vapi-webrequest.js @@ -25,9 +25,9 @@ /******************************************************************************/ -(function() { +(( ) => { // https://github.com/uBlockOrigin/uBlock-issues/issues/407 - if ( vAPI.webextFlavor.soup.has('firefox') ) { return; } + if ( vAPI.webextFlavor.soup.has('chromium') === false ) { return; } const extToTypeMap = new Map([ ['eot','font'],['otf','font'],['svg','font'],['ttf','font'],['woff','font'],['woff2','font'], @@ -35,33 +35,7 @@ ['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) { + const headerValue = (headers, name) => { let i = headers.length; while ( i-- ) { if ( headers[i].name.toLowerCase() === name ) { @@ -73,124 +47,100 @@ 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; + // Extend base class to normalize as per platform. + + vAPI.Net = class extends vAPI.Net { + constructor() { + super(); + this.suspendedTabIds = new Set(); } + normalizeDetails(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; + 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'; + // 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.startsWith('image/') ) { + + if ( type === 'imageset' ) { details.type = 'image'; return; } - if ( type.startsWith('audio/') || type.startsWith('video/') ) { - details.type = 'media'; + + // 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; } - } - }; - vAPI.net.denormalizeFilters = function(filters) { - const urls = filters.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('') === -1) - ) { - if ( urls.indexOf('ws://*/*') === -1 ) { - urls.push('ws://*/*'); - } - if ( urls.indexOf('wss://*/*') === -1 ) { - urls.push('wss://*/*'); + // 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; + } } } - return { types, urls }; - }; -})(); - -/******************************************************************************/ - -// https://github.com/gorhill/uBlock/issues/2067 -// Experimental: Block everything until uBO is fully ready. - -vAPI.net.onBeforeReady = vAPI.net.onBeforeReady || (function() { - // https://github.com/uBlockOrigin/uBlock-issues/issues/407 - if ( vAPI.webextFlavor.soup.has('firefox') ) { return; } - - let pendings; - - const handler = function(details) { - if ( pendings === undefined ) { return; } - if ( details.tabId < 0 ) { return; } - - pendings.add(details.tabId); - - 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 ) { + // https://www.reddit.com/r/uBlockOrigin/comments/9vcrk3/ + // 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. + denormalizeTypes(types) { + if ( types.length === 0 ) { + return Array.from(this.validTypes); + } + const out = new Set(); + for ( const type of types ) { + if ( this.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); + } + suspendOneRequest(details) { + this.suspendedTabIds.add(details.tabId); + return { cancel: true }; + } + unsuspendAllRequests() { + for ( const tabId of this.suspendedTabIds ) { vAPI.tabs.reload(tabId); } - pendings = undefined; - }, + this.suspendedTabIds.clear(); + } }; })(); @@ -200,7 +150,10 @@ vAPI.net.onBeforeReady = vAPI.net.onBeforeReady || (function() { // Use `X-DNS-Prefetch-Control` to workaround Chromium's disregard of the // setting "Predict network actions to improve page load performance". -vAPI.prefetching = (function() { +vAPI.prefetching = (( ) => { + // https://github.com/uBlockOrigin/uBlock-issues/issues/407 + if ( vAPI.webextFlavor.soup.has('chromium') === false ) { return; } + let listening = false; const onHeadersReceived = function(details) { diff --git a/platform/firefox/vapi-webrequest.js b/platform/firefox/vapi-webrequest.js index 547ad2e7e..ca85827a4 100644 --- a/platform/firefox/vapi-webrequest.js +++ b/platform/firefox/vapi-webrequest.js @@ -25,14 +25,14 @@ /******************************************************************************/ -(function() { +(( ) => { // https://github.com/uBlockOrigin/uBlock-issues/issues/407 if ( vAPI.webextFlavor.soup.has('firefox') === false ) { return; } // 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() { + const evalMustPunycode = ( ) => { return vAPI.webextFlavor.soup.has('firefox') && vAPI.webextFlavor.major < 57; }; @@ -45,142 +45,100 @@ 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) - ); + // 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 + + // Extend base class to normalize as per platform. + + vAPI.Net = class extends vAPI.Net { + constructor() { + super(); + this.pendingRequests = []; } + normalizeDetails(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; + 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; - } + // 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; - } + 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'; + // 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; } - break; } } } - }; - - vAPI.net.denormalizeFilters = function(filters) { - const urls = filters.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('') === -1) - ) { - if ( urls.indexOf('ws://*/*') === -1 ) { - urls.push('ws://*/*'); + denormalizeTypes(types) { + if ( types.length === 0 ) { + return Array.from(this.validTypes); } - if ( urls.indexOf('wss://*/*') === -1 ) { - urls.push('wss://*/*'); + const out = new Set(); + for ( const type of types ) { + if ( this.validTypes.has(type) ) { + out.add(type); + } + if ( type === 'image' && this.validTypes.has('imageset') ) { + out.add('imageset'); + } + if ( type === 'sub_frame' ) { + out.add('object'); + } } + return Array.from(out); } - 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 = vAPI.net.onBeforeReady || (function() { - // https://github.com/uBlockOrigin/uBlock-issues/issues/407 - if ( vAPI.webextFlavor.soup.has('firefox') === false ) { return; } - - let pendingSet; - - const handler = function(details) { - if ( pendingSet === undefined ) { return; } - if ( details.tabId < 0 ) { return; } - - const pending = { - details: Object.assign({}, details), - resolve: undefined, - promise: undefined - }; - - pending.promise = new Promise(function(resolve) { - pending.resolve = resolve; - }); - - pendingSet.push(pending); - - return pending.promise; - }; - - return { - start: function() { - pendingSet = []; - browser.webRequest.onBeforeRequest.addListener( - handler, - { urls: [ 'http://*/*', 'https://*/*' ] }, - [ 'blocking' ] - ); - }, - stop: function(resolver) { - if ( pendingSet === undefined ) { return; } - const resolvingSet = pendingSet; // not sure if re-entrance - pendingSet = undefined; // can occur... - for ( const entry of resolvingSet ) { - vAPI.net.normalizeDetails(entry.details); + suspendOneRequest(details) { + const pending = { + details: Object.assign({}, details), + resolve: undefined, + promise: undefined + }; + pending.promise = new Promise(function(resolve) { + pending.resolve = resolve; + }); + this.pendingRequests.push(pending); + return pending.promise; + } + unsuspendAllRequests(resolver) { + const pendingRequests = this.pendingRequests; + this.pendingRequests = []; + for ( const entry of pendingRequests ) { entry.resolve(resolver(entry.details)); } - }, + } + canSuspend() { + return true; + } }; })(); diff --git a/platform/thunderbird/vapi-webrequest.js b/platform/thunderbird/vapi-webrequest.js deleted file mode 100644 index 674351735..000000000 --- a/platform/thunderbird/vapi-webrequest.js +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - - uBlock Origin - 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/uBlock -*/ - -// 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) { - let urls = filters.urls || [ '' ]; - if ( urls.indexOf('https://*/*') !== -1 ) { - 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('') === -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; } - - 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 ) { - vAPI.net.normalizeDetails(pending.details); - pending.resolve(resolver(pending.details)); - } - pendings = undefined; - }, - }; -})(); - -/******************************************************************************/ diff --git a/src/js/storage.js b/src/js/storage.js index a3e889adc..7ccdb3f60 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -660,6 +660,8 @@ this.staticNetFilteringEngine.freeze(); this.staticExtFilteringEngine.freeze(); this.redirectEngine.freeze(); + vAPI.net.unsuspend(); + vAPI.storage.set({ 'availableFilterLists': this.availableFilterLists }); vAPI.messaging.broadcast({ @@ -702,8 +704,7 @@ }; const onFilterListsReady = lists => { - this.availableFilterLists = lists; - + vAPI.net.suspend(); this.redirectEngine.reset(); this.staticExtFilteringEngine.reset(); this.staticNetFilteringEngine.reset(); diff --git a/src/js/traffic.js b/src/js/traffic.js index 77c54453e..1df0bdaaf 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -25,7 +25,7 @@ // Start isolation from global scope -µBlock.webRequest = (function() { +µBlock.webRequest = (( ) => { /******************************************************************************/ @@ -1028,26 +1028,20 @@ const strictBlockBypasser = { /******************************************************************************/ return { - start: (function() { + start: (( ) => { + vAPI.net = new vAPI.Net(); + if ( - vAPI.net.onBeforeReady instanceof Object && - ( - vAPI.net.onBeforeReady.experimental !== true && - µBlock.hiddenSettings.suspendTabsUntilReady !== 'no' || - vAPI.net.onBeforeReady.experimental && - µBlock.hiddenSettings.suspendTabsUntilReady === 'yes' - ) + vAPI.net.canSuspend() && + µBlock.hiddenSettings.suspendTabsUntilReady !== 'no' || + vAPI.net.canSuspend() !== true && + µBlock.hiddenSettings.suspendTabsUntilReady === 'yes' ) { - vAPI.net.onBeforeReady.start(); + vAPI.net.suspend(true); } return function() { - vAPI.net.addListener( - 'onBeforeRequest', - onBeforeRequest, - { urls: [ 'http://*/*', 'https://*/*' ] }, - [ 'blocking' ] - ); + vAPI.net.setSuspendableListener(onBeforeRequest); vAPI.net.addListener( 'onHeadersReceived', onHeadersReceived, @@ -1074,9 +1068,7 @@ return { [ 'blocking', 'requestBody' ] ); } - if ( vAPI.net.onBeforeReady instanceof Object ) { - vAPI.net.onBeforeReady.stop(onBeforeRequest); - } + vAPI.net.unsuspend(); }; })(), diff --git a/tools/make-thunderbird.sh b/tools/make-thunderbird.sh index 9854e5cbb..1df213eb6 100755 --- a/tools/make-thunderbird.sh +++ b/tools/make-thunderbird.sh @@ -24,9 +24,9 @@ cp platform/chromium/*.html $DES/ cp platform/chromium/*.json $DES/ cp LICENSE.txt $DES/ -cp platform/thunderbird/manifest.json $DES/ -cp platform/thunderbird/vapi-webrequest.js $DES/js/ -cp platform/firefox/vapi-usercss.js $DES/js/ +cp platform/thunderbird/manifest.json $DES/ +cp platform/firefox/vapi-webrequest.js $DES/js/ +cp platform/firefox/vapi-usercss.js $DES/js/ echo "*** uBlock0.thunderbird: concatenating content scripts" cat $DES/js/vapi-usercss.js > /tmp/contentscript.js