mirror of
https://github.com/gorhill/uMatrix.git
synced 2024-05-14 09:13:20 +12:00
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()
This commit is contained in:
parent
dd5a3a807c
commit
31cc15ca6c
13
.jshintrc
13
.jshintrc
|
@ -3,14 +3,15 @@
|
|||
"devel": true,
|
||||
"eqeqeq": true,
|
||||
"esnext": true,
|
||||
"strict": "global",
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"globals": {
|
||||
"browser": false, // global variable in Firefox, Edge
|
||||
"self": false,
|
||||
"chrome": false,
|
||||
"vAPI": false,
|
||||
"µMatrix": false,
|
||||
"Components": false // global variable in Firefox
|
||||
}
|
||||
"µMatrix": false
|
||||
},
|
||||
"strict": "global",
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"validthis": true
|
||||
}
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
Home: https://github.com/gorhill/uMatrix
|
||||
*/
|
||||
|
||||
/* global self, µMatrix */
|
||||
|
||||
// For background page
|
||||
|
||||
'use strict';
|
||||
|
@ -37,22 +35,13 @@ var vAPI = self.vAPI = self.vAPI || {};
|
|||
var chrome = self.chrome;
|
||||
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(){};
|
||||
|
||||
// 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
|
||||
|
@ -96,10 +85,13 @@ vAPI.tabs = {};
|
|||
/******************************************************************************/
|
||||
|
||||
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) {
|
||||
//console.debug('onCreatedNavigationTarget: tab id %d = "%s"', details.tabId, details.url);
|
||||
if ( reGoodForWebRequestAPI.test(details.url) ) { return; }
|
||||
details.tabId = details.tabId.toString();
|
||||
onNavigationClient(details);
|
||||
};
|
||||
|
||||
var onUpdated = function(tabId, changeInfo, tab) {
|
||||
tabId = tabId.toString();
|
||||
onUpdatedClient(tabId, changeInfo, tab);
|
||||
};
|
||||
|
||||
|
@ -140,13 +130,12 @@ vAPI.tabs.registerListeners = function() {
|
|||
if ( details.frameId !== 0 ) {
|
||||
return;
|
||||
}
|
||||
details.tabId = details.tabId.toString();
|
||||
onNavigationClient(details);
|
||||
//console.debug('onCommitted: tab id %d = "%s"', details.tabId, details.url);
|
||||
};
|
||||
|
||||
var onClosed = function(tabId) {
|
||||
onClosedClient(tabId.toString());
|
||||
onClosedClient(tabId);
|
||||
};
|
||||
|
||||
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
|
||||
|
@ -161,29 +150,18 @@ vAPI.tabs.registerListeners = function() {
|
|||
|
||||
vAPI.tabs.get = function(tabId, callback) {
|
||||
var onTabReady = function(tab) {
|
||||
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||
if ( chrome.runtime.lastError ) {
|
||||
}
|
||||
if ( tab instanceof Object ) {
|
||||
tab.id = tab.id.toString();
|
||||
}
|
||||
resetLastError();
|
||||
callback(tab);
|
||||
};
|
||||
if ( tabId !== null ) {
|
||||
if ( typeof tabId === 'string' ) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
}
|
||||
chrome.tabs.get(tabId, onTabReady);
|
||||
return;
|
||||
}
|
||||
var onTabReceived = function(tabs) {
|
||||
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||
if ( chrome.runtime.lastError ) {
|
||||
}
|
||||
resetLastError();
|
||||
var tab = null;
|
||||
if ( Array.isArray(tabs) && tabs.length !== 0 ) {
|
||||
tab = tabs[0];
|
||||
tab.id = tab.id.toString();
|
||||
}
|
||||
callback(tab);
|
||||
};
|
||||
|
@ -193,16 +171,7 @@ vAPI.tabs.get = function(tabId, callback) {
|
|||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.getAll = function(callback) {
|
||||
var onTabsReady = function(tabs) {
|
||||
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);
|
||||
chrome.tabs.query({ url: '<all_urls>' }, callback);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -254,7 +223,7 @@ vAPI.tabs.open = function(details) {
|
|||
}
|
||||
|
||||
// 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 ( vAPI.lastError() ) {
|
||||
chrome.tabs.create(_details, focusWindow);
|
||||
|
@ -292,7 +261,7 @@ vAPI.tabs.open = function(details) {
|
|||
}
|
||||
|
||||
chrome.tabs.query({ url: targetURL }, function(tabs) {
|
||||
if ( chrome.runtime.lastError ) { /* noop */ }
|
||||
resetLastError();
|
||||
var tab = Array.isArray(tabs) && tabs[0];
|
||||
if ( tab ) {
|
||||
chrome.tabs.update(tab.id, { active: true }, function(tab) {
|
||||
|
@ -316,40 +285,21 @@ vAPI.tabs.replace = function(tabId, url) {
|
|||
targetURL = vAPI.getURL(targetURL);
|
||||
}
|
||||
|
||||
if ( typeof tabId !== 'number' ) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
if ( isNaN(tabId) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
|
||||
|
||||
chrome.tabs.update(tabId, { url: targetURL }, function() {
|
||||
// this prevent console error
|
||||
if ( chrome.runtime.lastError ) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
chrome.tabs.update(tabId, { url: targetURL }, resetLastError);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.remove = function(tabId) {
|
||||
var onTabRemoved = function() {
|
||||
if ( vAPI.lastError() ) {
|
||||
}
|
||||
};
|
||||
chrome.tabs.remove(parseInt(tabId, 10), onTabRemoved);
|
||||
chrome.tabs.remove(tabId, resetLastError);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.reload = function(tabId, bypassCache) {
|
||||
if ( typeof tabId === 'string' ) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
}
|
||||
if ( isNaN(tabId) ) {
|
||||
return;
|
||||
}
|
||||
if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
|
||||
chrome.tabs.reload(tabId, { bypassCache: bypassCache === true });
|
||||
};
|
||||
|
||||
|
@ -357,15 +307,12 @@ vAPI.tabs.reload = function(tabId, bypassCache) {
|
|||
|
||||
vAPI.tabs.injectScript = function(tabId, details, callback) {
|
||||
var onScriptExecuted = function() {
|
||||
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||
if ( chrome.runtime.lastError ) {
|
||||
}
|
||||
resetLastError();
|
||||
if ( typeof callback === 'function' ) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
if ( tabId ) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
chrome.tabs.executeScript(tabId, details, onScriptExecuted);
|
||||
} else {
|
||||
chrome.tabs.executeScript(details, onScriptExecuted);
|
||||
|
@ -399,8 +346,7 @@ vAPI.setIcon = (function() {
|
|||
};
|
||||
|
||||
return function(tabId, iconDetails, badgeDetails) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
if ( isNaN(tabId) || tabId === -1 ) { return; }
|
||||
if ( typeof tabId !== 'number' || tabId < 0 ) { return; }
|
||||
chrome.browserAction.setIcon(
|
||||
{ tabId: tabId, path: iconDetails },
|
||||
function() { onIconReady(tabId, badgeDetails); }
|
||||
|
@ -572,7 +518,13 @@ vAPI.net.registerListeners = function() {
|
|||
]);
|
||||
|
||||
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
|
||||
if ( details.type !== 'other' ) { return; }
|
||||
|
@ -762,7 +714,25 @@ vAPI.cloud = (function() {
|
|||
var maxChunkCountPerItem = Math.floor(512 * 0.75) & ~(chunkCountPerFetch - 1);
|
||||
|
||||
// Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing)
|
||||
var maxChunkSize = chrome.storage.sync.QUOTA_BYTES_PER_ITEM || 8192;
|
||||
// https://github.com/gorhill/uBlock/issues/3006
|
||||
// For Firefox, we will use a lower ratio to allow for more overhead for
|
||||
// the infrastructure. Unfortunately this leads to less usable space for
|
||||
// actual data, but all of this is provided for free by browser vendors,
|
||||
// so we need to accept and deal with these limitations.
|
||||
var evalMaxChunkSize = function() {
|
||||
return Math.floor(
|
||||
(chrome.storage.sync.QUOTA_BYTES_PER_ITEM || 8192) *
|
||||
(vAPI.webextFlavor.soup.has('firefox') ? 0.6 : 0.75)
|
||||
);
|
||||
};
|
||||
|
||||
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:
|
||||
|
@ -770,23 +740,6 @@ vAPI.cloud = (function() {
|
|||
// > 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
|
||||
// For Firefox, we will use a lower ratio to allow for more overhead for
|
||||
// the infrastructure. Unfortunately this leads to less usable space for
|
||||
// actual data, but all of this is provided for free by browser vendors,
|
||||
// so we need to accept and deal with these limitations.
|
||||
var initialize = function() {
|
||||
var ratio =
|
||||
vAPI.webextFlavor === undefined ||
|
||||
vAPI.webextFlavor.startsWith('Mozilla-Firefox-') ?
|
||||
0.6 :
|
||||
0.75;
|
||||
maxChunkSize = Math.floor(maxChunkSize * ratio);
|
||||
initialize = function(){};
|
||||
};
|
||||
|
||||
var options = {
|
||||
defaultDeviceName: window.navigator.platform,
|
||||
deviceName: vAPI.localStorage.getItem('deviceName') || ''
|
||||
|
@ -843,7 +796,6 @@ vAPI.cloud = (function() {
|
|||
};
|
||||
|
||||
var push = function(dataKey, data, callback) {
|
||||
initialize();
|
||||
|
||||
var bin = {
|
||||
'source': options.deviceName || options.defaultDeviceName,
|
||||
|
@ -882,7 +834,6 @@ vAPI.cloud = (function() {
|
|||
};
|
||||
|
||||
var pull = function(dataKey, callback) {
|
||||
initialize();
|
||||
|
||||
var assembleChunks = function(bin) {
|
||||
if ( chrome.runtime.lastError ) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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) +
|
||||
Math.random().toString(36).slice(2);
|
||||
vAPI.chrome = true;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
var setScriptDirection = function(language) {
|
||||
|
@ -121,10 +201,6 @@ vAPI.localStorage = {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.setTimeout = vAPI.setTimeout || window.setTimeout.bind(window);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})(this);
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -208,7 +208,8 @@ return {
|
|||
clearBrowserCacheCycle: 0,
|
||||
cspNoInlineScript: "script-src 'unsafe-eval' 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,
|
||||
firstUpdateAfter: 11 * oneMinute,
|
||||
nextUpdateAfter: 11 * oneHour,
|
||||
|
@ -220,9 +221,9 @@ return {
|
|||
|
||||
// urls stats are kept on the back burner while waiting to be reactivated
|
||||
// in a tab or another.
|
||||
pageStores: {},
|
||||
pageStores: new Map(),
|
||||
pageStoresToken: 0,
|
||||
pageStoreCemetery: {},
|
||||
pageStoreCemetery: new Map(),
|
||||
|
||||
// page url => permission scope
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -509,10 +509,7 @@ vAPI.cookies.onChanged = (function() {
|
|||
queue.delete(qentry[0]);
|
||||
}
|
||||
if ( cookieKeys.length !== 0 ) {
|
||||
let pageStores = µm.pageStores;
|
||||
for ( let tabId in pageStores ) {
|
||||
if ( pageStores.hasOwnProperty(tabId) === false ) { continue; }
|
||||
let pageStore = pageStores[tabId];
|
||||
for ( let pageStore of µm.pageStores.values() ) {
|
||||
let allHostnamesString = pageStore.allHostnamesString;
|
||||
for ( let cookieKey of cookieKeys ) {
|
||||
if ( cookieMatchDomains(cookieKey, allHostnamesString) ) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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 maxEntries = 0;
|
||||
var noTabId = '';
|
||||
var allTabIds = {};
|
||||
var allTabIdsToken;
|
||||
var pageStores = new Map();
|
||||
var pageStoresToken;
|
||||
var ownerId = Date.now();
|
||||
|
||||
var emphasizeTemplate = document.querySelector('#emphasizeTemplate > span');
|
||||
|
@ -71,7 +71,7 @@ var classNameFromTabId = function(tabId) {
|
|||
if ( tabId === noTabId ) {
|
||||
return 'tab_bts';
|
||||
}
|
||||
if ( tabId !== '' ) {
|
||||
if ( tabId > 0 ) {
|
||||
return 'tab_' + tabId;
|
||||
}
|
||||
return '';
|
||||
|
@ -298,22 +298,17 @@ var logDate = new Date(),
|
|||
|
||||
var renderLogEntries = function(response) {
|
||||
var entries = response.entries;
|
||||
if ( entries.length === 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( entries.length === 0 ) { return; }
|
||||
|
||||
// Preserve scroll position
|
||||
var height = tbody.offsetHeight;
|
||||
|
||||
var tabIds = response.tabIds;
|
||||
var n = entries.length;
|
||||
var entry;
|
||||
for ( var i = 0; i < n; i++ ) {
|
||||
entry = entries[i];
|
||||
// Unlikely, but it may happen
|
||||
if ( entry.tab && tabIds.hasOwnProperty(entry.tab) === false ) {
|
||||
continue;
|
||||
}
|
||||
if ( entry.tab && pageStores.has(entry.tab) === false ) { continue; }
|
||||
renderLogEntry(entries[i]);
|
||||
}
|
||||
|
||||
|
@ -346,18 +341,14 @@ var renderLogEntries = function(response) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var synchronizeTabIds = function(newTabIds) {
|
||||
var oldTabIds = allTabIds;
|
||||
var synchronizeTabIds = function(newPageStores) {
|
||||
var oldPageStores = pageStores;
|
||||
var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows');
|
||||
var rowVoided = false;
|
||||
var trs;
|
||||
for ( var tabId in oldTabIds ) {
|
||||
if ( oldTabIds.hasOwnProperty(tabId) === false ) {
|
||||
continue;
|
||||
}
|
||||
if ( newTabIds.hasOwnProperty(tabId) ) {
|
||||
continue;
|
||||
}
|
||||
for ( let entry of oldPageStores ) {
|
||||
let tabId = entry[0];
|
||||
if ( newPageStores.has(tabId) ) { continue; }
|
||||
// Mark or remove voided rows
|
||||
trs = uDom('.tab_' + tabId);
|
||||
if ( autoDeleteVoidRows ) {
|
||||
|
@ -374,22 +365,20 @@ var synchronizeTabIds = function(newTabIds) {
|
|||
|
||||
var select = document.getElementById('pageSelector');
|
||||
var selectValue = select.value;
|
||||
var tabIds = Object.keys(newTabIds).sort(function(a, b) {
|
||||
return newTabIds[a].localeCompare(newTabIds[b]);
|
||||
var tabIds = Array.from(newPageStores.keys()).sort(function(a, b) {
|
||||
return newPageStores.get(a).localeCompare(newPageStores.get(b));
|
||||
});
|
||||
var option;
|
||||
for ( var i = 0, j = 2; i < tabIds.length; i++ ) {
|
||||
tabId = tabIds[i];
|
||||
if ( tabId === noTabId ) {
|
||||
continue;
|
||||
}
|
||||
let tabId = tabIds[i];
|
||||
if ( tabId === noTabId ) { continue; }
|
||||
option = select.options[j];
|
||||
j += 1;
|
||||
if ( !option ) {
|
||||
option = document.createElement('option');
|
||||
select.appendChild(option);
|
||||
}
|
||||
option.textContent = newTabIds[tabId];
|
||||
option.textContent = newPageStores.get(tabId);
|
||||
option.value = classNameFromTabId(tabId);
|
||||
if ( option.value === selectValue ) {
|
||||
option.setAttribute('selected', '');
|
||||
|
@ -407,7 +396,7 @@ var synchronizeTabIds = function(newTabIds) {
|
|||
pageSelectorChanged();
|
||||
}
|
||||
|
||||
allTabIds = newTabIds;
|
||||
pageStores = newPageStores;
|
||||
|
||||
return rowVoided;
|
||||
};
|
||||
|
@ -446,9 +435,11 @@ var onLogBufferRead = function(response) {
|
|||
|
||||
// Neuter rows for which a tab does not exist anymore
|
||||
var rowVoided = false;
|
||||
if ( response.tabIdsToken !== allTabIdsToken ) {
|
||||
rowVoided = synchronizeTabIds(response.tabIds);
|
||||
allTabIdsToken = response.tabIdsToken;
|
||||
if ( response.pageStoresToken !== pageStoresToken ) {
|
||||
if ( Array.isArray(response.pageStores) ) {
|
||||
rowVoided = synchronizeTabIds(new Map(response.pageStores));
|
||||
}
|
||||
pageStoresToken = response.pageStoresToken;
|
||||
}
|
||||
|
||||
renderLogEntries(response);
|
||||
|
@ -479,7 +470,11 @@ var readLogBuffer = function() {
|
|||
if ( ownerId === undefined ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'logger-ui.js',
|
||||
{ what: 'readMany', ownerId: ownerId },
|
||||
{
|
||||
what: 'readMany',
|
||||
ownerId: ownerId,
|
||||
pageStoresToken: pageStoresToken
|
||||
},
|
||||
onLogBufferRead
|
||||
);
|
||||
};
|
||||
|
@ -515,15 +510,11 @@ var pageSelectorChanged = function() {
|
|||
var refreshTab = function() {
|
||||
var tabClass = document.getElementById('pageSelector').value;
|
||||
var matches = tabClass.match(/^tab_(.+)$/);
|
||||
if ( matches === null ) {
|
||||
return;
|
||||
}
|
||||
if ( matches[1] === 'bts' ) {
|
||||
return;
|
||||
}
|
||||
if ( matches === null ) { return; }
|
||||
if ( matches[1] === 'bts' ) { return; }
|
||||
vAPI.messaging.send(
|
||||
'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
|
||||
|
||||
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 };
|
||||
break;
|
||||
}
|
||||
var tabIds = {};
|
||||
for ( var tabId in µm.pageStores ) {
|
||||
var pageStore = µm.pageStoreFromTabId(tabId);
|
||||
if ( pageStore === null ) { continue; }
|
||||
if ( pageStore.rawUrl.startsWith(loggerURL) ) { continue; }
|
||||
tabIds[tabId] = pageStore.title || pageStore.rawUrl;
|
||||
let pageStores;
|
||||
if ( request.pageStoresToken !== µm.pageStoresToken ) {
|
||||
pageStores = [];
|
||||
for ( let entry of µm.pageStores ) {
|
||||
let tabId = entry[0];
|
||||
let pageStore = entry[1];
|
||||
if ( pageStore.rawUrl.startsWith(loggerURL) ) { continue; }
|
||||
pageStores.push([ tabId, pageStore.title || pageStore.rawUrl ]);
|
||||
}
|
||||
}
|
||||
response = {
|
||||
colorBlind: false,
|
||||
entries: µm.logger.readAll(request.ownerId),
|
||||
maxLoggedRequests: µm.userSettings.maxLoggedRequests,
|
||||
noTabId: vAPI.noTabId,
|
||||
tabIds: tabIds,
|
||||
tabIdsToken: µm.pageStoresToken
|
||||
pageStores: pageStores,
|
||||
pageStoresToken: µm.pageStoresToken
|
||||
};
|
||||
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
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -1584,13 +1584,13 @@ var matrixSnapshotPoller = (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 ( tabId === undefined ) {
|
||||
var matches = window.location.search.match(/(?:\?|&)tabId=([^&]+)/);
|
||||
if ( matches !== null ) {
|
||||
tabId = matches[1];
|
||||
tabId = parseInt(matches[1], 10);
|
||||
// No need for logger button when embedded in logger
|
||||
uDom('[data-extension-url="logger-ui.html"]').remove();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
uMatrix - a Chromium browser extension to black/white list requests.
|
||||
Copyright (C) 2014-2017 Raymond Hill
|
||||
uMatrix - a browser extension to black/white list requests.
|
||||
Copyright (C) 2014-2018 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
|
||||
|
@ -89,8 +89,10 @@ var onPSLReady = function() {
|
|||
// rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the
|
||||
// normal way forbid binding behind the scene tab.
|
||||
// https://github.com/gorhill/httpswitchboard/issues/67
|
||||
µm.pageStores[vAPI.noTabId] = µm.pageStoreFactory(µm.tabContextManager.mustLookup(vAPI.noTabId));
|
||||
µm.pageStores[vAPI.noTabId].title = vAPI.i18n('statsPageDetailedBehindTheScenePage');
|
||||
let pageStore =
|
||||
µm.pageStoreFactory(µm.tabContextManager.mustLookup(vAPI.noTabId));
|
||||
pageStore.title = vAPI.i18n('statsPageDetailedBehindTheScenePage');
|
||||
µm.pageStores.set(vAPI.noTabId, pageStore);
|
||||
|
||||
vAPI.tabs.getAll(onTabsReady);
|
||||
};
|
||||
|
|
|
@ -519,11 +519,32 @@
|
|||
µMatrix.mergeHostsFileContent = function(rawText) {
|
||||
var rawEnd = rawText.length;
|
||||
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 matches;
|
||||
var lineBeg = 0, lineEnd;
|
||||
var line;
|
||||
|
||||
while ( lineBeg < rawEnd ) {
|
||||
lineEnd = rawText.indexOf('\n', lineBeg);
|
||||
|
@ -537,7 +558,7 @@
|
|||
// rhill 2014-04-18: The trim is important here, as without it there
|
||||
// could be a lingering `\r` which would cause problems in the
|
||||
// following parsing code.
|
||||
line = rawText.slice(lineBeg, lineEnd).trim();
|
||||
let line = rawText.slice(lineBeg, lineEnd).trim();
|
||||
lineBeg = lineEnd + 1;
|
||||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/15
|
||||
|
@ -550,22 +571,15 @@
|
|||
|
||||
// The filter is whatever sequence of printable ascii character without
|
||||
// whitespaces
|
||||
matches = reAsciiSegment.exec(line);
|
||||
if ( !matches || matches.length === 0 ) {
|
||||
continue;
|
||||
}
|
||||
let matches = reAsciiSegment.exec(line);
|
||||
if ( matches === null ) { continue; }
|
||||
|
||||
// Bypass anomalies
|
||||
// For example, when a filter contains whitespace characters, or
|
||||
// whatever else outside the range of printable ascii characters.
|
||||
if ( matches[0] !== line ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( matches[0] !== line ) { continue; }
|
||||
line = matches[0];
|
||||
if ( line === '' ) {
|
||||
continue;
|
||||
}
|
||||
if ( line === '' ) { continue; }
|
||||
|
||||
ubiquitousBlacklist.add(line);
|
||||
}
|
||||
|
|
155
src/js/tab.js
155
src/js/tab.js
|
@ -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
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -140,7 +140,7 @@ housekeep itself.
|
|||
*/
|
||||
|
||||
µm.tabContextManager = (function() {
|
||||
var tabContexts = Object.create(null);
|
||||
var tabContexts = new Map();
|
||||
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/1001
|
||||
// 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.gcTimer = null;
|
||||
|
||||
tabContexts[tabId] = this;
|
||||
tabContexts.set(tabId, this);
|
||||
};
|
||||
|
||||
TabContext.prototype.destroy = function() {
|
||||
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) {
|
||||
return;
|
||||
}
|
||||
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
|
||||
if ( this.gcTimer !== null ) {
|
||||
clearTimeout(this.gcTimer);
|
||||
this.gcTimer = null;
|
||||
}
|
||||
delete tabContexts[this.tabId];
|
||||
tabContexts.delete(this.tabId);
|
||||
};
|
||||
|
||||
TabContext.prototype.onTab = function(tab) {
|
||||
|
@ -285,7 +283,7 @@ housekeep itself.
|
|||
// These are to be used for the API of the tab context manager.
|
||||
|
||||
var push = function(tabId, url, context) {
|
||||
var entry = tabContexts[tabId];
|
||||
let entry = tabContexts.get(tabId);
|
||||
if ( entry === undefined ) {
|
||||
entry = new TabContext(tabId);
|
||||
entry.autodestroy();
|
||||
|
@ -303,7 +301,7 @@ housekeep itself.
|
|||
if ( url !== undefined ) {
|
||||
entry = push(tabId, url);
|
||||
} else {
|
||||
entry = tabContexts[tabId];
|
||||
entry = tabContexts.get(tabId);
|
||||
}
|
||||
if ( entry !== undefined ) {
|
||||
return entry;
|
||||
|
@ -329,11 +327,11 @@ housekeep itself.
|
|||
// about to fall through the cracks.
|
||||
// Example: Chromium + case #12 at
|
||||
// http://raymondhill.net/ublock/popup.html
|
||||
return tabContexts[vAPI.noTabId];
|
||||
return tabContexts.get(vAPI.noTabId);
|
||||
};
|
||||
|
||||
var lookup = function(tabId) {
|
||||
return tabContexts[tabId] || null;
|
||||
return tabContexts.get(tabId) || null;
|
||||
};
|
||||
|
||||
// Behind-the-scene tab context
|
||||
|
@ -372,7 +370,7 @@ housekeep itself.
|
|||
|
||||
vAPI.tabs.onClosed = function(tabId) {
|
||||
µm.unbindTabFromPageStats(tabId);
|
||||
var entry = tabContexts[tabId];
|
||||
let entry = tabContexts.get(tabId);
|
||||
if ( entry instanceof TabContext ) {
|
||||
entry.destroy();
|
||||
}
|
||||
|
@ -397,7 +395,7 @@ vAPI.tabs.registerListeners();
|
|||
|
||||
// Do not create a page store for URLs which are of no interests
|
||||
// Example: dev console
|
||||
var tabContext = this.tabContextManager.lookup(tabId);
|
||||
let tabContext = this.tabContextManager.lookup(tabId);
|
||||
if ( tabContext === null ) {
|
||||
throw new Error('Unmanaged tab id: ' + tabId);
|
||||
}
|
||||
|
@ -406,14 +404,14 @@ vAPI.tabs.registerListeners();
|
|||
// virtual tab.
|
||||
// https://github.com/gorhill/httpswitchboard/issues/67
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
return this.pageStores[tabId];
|
||||
return this.pageStores.get(tabId);
|
||||
}
|
||||
|
||||
var normalURL = tabContext.normalURL;
|
||||
var pageStore = this.pageStores[tabId] || null;
|
||||
let normalURL = tabContext.normalURL;
|
||||
let pageStore = this.pageStores.get(tabId);
|
||||
|
||||
// The previous page URL, if any, associated with the tab
|
||||
if ( pageStore !== null ) {
|
||||
if ( pageStore !== undefined ) {
|
||||
// No change, do not rebind
|
||||
if ( pageStore.pageUrl === normalURL ) {
|
||||
return pageStore;
|
||||
|
@ -425,7 +423,10 @@ vAPI.tabs.registerListeners();
|
|||
// Example: Google Maps, Github
|
||||
// https://github.com/gorhill/uMatrix/issues/72
|
||||
// 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.normalURL = normalURL;
|
||||
this.updateTitle(tabId);
|
||||
|
@ -442,29 +443,22 @@ vAPI.tabs.registerListeners();
|
|||
if ( pageStore === null ) {
|
||||
pageStore = this.pageStoreFactory(tabContext);
|
||||
}
|
||||
this.pageStores[tabId] = pageStore;
|
||||
this.pageStores.set(tabId, pageStore);
|
||||
this.updateTitle(tabId);
|
||||
this.pageStoresToken = Date.now();
|
||||
|
||||
// console.debug('tab.js > bindTabToPageStats(): dispatching traffic in tab id %d to page store "%s"', tabId, pageUrl);
|
||||
|
||||
return pageStore;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µ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;
|
||||
if ( pageStore === null ) {
|
||||
return;
|
||||
}
|
||||
let pageStore = this.pageStores.get(tabId);
|
||||
if ( pageStore === undefined ) { return; }
|
||||
|
||||
delete this.pageStores[tabId];
|
||||
this.pageStores.delete(tabId);
|
||||
this.pageStoresToken = Date.now();
|
||||
|
||||
if ( pageStore.incinerationTimer ) {
|
||||
|
@ -472,13 +466,13 @@ vAPI.tabs.registerListeners();
|
|||
pageStore.incinerationTimer = null;
|
||||
}
|
||||
|
||||
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
|
||||
this.pageStoreCemetery[tabId] = {};
|
||||
let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
|
||||
if ( pageStoreCrypt === undefined ) {
|
||||
this.pageStoreCemetery.set(tabId, (pageStoreCrypt = new Map()));
|
||||
}
|
||||
var pageStoreCrypt = this.pageStoreCemetery[tabId];
|
||||
|
||||
var pageURL = pageStore.pageUrl;
|
||||
pageStoreCrypt[pageURL] = pageStore;
|
||||
let pageURL = pageStore.pageUrl;
|
||||
pageStoreCrypt.set(pageURL, pageStore);
|
||||
|
||||
pageStore.incinerationTimer = vAPI.setTimeout(
|
||||
this.incineratePageStore.bind(this, tabId, pageURL),
|
||||
|
@ -489,25 +483,21 @@ vAPI.tabs.registerListeners();
|
|||
/******************************************************************************/
|
||||
|
||||
µm.resurrectPageStore = function(tabId, pageURL) {
|
||||
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
|
||||
return null;
|
||||
}
|
||||
var pageStoreCrypt = this.pageStoreCemetery[tabId];
|
||||
let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
|
||||
if ( pageStoreCrypt === undefined ) { return null; }
|
||||
|
||||
if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) {
|
||||
return null;
|
||||
}
|
||||
let pageStore = pageStoreCrypt.get(pageURL);
|
||||
if ( pageStore === undefined ) { return null; }
|
||||
|
||||
var pageStore = pageStoreCrypt[pageURL];
|
||||
|
||||
if ( pageStore.incinerationTimer !== null ) {
|
||||
clearTimeout(pageStore.incinerationTimer);
|
||||
pageStore.incinerationTimer = null;
|
||||
}
|
||||
|
||||
delete pageStoreCrypt[pageURL];
|
||||
if ( Object.keys(pageStoreCrypt).length === 0 ) {
|
||||
delete this.pageStoreCemetery[tabId];
|
||||
pageStoreCrypt.delete(pageURL);
|
||||
if ( pageStoreCrypt.size === 0 ) {
|
||||
this.pageStoreCemetery.delete(tabId);
|
||||
}
|
||||
|
||||
return pageStore;
|
||||
|
@ -516,24 +506,20 @@ vAPI.tabs.registerListeners();
|
|||
/******************************************************************************/
|
||||
|
||||
µm.incineratePageStore = function(tabId, pageURL) {
|
||||
if ( this.pageStoreCemetery.hasOwnProperty(tabId) === false ) {
|
||||
return;
|
||||
}
|
||||
var pageStoreCrypt = this.pageStoreCemetery[tabId];
|
||||
let pageStoreCrypt = this.pageStoreCemetery.get(tabId);
|
||||
if ( pageStoreCrypt === undefined ) { return; }
|
||||
|
||||
if ( pageStoreCrypt.hasOwnProperty(pageURL) === false ) {
|
||||
return;
|
||||
}
|
||||
let pageStore = pageStoreCrypt.get(pageURL);
|
||||
if ( pageStore === undefined ) { return; }
|
||||
|
||||
var pageStore = pageStoreCrypt[pageURL];
|
||||
if ( pageStore.incinerationTimer !== null ) {
|
||||
clearTimeout(pageStore.incinerationTimer);
|
||||
pageStore.incinerationTimer = null;
|
||||
}
|
||||
|
||||
delete pageStoreCrypt[pageURL];
|
||||
if ( Object.keys(pageStoreCrypt).length === 0 ) {
|
||||
delete this.pageStoreCemetery[tabId];
|
||||
pageStoreCrypt.delete(pageURL);
|
||||
if ( pageStoreCrypt.size === 0 ) {
|
||||
this.pageStoreCemetery.delete(tabId);
|
||||
}
|
||||
|
||||
pageStore.dispose();
|
||||
|
@ -542,12 +528,12 @@ vAPI.tabs.registerListeners();
|
|||
/******************************************************************************/
|
||||
|
||||
µm.pageStoreFromTabId = function(tabId) {
|
||||
return this.pageStores[tabId] || null;
|
||||
return this.pageStores.get(tabId) || null;
|
||||
};
|
||||
|
||||
// Never return null
|
||||
µ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() {
|
||||
var tabIdToTimer = Object.create(null);
|
||||
var tabIdToTryCount = Object.create(null);
|
||||
var delay = 499;
|
||||
let tabIdToTimer = new Map();
|
||||
let tabIdToTryCount = new Map();
|
||||
let delay = 499;
|
||||
|
||||
var tryNoMore = function(tabId) {
|
||||
delete tabIdToTryCount[tabId];
|
||||
let tryNoMore = function(tabId) {
|
||||
tabIdToTryCount.delete(tabId);
|
||||
};
|
||||
|
||||
var tryAgain = function(tabId) {
|
||||
var count = tabIdToTryCount[tabId];
|
||||
if ( count === undefined ) {
|
||||
return false;
|
||||
}
|
||||
let tryAgain = function(tabId) {
|
||||
let count = tabIdToTryCount.get(tabId);
|
||||
if ( count === undefined ) { return false; }
|
||||
if ( count === 1 ) {
|
||||
delete tabIdToTryCount[tabId];
|
||||
tabIdToTryCount.delete(tabId);
|
||||
return false;
|
||||
}
|
||||
tabIdToTryCount[tabId] = count - 1;
|
||||
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(µm, tabId), delay);
|
||||
tabIdToTryCount.set(tabId, count - 1);
|
||||
tabIdToTimer.set(
|
||||
tabId,
|
||||
vAPI.setTimeout(updateTitle.bind(µm, tabId), delay)
|
||||
);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -652,19 +639,21 @@ vAPI.tabs.registerListeners();
|
|||
};
|
||||
|
||||
var updateTitle = function(tabId) {
|
||||
delete tabIdToTimer[tabId];
|
||||
tabIdToTimer.delete(tabId);
|
||||
vAPI.tabs.get(tabId, onTabReady.bind(this, tabId));
|
||||
};
|
||||
|
||||
return function(tabId) {
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
return;
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
|
||||
let timer = tabIdToTimer.get(tabId);
|
||||
if ( timer !== undefined ) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
if ( tabIdToTimer[tabId] ) {
|
||||
clearTimeout(tabIdToTimer[tabId]);
|
||||
}
|
||||
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(this, tabId), delay);
|
||||
tabIdToTryCount[tabId] = 5;
|
||||
tabIdToTimer.set(
|
||||
tabId,
|
||||
vAPI.setTimeout(updateTitle.bind(this, tabId), delay)
|
||||
);
|
||||
tabIdToTryCount.set(tabId, 5);
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -680,7 +669,7 @@ vAPI.tabs.registerListeners();
|
|||
|
||||
var cleanup = function() {
|
||||
var vapiTabs = vAPI.tabs;
|
||||
var tabIds = Object.keys(µm.pageStores).sort();
|
||||
var tabIds = Array.from(µm.pageStores.keys()).sort();
|
||||
var checkTab = function(tabId) {
|
||||
vapiTabs.get(tabId, function(tab) {
|
||||
if ( !tab ) {
|
||||
|
@ -695,9 +684,7 @@ vAPI.tabs.registerListeners();
|
|||
var n = Math.min(cleanupSampleAt + cleanupSampleSize, tabIds.length);
|
||||
for ( var i = cleanupSampleAt; i < n; i++ ) {
|
||||
tabId = tabIds[i];
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
continue;
|
||||
}
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { continue; }
|
||||
checkTab(tabId);
|
||||
}
|
||||
cleanupSampleAt = n;
|
||||
|
|
|
@ -127,6 +127,12 @@ var onBeforeRequestHandler = function(details) {
|
|||
rootHostname = tabContext.rootHostname,
|
||||
specificity = 0;
|
||||
|
||||
if ( tabId < 0 && details.documentUrl !== undefined ) {
|
||||
rootHostname = µmuri.hostnameFromURI(
|
||||
µm.normalizePageURL(0, details.documentUrl)
|
||||
);
|
||||
}
|
||||
|
||||
// Filter through matrix
|
||||
var block = µm.tMatrix.mustBlock(
|
||||
rootHostname,
|
||||
|
@ -344,16 +350,10 @@ var onHeadersReceived = function(details) {
|
|||
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) ) {
|
||||
csp.push(cspNoWorker);
|
||||
csp.push(µm.cspNoWorker);
|
||||
} else if ( µm.rawSettings.disableCSPReportInjection === false ) {
|
||||
cspReport.push(cspNoWorker);
|
||||
cspReport.push(µm.cspNoWorker);
|
||||
}
|
||||
|
||||
if ( csp.length === 0 && cspReport.length === 0 ) { return; }
|
||||
|
@ -368,7 +368,7 @@ var onHeadersReceived = function(details) {
|
|||
if ( csp.length !== 0 ) {
|
||||
let cspRight = csp.join(', ');
|
||||
let cspTotal = cspRight;
|
||||
if ( cantMergeCSPHeaders ) {
|
||||
if ( µm.cantMergeCSPHeaders ) {
|
||||
let i = headerIndexFromName(
|
||||
'content-security-policy',
|
||||
headers
|
||||
|
@ -390,7 +390,7 @@ var onHeadersReceived = function(details) {
|
|||
if ( cspReport.length !== 0 ) {
|
||||
let cspRight = cspReport.join(', ');
|
||||
let cspTotal = cspRight;
|
||||
if ( cantMergeCSPHeaders ) {
|
||||
if ( µm.cantMergeCSPHeaders ) {
|
||||
let i = headerIndexFromName(
|
||||
'content-security-policy-report-only',
|
||||
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
|
||||
// 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() {
|
||||
if ( vAPI.webextFlavor === undefined ) {
|
||||
return "child-src 'none'; frame-src data: blob: *; report-uri about:blank";
|
||||
window.addEventListener('webextFlavor', function() {
|
||||
if ( vAPI.webextFlavor.soup.has('firefox') === false ) { return; }
|
||||
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) ?
|
||||
"child-src 'none'; frame-src data: blob: *; report-uri about:blank" :
|
||||
"worker-src 'none'; report-uri about:blank" ;
|
||||
return µMatrix.cspNoWorker;
|
||||
};
|
||||
if ( vAPI.webextFlavor.major <= 58 ) {
|
||||
µMatrix.cantMergeCSPHeaders = true;
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
Loading…
Reference in a new issue