lots of informal fixes

- us integer tab id -- do not stringify anymore
- improved the parsing of hosts files
- better handling of behind-the-scene network requests when a
  context is provided by the webRequest API
- imported webextFlavor code from uBO
- converted instances of object-as-dict to Map()
pull/2/head
Raymond Hill 6 years ago
parent dd5a3a807c
commit 31cc15ca6c
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2

@ -3,14 +3,15 @@
"devel": true, "devel": true,
"eqeqeq": true, "eqeqeq": true,
"esnext": true, "esnext": true,
"strict": "global",
"undef": true,
"unused": true,
"globals": { "globals": {
"browser": false, // global variable in Firefox, Edge
"self": false, "self": false,
"chrome": false, "chrome": false,
"vAPI": false, "vAPI": false,
"µMatrix": false, "µMatrix": false
"Components": false // global variable in Firefox },
} "strict": "global",
"undef": true,
"unused": true,
"validthis": true
} }

@ -20,8 +20,6 @@
Home: https://github.com/gorhill/uMatrix Home: https://github.com/gorhill/uMatrix
*/ */
/* global self, µMatrix */
// For background page // For background page
'use strict'; 'use strict';
@ -37,22 +35,13 @@ var vAPI = self.vAPI = self.vAPI || {};
var chrome = self.chrome; var chrome = self.chrome;
var manifest = chrome.runtime.getManifest(); var manifest = chrome.runtime.getManifest();
vAPI.chrome = true;
vAPI.webextFlavor = undefined;
if (
self.browser instanceof Object &&
typeof self.browser.runtime.getBrowserInfo === 'function'
) {
self.browser.runtime.getBrowserInfo().then(function(info) {
vAPI.webextFlavor = info.vendor + '-' + info.name + '-' + info.version;
});
} else {
vAPI.webextFlavor = '';
}
var noopFunc = function(){}; var noopFunc = function(){};
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
var resetLastError = function() {
void chrome.runtime.lastError;
};
/******************************************************************************/ /******************************************************************************/
// https://github.com/gorhill/uMatrix/issues/234 // https://github.com/gorhill/uMatrix/issues/234
@ -96,10 +85,13 @@ vAPI.tabs = {};
/******************************************************************************/ /******************************************************************************/
vAPI.isBehindTheSceneTabId = function(tabId) { vAPI.isBehindTheSceneTabId = function(tabId) {
return tabId.toString() === '-1'; if ( typeof tabId === 'string' ) { debugger; }
return tabId < 0;
}; };
vAPI.noTabId = '-1'; vAPI.unsetTabId = 0;
vAPI.noTabId = -1; // definitely not any existing tab
vAPI.anyTabId = -2; // one of the existing tab
/******************************************************************************/ /******************************************************************************/
@ -126,12 +118,10 @@ vAPI.tabs.registerListeners = function() {
var onCreatedNavigationTarget = function(details) { var onCreatedNavigationTarget = function(details) {
//console.debug('onCreatedNavigationTarget: tab id %d = "%s"', details.tabId, details.url); //console.debug('onCreatedNavigationTarget: tab id %d = "%s"', details.tabId, details.url);
if ( reGoodForWebRequestAPI.test(details.url) ) { return; } if ( reGoodForWebRequestAPI.test(details.url) ) { return; }
details.tabId = details.tabId.toString();
onNavigationClient(details); onNavigationClient(details);
}; };
var onUpdated = function(tabId, changeInfo, tab) { var onUpdated = function(tabId, changeInfo, tab) {
tabId = tabId.toString();
onUpdatedClient(tabId, changeInfo, tab); onUpdatedClient(tabId, changeInfo, tab);
}; };
@ -140,13 +130,12 @@ vAPI.tabs.registerListeners = function() {
if ( details.frameId !== 0 ) { if ( details.frameId !== 0 ) {
return; return;
} }
details.tabId = details.tabId.toString();
onNavigationClient(details); onNavigationClient(details);
//console.debug('onCommitted: tab id %d = "%s"', details.tabId, details.url); //console.debug('onCommitted: tab id %d = "%s"', details.tabId, details.url);
}; };
var onClosed = function(tabId) { var onClosed = function(tabId) {
onClosedClient(tabId.toString()); onClosedClient(tabId);
}; };
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget); chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
@ -161,29 +150,18 @@ vAPI.tabs.registerListeners = function() {
vAPI.tabs.get = function(tabId, callback) { vAPI.tabs.get = function(tabId, callback) {
var onTabReady = function(tab) { var onTabReady = function(tab) {
// https://code.google.com/p/chromium/issues/detail?id=410868#c8 resetLastError();
if ( chrome.runtime.lastError ) {
}
if ( tab instanceof Object ) {
tab.id = tab.id.toString();
}
callback(tab); callback(tab);
}; };
if ( tabId !== null ) { if ( tabId !== null ) {
if ( typeof tabId === 'string' ) {
tabId = parseInt(tabId, 10);
}
chrome.tabs.get(tabId, onTabReady); chrome.tabs.get(tabId, onTabReady);
return; return;
} }
var onTabReceived = function(tabs) { var onTabReceived = function(tabs) {
// https://code.google.com/p/chromium/issues/detail?id=410868#c8 resetLastError();
if ( chrome.runtime.lastError ) {
}
var tab = null; var tab = null;
if ( Array.isArray(tabs) && tabs.length !== 0 ) { if ( Array.isArray(tabs) && tabs.length !== 0 ) {
tab = tabs[0]; tab = tabs[0];
tab.id = tab.id.toString();
} }
callback(tab); callback(tab);
}; };
@ -193,16 +171,7 @@ vAPI.tabs.get = function(tabId, callback) {
/******************************************************************************/ /******************************************************************************/
vAPI.tabs.getAll = function(callback) { vAPI.tabs.getAll = function(callback) {
var onTabsReady = function(tabs) { chrome.tabs.query({ url: '<all_urls>' }, callback);
if ( Array.isArray(tabs) ) {
var i = tabs.length;
while ( i-- ) {
tabs[i].id = tabs[i].id.toString();
}
}
callback(tabs);
};
chrome.tabs.query({ url: '<all_urls>' }, onTabsReady);
}; };
/******************************************************************************/ /******************************************************************************/
@ -254,7 +223,7 @@ vAPI.tabs.open = function(details) {
} }
// update doesn't accept index, must use move // update doesn't accept index, must use move
chrome.tabs.update(parseInt(details.tabId, 10), _details, function(tab) { chrome.tabs.update(details.tabId, _details, function(tab) {
// if the tab doesn't exist // if the tab doesn't exist
if ( vAPI.lastError() ) { if ( vAPI.lastError() ) {
chrome.tabs.create(_details, focusWindow); chrome.tabs.create(_details, focusWindow);
@ -292,7 +261,7 @@ vAPI.tabs.open = function(details) {
} }
chrome.tabs.query({ url: targetURL }, function(tabs) { chrome.tabs.query({ url: targetURL }, function(tabs) {
if ( chrome.runtime.lastError ) { /* noop */ } resetLastError();
var tab = Array.isArray(tabs) && tabs[0]; var tab = Array.isArray(tabs) && tabs[0];
if ( tab ) { if ( tab ) {
chrome.tabs.update(tab.id, { active: true }, function(tab) { chrome.tabs.update(tab.id, { active: true }, function(tab) {
@ -316,40 +285,21 @@ vAPI.tabs.replace = function(tabId, url) {
targetURL = vAPI.getURL(targetURL); targetURL = vAPI.getURL(targetURL);
} }
if ( typeof tabId !== 'number' ) { if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
tabId = parseInt(tabId, 10);
if ( isNaN(tabId) ) {
return;
}
}
chrome.tabs.update(tabId, { url: targetURL }, function() { chrome.tabs.update(tabId, { url: targetURL }, resetLastError);
// this prevent console error
if ( chrome.runtime.lastError ) {
return;
}
});
}; };
/******************************************************************************/ /******************************************************************************/
vAPI.tabs.remove = function(tabId) { vAPI.tabs.remove = function(tabId) {
var onTabRemoved = function() { chrome.tabs.remove(tabId, resetLastError);
if ( vAPI.lastError() ) {
}
};
chrome.tabs.remove(parseInt(tabId, 10), onTabRemoved);
}; };
/******************************************************************************/ /******************************************************************************/
vAPI.tabs.reload = function(tabId, bypassCache) { vAPI.tabs.reload = function(tabId, bypassCache) {
if ( typeof tabId === 'string' ) { if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
tabId = parseInt(tabId, 10);
}
if ( isNaN(tabId) ) {
return;
}
chrome.tabs.reload(tabId, { bypassCache: bypassCache === true }); chrome.tabs.reload(tabId, { bypassCache: bypassCache === true });
}; };
@ -357,15 +307,12 @@ vAPI.tabs.reload = function(tabId, bypassCache) {
vAPI.tabs.injectScript = function(tabId, details, callback) { vAPI.tabs.injectScript = function(tabId, details, callback) {
var onScriptExecuted = function() { var onScriptExecuted = function() {
// https://code.google.com/p/chromium/issues/detail?id=410868#c8 resetLastError();
if ( chrome.runtime.lastError ) {
}
if ( typeof callback === 'function' ) { if ( typeof callback === 'function' ) {
callback(); callback();
} }
}; };
if ( tabId ) { if ( tabId ) {
tabId = parseInt(tabId, 10);
chrome.tabs.executeScript(tabId, details, onScriptExecuted); chrome.tabs.executeScript(tabId, details, onScriptExecuted);
} else { } else {
chrome.tabs.executeScript(details, onScriptExecuted); chrome.tabs.executeScript(details, onScriptExecuted);
@ -399,8 +346,7 @@ vAPI.setIcon = (function() {
}; };
return function(tabId, iconDetails, badgeDetails) { return function(tabId, iconDetails, badgeDetails) {
tabId = parseInt(tabId, 10); if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
if ( isNaN(tabId) || tabId === -1 ) { return; }
chrome.browserAction.setIcon( chrome.browserAction.setIcon(
{ tabId: tabId, path: iconDetails }, { tabId: tabId, path: iconDetails },
function() { onIconReady(tabId, badgeDetails); } function() { onIconReady(tabId, badgeDetails); }
@ -572,7 +518,13 @@ vAPI.net.registerListeners = function() {
]); ]);
var normalizeRequestDetails = function(details) { var normalizeRequestDetails = function(details) {
details.tabId = details.tabId.toString(); if (
details.tabId === -1 &&
details.documentUrl === undefined &&
details.initiator !== undefined
) {
details.documentUrl = details.initiator;
}
// The rest of the function code is to normalize request type // The rest of the function code is to normalize request type
if ( details.type !== 'other' ) { return; } if ( details.type !== 'other' ) { return; }
@ -762,31 +714,32 @@ vAPI.cloud = (function() {
var maxChunkCountPerItem = Math.floor(512 * 0.75) & ~(chunkCountPerFetch - 1); var maxChunkCountPerItem = Math.floor(512 * 0.75) & ~(chunkCountPerFetch - 1);
// Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing) // Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing)
var maxChunkSize = chrome.storage.sync.QUOTA_BYTES_PER_ITEM || 8192;
// Mind chrome.storage.sync.QUOTA_BYTES (128 kB at time of writing)
// Firefox:
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/sync
// > You can store up to 100KB of data using this API/
var maxStorageSize = chrome.storage.sync.QUOTA_BYTES || 102400;
// Flavor-specific handling needs to be done here. Reason: to allow time
// for vAPI.webextFlavor to be properly set.
// https://github.com/gorhill/uBlock/issues/3006 // https://github.com/gorhill/uBlock/issues/3006
// For Firefox, we will use a lower ratio to allow for more overhead for // For Firefox, we will use a lower ratio to allow for more overhead for
// the infrastructure. Unfortunately this leads to less usable space for // the infrastructure. Unfortunately this leads to less usable space for
// actual data, but all of this is provided for free by browser vendors, // actual data, but all of this is provided for free by browser vendors,
// so we need to accept and deal with these limitations. // so we need to accept and deal with these limitations.
var initialize = function() { var evalMaxChunkSize = function() {
var ratio = return Math.floor(
vAPI.webextFlavor === undefined || (chrome.storage.sync.QUOTA_BYTES_PER_ITEM || 8192) *
vAPI.webextFlavor.startsWith('Mozilla-Firefox-') ? (vAPI.webextFlavor.soup.has('firefox') ? 0.6 : 0.75)
0.6 : );
0.75;
maxChunkSize = Math.floor(maxChunkSize * ratio);
initialize = function(){};
}; };
var maxChunkSize = evalMaxChunkSize();
// The real actual webextFlavor value may not be set in stone, so listen
// for possible future changes.
window.addEventListener('webextFlavor', function() {
maxChunkSize = evalMaxChunkSize();
}, { once: true });
// Mind chrome.storage.sync.QUOTA_BYTES (128 kB at time of writing)
// Firefox:
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/sync
// > You can store up to 100KB of data using this API/
var maxStorageSize = chrome.storage.sync.QUOTA_BYTES || 102400;
var options = { var options = {
defaultDeviceName: window.navigator.platform, defaultDeviceName: window.navigator.platform,
deviceName: vAPI.localStorage.getItem('deviceName') || '' deviceName: vAPI.localStorage.getItem('deviceName') || ''
@ -843,7 +796,6 @@ vAPI.cloud = (function() {
}; };
var push = function(dataKey, data, callback) { var push = function(dataKey, data, callback) {
initialize();
var bin = { var bin = {
'source': options.deviceName || options.defaultDeviceName, 'source': options.deviceName || options.defaultDeviceName,
@ -882,7 +834,6 @@ vAPI.cloud = (function() {
}; };
var pull = function(dataKey, callback) { var pull = function(dataKey, callback) {
initialize();
var assembleChunks = function(bin) { var assembleChunks = function(bin) {
if ( chrome.runtime.lastError ) { if ( chrome.runtime.lastError ) {

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a browser extension to block requests. uMatrix - a browser extension to block requests.
Copyright (C) 2014-2017 The uMatrix/uBlock Origin authors Copyright (C) 2014-2018 The uMatrix/uBlock Origin authors
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -47,7 +47,6 @@ vAPI.vapiClientInjected = true;
vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) + vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
Math.random().toString(36).slice(2); Math.random().toString(36).slice(2);
vAPI.chrome = true;
/******************************************************************************/ /******************************************************************************/

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a browser extension to block requests. uMatrix - a browser extension to block requests.
Copyright (C) 2014-2017 The uMatrix/uBlock Origin authors Copyright (C) 2014-2018 The uMatrix/uBlock Origin authors
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -40,6 +40,86 @@ var chrome = self.chrome;
/******************************************************************************/ /******************************************************************************/
vAPI.setTimeout = vAPI.setTimeout || window.setTimeout.bind(window);
/******************************************************************************/
vAPI.webextFlavor = {
major: 0,
soup: new Set()
};
(function() {
var ua = navigator.userAgent,
flavor = vAPI.webextFlavor,
soup = flavor.soup;
var dispatch = function() {
window.dispatchEvent(new CustomEvent('webextFlavor'));
};
// This is always true.
soup.add('ublock');
if ( /\bMobile\b/.test(ua) ) {
soup.add('mobile');
}
// Asynchronous
var async = self.browser instanceof Object &&
typeof self.browser.runtime.getBrowserInfo === 'function';
if ( async ) {
self.browser.runtime.getBrowserInfo().then(function(info) {
flavor.major = parseInt(info.version, 10) || 0;
soup.add(info.vendor.toLowerCase())
.add(info.name.toLowerCase());
if ( flavor.major >= 53 ) { soup.add('user_stylesheet'); }
if ( flavor.major >= 57 ) { soup.add('html_filtering'); }
dispatch();
});
}
// Synchronous
var match = /Firefox\/([\d.]+)/.exec(ua);
if ( match !== null ) {
flavor.major = parseInt(match[1], 10) || 0;
soup.add('mozilla')
.add('firefox');
if ( flavor.major >= 53 ) { soup.add('user_stylesheet'); }
if ( flavor.major >= 57 ) { soup.add('html_filtering'); }
} else {
match = /OPR\/([\d.]+)/.exec(ua);
if ( match !== null ) {
var reEx = /Chrom(?:e|ium)\/([\d.]+)/;
if ( reEx.test(ua) ) { match = reEx.exec(ua); }
flavor.major = parseInt(match[1], 10) || 0;
soup.add('opera').add('chromium');
} else {
match = /Chromium\/([\d.]+)/.exec(ua);
if ( match !== null ) {
flavor.major = parseInt(match[1], 10) || 0;
soup.add('chromium');
} else {
match = /Chrome\/([\d.]+)/.exec(ua);
if ( match !== null ) {
flavor.major = parseInt(match[1], 10) || 0;
soup.add('google').add('chromium');
}
}
}
// https://github.com/gorhill/uBlock/issues/3588
if ( soup.has('chromium') && flavor.major >= 67 ) {
soup.add('user_stylesheet');
}
}
// Don't starve potential listeners
if ( !async ) {
vAPI.setTimeout(dispatch, 97);
}
})();
/******************************************************************************/
// http://www.w3.org/International/questions/qa-scripts#directions // http://www.w3.org/International/questions/qa-scripts#directions
var setScriptDirection = function(language) { var setScriptDirection = function(language) {
@ -121,10 +201,6 @@ vAPI.localStorage = {
/******************************************************************************/ /******************************************************************************/
vAPI.setTimeout = vAPI.setTimeout || window.setTimeout.bind(window);
/******************************************************************************/
})(this); })(this);
/******************************************************************************/ /******************************************************************************/

@ -208,7 +208,8 @@ return {
clearBrowserCacheCycle: 0, clearBrowserCacheCycle: 0,
cspNoInlineScript: "script-src 'unsafe-eval' blob: *", cspNoInlineScript: "script-src 'unsafe-eval' blob: *",
cspNoInlineStyle: "style-src blob: *", cspNoInlineStyle: "style-src blob: *",
cspNoWorker: undefined, cspNoWorker: "worker-src 'none'; report-uri about:blank",
cantMergeCSPHeaders: false,
updateAssetsEvery: 11 * oneDay + 1 * oneHour + 1 * oneMinute + 1 * oneSecond, updateAssetsEvery: 11 * oneDay + 1 * oneHour + 1 * oneMinute + 1 * oneSecond,
firstUpdateAfter: 11 * oneMinute, firstUpdateAfter: 11 * oneMinute,
nextUpdateAfter: 11 * oneHour, nextUpdateAfter: 11 * oneHour,
@ -220,9 +221,9 @@ return {
// urls stats are kept on the back burner while waiting to be reactivated // urls stats are kept on the back burner while waiting to be reactivated
// in a tab or another. // in a tab or another.
pageStores: {}, pageStores: new Map(),
pageStoresToken: 0, pageStoresToken: 0,
pageStoreCemetery: {}, pageStoreCemetery: new Map(),
// page url => permission scope // page url => permission scope
tMatrix: null, tMatrix: null,

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2017-2018 Raymond Hill Copyright (C) 2017-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify

@ -509,10 +509,7 @@ vAPI.cookies.onChanged = (function() {
queue.delete(qentry[0]); queue.delete(qentry[0]);
} }
if ( cookieKeys.length !== 0 ) { if ( cookieKeys.length !== 0 ) {
let pageStores = µm.pageStores; for ( let pageStore of µm.pageStores.values() ) {
for ( let tabId in pageStores ) {
if ( pageStores.hasOwnProperty(tabId) === false ) { continue; }
let pageStore = pageStores[tabId];
let allHostnamesString = pageStore.allHostnamesString; let allHostnamesString = pageStore.allHostnamesString;
for ( let cookieKey of cookieKeys ) { for ( let cookieKey of cookieKeys ) {
if ( cookieMatchDomains(cookieKey, allHostnamesString) ) { if ( cookieMatchDomains(cookieKey, allHostnamesString) ) {

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a browser extension to benchmark browser session. uMatrix - a browser extension to benchmark browser session.
Copyright (C) 2015 Raymond Hill Copyright (C) 2015-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -36,8 +36,8 @@ var firstVarDataCol = 2; // currently, column 2 (0-based index)
var lastVarDataIndex = 3; // currently, d0-d3 var lastVarDataIndex = 3; // currently, d0-d3
var maxEntries = 0; var maxEntries = 0;
var noTabId = ''; var noTabId = '';
var allTabIds = {}; var pageStores = new Map();
var allTabIdsToken; var pageStoresToken;
var ownerId = Date.now(); var ownerId = Date.now();
var emphasizeTemplate = document.querySelector('#emphasizeTemplate > span'); var emphasizeTemplate = document.querySelector('#emphasizeTemplate > span');
@ -71,7 +71,7 @@ var classNameFromTabId = function(tabId) {
if ( tabId === noTabId ) { if ( tabId === noTabId ) {
return 'tab_bts'; return 'tab_bts';
} }
if ( tabId !== '' ) { if ( tabId > 0 ) {
return 'tab_' + tabId; return 'tab_' + tabId;
} }
return ''; return '';
@ -298,22 +298,17 @@ var logDate = new Date(),
var renderLogEntries = function(response) { var renderLogEntries = function(response) {
var entries = response.entries; var entries = response.entries;
if ( entries.length === 0 ) { if ( entries.length === 0 ) { return; }
return;
}
// Preserve scroll position // Preserve scroll position
var height = tbody.offsetHeight; var height = tbody.offsetHeight;
var tabIds = response.tabIds;
var n = entries.length; var n = entries.length;
var entry; var entry;
for ( var i = 0; i < n; i++ ) { for ( var i = 0; i < n; i++ ) {
entry = entries[i]; entry = entries[i];
// Unlikely, but it may happen // Unlikely, but it may happen
if ( entry.tab && tabIds.hasOwnProperty(entry.tab) === false ) { if ( entry.tab && pageStores.has(entry.tab) === false ) { continue; }
continue;
}
renderLogEntry(entries[i]); renderLogEntry(entries[i]);
} }
@ -346,18 +341,14 @@ var renderLogEntries = function(response) {
/******************************************************************************/ /******************************************************************************/
var synchronizeTabIds = function(newTabIds) { var synchronizeTabIds = function(newPageStores) {
var oldTabIds = allTabIds; var oldPageStores = pageStores;
var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows'); var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
var rowVoided = false; var rowVoided = false;
var trs; var trs;
for ( var tabId in oldTabIds ) { for ( let entry of oldPageStores ) {
if ( oldTabIds.hasOwnProperty(tabId) === false ) { let tabId = entry[0];
continue; if ( newPageStores.has(tabId) ) { continue; }
}
if ( newTabIds.hasOwnProperty(tabId) ) {
continue;
}
// Mark or remove voided rows // Mark or remove voided rows
trs = uDom('.tab_' + tabId); trs = uDom('.tab_' + tabId);
if ( autoDeleteVoidRows ) { if ( autoDeleteVoidRows ) {
@ -374,22 +365,20 @@ var synchronizeTabIds = function(newTabIds) {
var select = document.getElementById('pageSelector'); var select = document.getElementById('pageSelector');
var selectValue = select.value; var selectValue = select.value;
var tabIds = Object.keys(newTabIds).sort(function(a, b) { var tabIds = Array.from(newPageStores.keys()).sort(function(a, b) {
return newTabIds[a].localeCompare(newTabIds[b]); return newPageStores.get(a).localeCompare(newPageStores.get(b));
}); });
var option; var option;
for ( var i = 0, j = 2; i < tabIds.length; i++ ) { for ( var i = 0, j = 2; i < tabIds.length; i++ ) {
tabId = tabIds[i]; let tabId = tabIds[i];
if ( tabId === noTabId ) { if ( tabId === noTabId ) { continue; }
continue;
}
option = select.options[j]; option = select.options[j];
j += 1; j += 1;
if ( !option ) { if ( !option ) {
option = document.createElement('option'); option = document.createElement('option');
select.appendChild(option); select.appendChild(option);
} }
option.textContent = newTabIds[tabId]; option.textContent = newPageStores.get(tabId);
option.value = classNameFromTabId(tabId); option.value = classNameFromTabId(tabId);
if ( option.value === selectValue ) { if ( option.value === selectValue ) {
option.setAttribute('selected', ''); option.setAttribute('selected', '');
@ -407,7 +396,7 @@ var synchronizeTabIds = function(newTabIds) {
pageSelectorChanged(); pageSelectorChanged();
} }
allTabIds = newTabIds; pageStores = newPageStores;
return rowVoided; return rowVoided;
}; };
@ -446,9 +435,11 @@ var onLogBufferRead = function(response) {
// Neuter rows for which a tab does not exist anymore // Neuter rows for which a tab does not exist anymore
var rowVoided = false; var rowVoided = false;
if ( response.tabIdsToken !== allTabIdsToken ) { if ( response.pageStoresToken !== pageStoresToken ) {
rowVoided = synchronizeTabIds(response.tabIds); if ( Array.isArray(response.pageStores) ) {
allTabIdsToken = response.tabIdsToken; rowVoided = synchronizeTabIds(new Map(response.pageStores));
}
pageStoresToken = response.pageStoresToken;
} }
renderLogEntries(response); renderLogEntries(response);
@ -479,7 +470,11 @@ var readLogBuffer = function() {
if ( ownerId === undefined ) { return; } if ( ownerId === undefined ) { return; }
vAPI.messaging.send( vAPI.messaging.send(
'logger-ui.js', 'logger-ui.js',
{ what: 'readMany', ownerId: ownerId }, {
what: 'readMany',
ownerId: ownerId,
pageStoresToken: pageStoresToken
},
onLogBufferRead onLogBufferRead
); );
}; };
@ -515,15 +510,11 @@ var pageSelectorChanged = function() {
var refreshTab = function() { var refreshTab = function() {
var tabClass = document.getElementById('pageSelector').value; var tabClass = document.getElementById('pageSelector').value;
var matches = tabClass.match(/^tab_(.+)$/); var matches = tabClass.match(/^tab_(.+)$/);
if ( matches === null ) { if ( matches === null ) { return; }
return; if ( matches[1] === 'bts' ) { return; }
}
if ( matches[1] === 'bts' ) {
return;
}
vAPI.messaging.send( vAPI.messaging.send(
'logger-ui.js', 'logger-ui.js',
{ what: 'forceReloadTab', tabId: matches[1] } { what: 'forceReloadTab', tabId: parseInt(matches[1], 10) }
); );
}; };

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -938,20 +938,23 @@ var onMessage = function(request, sender, callback) {
response = { unavailable: true }; response = { unavailable: true };
break; break;
} }
var tabIds = {}; let pageStores;
for ( var tabId in µm.pageStores ) { if ( request.pageStoresToken !== µm.pageStoresToken ) {
var pageStore = µm.pageStoreFromTabId(tabId); pageStores = [];
if ( pageStore === null ) { continue; } for ( let entry of µm.pageStores ) {
if ( pageStore.rawUrl.startsWith(loggerURL) ) { continue; } let tabId = entry[0];
tabIds[tabId] = pageStore.title || pageStore.rawUrl; let pageStore = entry[1];
if ( pageStore.rawUrl.startsWith(loggerURL) ) { continue; }
pageStores.push([ tabId, pageStore.title || pageStore.rawUrl ]);
}
} }
response = { response = {
colorBlind: false, colorBlind: false,
entries: µm.logger.readAll(request.ownerId), entries: µm.logger.readAll(request.ownerId),
maxLoggedRequests: µm.userSettings.maxLoggedRequests, maxLoggedRequests: µm.userSettings.maxLoggedRequests,
noTabId: vAPI.noTabId, noTabId: vAPI.noTabId,
tabIds: tabIds, pageStores: pageStores,
tabIdsToken: µm.pageStoresToken pageStoresToken: µm.pageStoresToken
}; };
break; break;

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -1584,13 +1584,13 @@ var matrixSnapshotPoller = (function() {
}; };
(function() { (function() {
var tabId = matrixSnapshot.tabId; let tabId = matrixSnapshot.tabId;
// If no tab id yet, see if there is one specified in our URL // If no tab id yet, see if there is one specified in our URL
if ( tabId === undefined ) { if ( tabId === undefined ) {
var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/); var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/);
if ( matches !== null ) { if ( matches !== null ) {
tabId = matches[1]; tabId = parseInt(matches[1], 10);
// No need for logger button when embedded in logger // No need for logger button when embedded in logger
uDom('[data-extension-url="logger-ui.html"]').remove(); uDom('[data-extension-url="logger-ui.html"]').remove();
} }

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2017 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -89,8 +89,10 @@ var onPSLReady = function() {
// rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the // rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the
// normal way forbid binding behind the scene tab. // normal way forbid binding behind the scene tab.
// https://github.com/gorhill/httpswitchboard/issues/67 // https://github.com/gorhill/httpswitchboard/issues/67
µm.pageStores[vAPI.noTabId] = µm.pageStoreFactory(µm.tabContextManager.mustLookup(vAPI.noTabId)); let pageStore =
µm.pageStores[vAPI.noTabId].title = vAPI.i18n('statsPageDetailedBehindTheScenePage'); µm.pageStoreFactory(µm.tabContextManager.mustLookup(vAPI.noTabId));
pageStore.title = vAPI.i18n('statsPageDetailedBehindTheScenePage');
µm.pageStores.set(vAPI.noTabId, pageStore);
vAPI.tabs.getAll(onTabsReady); vAPI.tabs.getAll(onTabsReady);
}; };

@ -519,11 +519,32 @@
µMatrix.mergeHostsFileContent = function(rawText) { µMatrix.mergeHostsFileContent = function(rawText) {
var rawEnd = rawText.length; var rawEnd = rawText.length;
var ubiquitousBlacklist = this.ubiquitousBlacklist; var ubiquitousBlacklist = this.ubiquitousBlacklist;
var reLocalhost = /(^|\s)(localhost\.localdomain|localhost|local|broadcasthost|0\.0\.0\.0|127\.0\.0\.1|::1|fe80::1%lo0)(?=\s|$)/g; var reLocalhost = new RegExp(
[
'(?:^|\\s+)(?:',
[
'broadcasthost',
'ip6-allnodes',
'ip6-allrouters',
'ip6-localhost',
'ip6-loopback',
'localhost\\.localdomain',
'localhost',
'local',
'0\\.0\\.0\\.0',
'127\\.0\\.0\\.1',
'255\\.255\\.255\\.255',
'::1',
'ff02::1',
'ff02::2',
'fe80::1%lo0',
].join('|'),
')(?=\\s+|$)'
].join(''),
'g'
);
var reAsciiSegment = /^[\x21-\x7e]+$/; var reAsciiSegment = /^[\x21-\x7e]+$/;
var matches;
var lineBeg = 0, lineEnd; var lineBeg = 0, lineEnd;
var line;
while ( lineBeg < rawEnd ) { while ( lineBeg < rawEnd ) {
lineEnd = rawText.indexOf('\n', lineBeg); lineEnd = rawText.indexOf('\n', lineBeg);
@ -537,7 +558,7 @@
// rhill 2014-04-18: The trim is important here, as without it there // rhill 2014-04-18: The trim is important here, as without it there
// could be a lingering `\r` which would cause problems in the // could be a lingering `\r` which would cause problems in the
// following parsing code. // following parsing code.
line = rawText.slice(lineBeg, lineEnd).trim(); let line = rawText.slice(lineBeg, lineEnd).trim();
lineBeg = lineEnd + 1; lineBeg = lineEnd + 1;
// https://github.com/gorhill/httpswitchboard/issues/15 // https://github.com/gorhill/httpswitchboard/issues/15
@ -550,22 +571,15 @@
// The filter is whatever sequence of printable ascii character without // The filter is whatever sequence of printable ascii character without
// whitespaces // whitespaces
matches = reAsciiSegment.exec(line); let matches = reAsciiSegment.exec(line);
if ( !matches || matches.length === 0 ) { if ( matches === null ) { continue; }
continue;
}
// Bypass anomalies // Bypass anomalies
// For example, when a filter contains whitespace characters, or // For example, when a filter contains whitespace characters, or
// whatever else outside the range of printable ascii characters. // whatever else outside the range of printable ascii characters.
if ( matches[0] !== line ) { if ( matches[0] !== line ) { continue; }
continue;
}
line = matches[0]; line = matches[0];
if ( line === '' ) { if ( line === '' ) { continue; }
continue;
}
ubiquitousBlacklist.add(line); ubiquitousBlacklist.add(line);
} }

@ -1,6 +1,6 @@
/******************************************************************************* /*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests. uMatrix - a browser extension to black/white list requests.
Copyright (C) 2014-2018 Raymond Hill Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -140,7 +140,7 @@ housekeep itself.
*/ */
µm.tabContextManager = (function() { µm.tabContextManager = (function() {
var tabContexts = Object.create(null); var tabContexts = new Map();
// https://github.com/chrisaljoudi/uBlock/issues/1001 // https://github.com/chrisaljoudi/uBlock/issues/1001
// This is to be used as last-resort fallback in case a tab is found to not // This is to be used as last-resort fallback in case a tab is found to not
@ -170,18 +170,16 @@ housekeep itself.
this.commitTimer = null; this.commitTimer = null;
this.gcTimer = null; this.gcTimer = null;
tabContexts[tabId] = this; tabContexts.set(tabId, this);
}; };
TabContext.prototype.destroy = function() { TabContext.prototype.destroy = function() {
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
return;
}
if ( this.gcTimer !== null ) { if ( this.gcTimer !== null ) {
clearTimeout(this.gcTimer); clearTimeout(this.gcTimer);
this.gcTimer = null; this.gcTimer = null;
} }
delete tabContexts[this.tabId]; tabContexts.delete(this.tabId);
}; };
TabContext.prototype.onTab = function(tab) { TabContext.prototype.onTab = function(tab) {
@ -285,7 +283,7 @@ housekeep itself.
// These are to be used for the API of the tab context manager. // These are to be used for the API of the tab context manager.
var push = function(tabId, url, context) { var push = function(tabId, url, context) {
var entry = tabContexts[tabId]; let entry = tabContexts.get(tabId);
if ( entry === undefined ) { if ( entry === undefined ) {
entry = new TabContext(tabId); entry = new TabContext(tabId);
entry.autodestroy(); entry.autodestroy();
@ -303,7 +301,7 @@ housekeep itself.
if ( url !== undefined ) { if ( url !== undefined ) {
entry = push(tabId, url); entry = push(tabId, url);
} else { } else {
entry = tabContexts[tabId]; entry = tabContexts.get(tabId);
} }
if ( entry !== undefined ) { if ( entry !== undefined ) {
return entry; return entry;
@ -329,11 +327,11 @@ housekeep itself.
// about to fall through the cracks. // about to fall through the cracks.
// Example: Chromium + case #12 at // Example: Chromium + case #12 at
// http://raymondhill.net/ublock/popup.html // http://raymondhill.net/ublock/popup.html
return tabContexts[vAPI.noTabId]; return tabContexts.get(vAPI.noTabId);
}; };
var lookup = function(tabId) { var lookup = function(tabId) {
return tabContexts[tabId] || null; return tabContexts.get(tabId) || null;
}; };
// Behind-the-scene tab context // Behind-the-scene tab context
@ -372,7 +370,7 @@ housekeep itself.
vAPI.tabs.onClosed = function(tabId) { vAPI.tabs.onClosed = function(tabId) {
µm.unbindTabFromPageStats(tabId); µm.unbindTabFromPageStats(tabId);
var entry = tabContexts[tabId]; let entry = tabContexts.get(tabId);
if ( entry instanceof TabContext ) { if ( entry instanceof TabContext ) {
entry.destroy(); entry.destroy();
} }
@ -397,7 +395,7 @@ vAPI.tabs.registerListeners();
// Do not create a page store for URLs which are of no interests // Do not create a page store for URLs which are of no interests
// Example: dev console // Example: dev console
var tabContext = this.tabContextManager.lookup(tabId); let tabContext = this.tabContextManager.lookup(tabId);
if ( tabContext === null ) { if ( tabContext === null ) {
throw new Error('Unmanaged tab id: ' + tabId); throw new Error('Unmanaged tab id: ' + tabId);
} }
@ -406,14 +404,14 @@ vAPI.tabs.registerListeners();
// virtual tab. // virtual tab.
// https://github.com/gorhill/httpswitchboard/issues/67 // https://github.com/gorhill/httpswitchboard/issues/67
if ( vAPI.isBehindTheSceneTabId(tabId) ) { if ( vAPI.isBehindTheSceneTabId(tabId) ) {
return this.pageStores[tabId]; return this.pageStores.get(tabId);
} }
var normalURL = tabContext.normalURL; let normalURL = tabContext.normalURL;
var pageStore = this.pageStores[tabId] || null; let pageStore = this.pageStores.get(tabId);
// The previous page URL, if any, associated with the tab // The previous page URL, if any, associated with the tab
if ( pageStore !== null ) { if ( pageStore !== undefined ) {
// No change, do not rebind // No change, do not rebind
if ( pageStore.pageUrl === normalURL ) { if ( pageStore.pageUrl === normalURL ) {
return pageStore; return pageStore;
@ -425,7 +423,10 @@ vAPI.tabs.registerListeners();
// Example: Google Maps, Github // Example: Google Maps, Github
// https://github.com/gorhill/uMatrix/issues/72 // https://github.com/gorhill/uMatrix/issues/72
// Need to double-check that the new scope is same as old scope // Need to double-check that the new scope is same as old scope
if ( context === 'updateURL' && pageStore.pageHostname === tabContext.rootHostname ) { if (
context === 'updateURL' &&
pageStore.pageHostname === tabContext.rootHostname
) {
pageStore.rawURL = tabContext.rawURL; pageStore.rawURL = tabContext.rawURL;
pageStore.normalURL = normalURL; pageStore.normalURL = normalURL;
this.updateTitle(tabId); this.updateTitle(tabId);
@ -442,29 +443,22 @@ vAPI.tabs.registerListeners();
if ( pageStore === null ) { if ( pageStore === null ) {
pageStore = this.pageStoreFactory(tabContext); pageStore = this.pageStoreFactory(tabContext);
} }
this.pageStores[tabId] = pageStore; this.pageStores.set(tabId, pageStore);
this.updateTitle(tabId); this.updateTitle(tabId);
this.pageStoresToken = Date.now(); this.pageStoresToken = Date.now();
// console.debug('tab.js > bindTabToPageStats(): dispatching traffic in tab id %d to page store "%s"', tabId, pageUrl);
return pageStore; return pageStore;
}; };
/******************************************************************************/ /******************************************************************************/
µm.unbindTabFromPageStats = function(tabId) { µm.unbindTabFromPageStats = function(tabId) {
// Never unbind behind-the-scene page store. if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
return;
}
var pageStore = this.pageStores[tabId] || null; let pageStore = this.pageStores.get(tabId);
if ( pageStore === null ) { if ( pageStore === undefined ) { return; }
return;
}
delete this.pageStores[tabId]; this.pageStores.delete(tabId);
this.pageStoresToken = Date.now(); this.pageStoresToken = Date.now();
if ( pageStore.incinerationTimer ) { if ( pageStore.incinerationTimer ) {
@ -472,13 +466,13 @@ vAPI.tabs.registerListeners();
pageStore.incinerationTimer = null; pageStore.incinerationTimer = null;
} }
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) { let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
this.pageStoreCemetery[tabId] = {}; if ( pageStoreCrypt === undefined ) {
this.pageStoreCemetery.set(tabId, (pageStoreCrypt = new Map()));
} }
var pageStoreCrypt = this.pageStoreCemetery[tabId];
var pageURL = pageStore.pageUrl; let pageURL = pageStore.pageUrl;
pageStoreCrypt[pageURL] = pageStore; pageStoreCrypt.set(pageURL, pageStore);
pageStore.incinerationTimer = vAPI.setTimeout( pageStore.incinerationTimer = vAPI.setTimeout(
this.incineratePageStore.bind(this, tabId, pageURL), this.incineratePageStore.bind(this, tabId, pageURL),
@ -489,25 +483,21 @@ vAPI.tabs.registerListeners();
/******************************************************************************/ /******************************************************************************/
µm.resurrectPageStore = function(tabId, pageURL) { µm.resurrectPageStore = function(tabId, pageURL) {
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) { let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
return null; if ( pageStoreCrypt === undefined ) { return null; }
}
var pageStoreCrypt = this.pageStoreCemetery[tabId];
if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) { let pageStore = pageStoreCrypt.get(pageURL);
return null; if ( pageStore === undefined ) { return null; }
}
var pageStore = pageStoreCrypt[pageURL];
if ( pageStore.incinerationTimer !== null ) { if ( pageStore.incinerationTimer !== null ) {
clearTimeout(pageStore.incinerationTimer); clearTimeout(pageStore.incinerationTimer);
pageStore.incinerationTimer = null; pageStore.incinerationTimer = null;
} }
delete pageStoreCrypt[pageURL]; pageStoreCrypt.delete(pageURL);
if ( Object.keys(pageStoreCrypt).length === 0 ) { if ( pageStoreCrypt.size === 0 ) {
delete this.pageStoreCemetery[tabId]; this.pageStoreCemetery.delete(tabId);
} }
return pageStore; return pageStore;
@ -516,24 +506,20 @@ vAPI.tabs.registerListeners();
/******************************************************************************/ /******************************************************************************/
µm.incineratePageStore = function(tabId, pageURL) { µm.incineratePageStore = function(tabId, pageURL) {
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) { let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
return; if ( pageStoreCrypt === undefined ) { return; }
}
var pageStoreCrypt = this.pageStoreCemetery[tabId];
if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) { let pageStore = pageStoreCrypt.get(pageURL);
return; if ( pageStore === undefined ) { return; }
}
var pageStore = pageStoreCrypt[pageURL];
if ( pageStore.incinerationTimer !== null ) { if ( pageStore.incinerationTimer !== null ) {
clearTimeout(pageStore.incinerationTimer); clearTimeout(pageStore.incinerationTimer);
pageStore.incinerationTimer = null; pageStore.incinerationTimer = null;
} }
delete pageStoreCrypt[pageURL]; pageStoreCrypt.delete(pageURL);
if ( Object.keys(pageStoreCrypt).length === 0 ) { if ( pageStoreCrypt.size === 0 ) {
delete this.pageStoreCemetery[tabId]; this.pageStoreCemetery.delete(tabId);
} }
pageStore.dispose(); pageStore.dispose();
@ -542,12 +528,12 @@ vAPI.tabs.registerListeners();
/******************************************************************************/ /******************************************************************************/
µm.pageStoreFromTabId = function(tabId) { µm.pageStoreFromTabId = function(tabId) {
return this.pageStores[tabId] || null; return this.pageStores.get(tabId) || null;
}; };
// Never return null // Never return null
µm.mustPageStoreFromTabId = function(tabId) { µm.mustPageStoreFromTabId = function(tabId) {
return this.pageStores[tabId] || this.pageStores[vAPI.noTabId]; return this.pageStores.get(tabId) || this.pageStores.get(vAPI.noTabId);
}; };
/******************************************************************************/ /******************************************************************************/
@ -608,25 +594,26 @@ vAPI.tabs.registerListeners();
/******************************************************************************/ /******************************************************************************/
µm.updateTitle = (function() { µm.updateTitle = (function() {
var tabIdToTimer = Object.create(null); let tabIdToTimer = new Map();
var tabIdToTryCount = Object.create(null); let tabIdToTryCount = new Map();
var delay = 499; let delay = 499;
var tryNoMore = function(tabId) { let tryNoMore = function(tabId) {
delete tabIdToTryCount[tabId]; tabIdToTryCount.delete(tabId);
}; };
var tryAgain = function(tabId) { let tryAgain = function(tabId) {
var count = tabIdToTryCount[tabId]; let count = tabIdToTryCount.get(tabId);
if ( count === undefined ) { if ( count === undefined ) { return false; }
return false;
}
if ( count === 1 ) { if ( count === 1 ) {
delete tabIdToTryCount[tabId]; tabIdToTryCount.delete(tabId);
return false; return false;
} }
tabIdToTryCount[tabId] = count - 1; tabIdToTryCount.set(tabId, count - 1);
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(µm, tabId), delay); tabIdToTimer.set(
tabId,
vAPI.setTimeout(updateTitle.bind(µm, tabId), delay)
);
return true; return true;
}; };
@ -652,19 +639,21 @@ vAPI.tabs.registerListeners();
}; };
var updateTitle = function(tabId) { var updateTitle = function(tabId) {
delete tabIdToTimer[tabId]; tabIdToTimer.delete(tabId);
vAPI.tabs.get(tabId, onTabReady.bind(this, tabId)); vAPI.tabs.get(tabId, onTabReady.bind(this, tabId));
}; };
return function(tabId) { return function(tabId) {
if ( vAPI.isBehindTheSceneTabId(tabId) ) { if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
return; let timer = tabIdToTimer.get(tabId);
} if ( timer !== undefined ) {
if ( tabIdToTimer[tabId] ) { clearTimeout(timer);
clearTimeout(tabIdToTimer[tabId]);
} }
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(this, tabId), delay); tabIdToTimer.set(
tabIdToTryCount[tabId] = 5; tabId,
vAPI.setTimeout(updateTitle.bind(this, tabId), delay)
);
tabIdToTryCount.set(tabId, 5);
}; };
})(); })();
@ -680,7 +669,7 @@ vAPI.tabs.registerListeners();
var cleanup = function() { var cleanup = function() {
var vapiTabs = vAPI.tabs; var vapiTabs = vAPI.tabs;
var tabIds = Object.keys(µm.pageStores).sort(); var tabIds = Array.from(µm.pageStores.keys()).sort();
var checkTab = function(tabId) { var checkTab = function(tabId) {
vapiTabs.get(tabId, function(tab) { vapiTabs.get(tabId, function(tab) {
if ( !tab ) { if ( !tab ) {
@ -695,9 +684,7 @@ vAPI.tabs.registerListeners();
var n = Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length); var n = Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length);
for ( var i = cleanupSampleAt; i < n; i++ ) { for ( var i = cleanupSampleAt; i < n; i++ ) {
tabId = tabIds[i]; tabId = tabIds[i];
if ( vAPI.isBehindTheSceneTabId(tabId) ) { if ( vAPI.isBehindTheSceneTabId(tabId) ) { continue; }
continue;
}
checkTab(tabId); checkTab(tabId);
} }
cleanupSampleAt = n; cleanupSampleAt = n;

@ -127,6 +127,12 @@ var onBeforeRequestHandler = function(details) {
rootHostname = tabContext.rootHostname, rootHostname = tabContext.rootHostname,
specificity = 0; specificity = 0;
if ( tabId < 0 && details.documentUrl !== undefined ) {
rootHostname = µmuri.hostnameFromURI(
µm.normalizePageURL(0, details.documentUrl)
);
}
// Filter through matrix // Filter through matrix
var block = µm.tMatrix.mustBlock( var block = µm.tMatrix.mustBlock(
rootHostname, rootHostname,
@ -344,16 +350,10 @@ var onHeadersReceived = function(details) {
csp.push(µm.cspNoInlineStyle); csp.push(µm.cspNoInlineStyle);
} }
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302667
var cspNoWorker = µm.cspNoWorker;
if ( cspNoWorker === undefined ) {
cspNoWorker = cspNoWorkerInit();
}
if ( µm.tMatrix.evaluateSwitchZ('no-workers', rootHostname) ) { if ( µm.tMatrix.evaluateSwitchZ('no-workers', rootHostname) ) {
csp.push(cspNoWorker); csp.push(µm.cspNoWorker);
} else if ( µm.rawSettings.disableCSPReportInjection === false ) { } else if ( µm.rawSettings.disableCSPReportInjection === false ) {
cspReport.push(cspNoWorker); cspReport.push(µm.cspNoWorker);
} }
if ( csp.length === 0 && cspReport.length === 0 ) { return; } if ( csp.length === 0 && cspReport.length === 0 ) { return; }
@ -368,7 +368,7 @@ var onHeadersReceived = function(details) {
if ( csp.length !== 0 ) { if ( csp.length !== 0 ) {
let cspRight = csp.join(', '); let cspRight = csp.join(', ');
let cspTotal = cspRight; let cspTotal = cspRight;
if ( cantMergeCSPHeaders ) { if ( µm.cantMergeCSPHeaders ) {
let i = headerIndexFromName( let i = headerIndexFromName(
'content-security-policy', 'content-security-policy',
headers headers
@ -390,7 +390,7 @@ var onHeadersReceived = function(details) {
if ( cspReport.length !== 0 ) { if ( cspReport.length !== 0 ) {
let cspRight = cspReport.join(', '); let cspRight = cspReport.join(', ');
let cspTotal = cspRight; let cspTotal = cspRight;
if ( cantMergeCSPHeaders ) { if ( µm.cantMergeCSPHeaders ) {
let i = headerIndexFromName( let i = headerIndexFromName(
'content-security-policy-report-only', 'content-security-policy-report-only',
headers headers
@ -411,34 +411,19 @@ var onHeadersReceived = function(details) {
/******************************************************************************/ /******************************************************************************/
// https://bugzilla.mozilla.org/show_bug.cgi?id=1302667
// https://github.com/gorhill/uMatrix/issues/967#issuecomment-373002011 // https://github.com/gorhill/uMatrix/issues/967#issuecomment-373002011
// This can be removed once Firefox 60 ESR is released.
var cantMergeCSPHeaders = (function() {
if (
self.browser instanceof Object &&
typeof self.browser.runtime.getBrowserInfo === 'function'
) {
self.browser.runtime.getBrowserInfo().then(function(info) {
cantMergeCSPHeaders =
info.vendor === 'Mozilla' &&
info.name === 'Firefox' &&
parseInt(info.version, 10) < 59;
});
}
return false;
})();
/******************************************************************************/
var cspNoWorkerInit = function() { window.addEventListener('webextFlavor', function() {
if ( vAPI.webextFlavor === undefined ) { if ( vAPI.webextFlavor.soup.has('firefox') === false ) { return; }
return "child-src 'none'; frame-src data: blob: *; report-uri about:blank"; if ( vAPI.webextFlavor.major <= 57 ) {
µMatrix.cspNoWorker =
"child-src 'none'; frame-src data: blob: *; report-uri about:blank";
} }
µMatrix.cspNoWorker = /^Mozilla-Firefox-5[67]/.test(vAPI.webextFlavor) ? if ( vAPI.webextFlavor.major <= 58 ) {
"child-src 'none'; frame-src data: blob: *; report-uri about:blank" : µMatrix.cantMergeCSPHeaders = true;
"worker-src 'none'; report-uri about:blank" ; }
return µMatrix.cspNoWorker; }, { once: true });
};
/******************************************************************************/ /******************************************************************************/

Loading…
Cancel
Save