1
0
mirror of https://github.com/gorhill/uBlock.git synced 2024-10-06 09:37:12 +02:00
This commit is contained in:
Raymond Hill 2018-02-26 13:59:16 -05:00
parent 64682ab8a1
commit 2c901588c7
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
12 changed files with 191 additions and 188 deletions

View File

@ -265,18 +265,29 @@ vAPI.tabs = {};
/******************************************************************************/ /******************************************************************************/
// https://github.com/gorhill/uBlock/issues/3546
// Added a new flavor of behind-the-scene tab id: vAPI.anyTabId.
// vAPI.anyTabId will be used for network requests which can be filtered,
// because they comes with enough contextual information. It's just not
// possible to pinpoint exactly from which tab it comes from. For example,
// with Firefox/webext, the `documentUrl` property is available for every
// network requests.
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
/******************************************************************************/ /******************************************************************************/
// To remove when tabId-as-integer has been tested enough.
var toChromiumTabId = function(tabId) { var toChromiumTabId = function(tabId) {
if ( typeof tabId === 'string' ) { if ( typeof tabId === 'string' ) { debugger; }
tabId = parseInt(tabId, 10);
}
if ( typeof tabId !== 'number' || isNaN(tabId) || tabId === -1 ) { if ( typeof tabId !== 'number' || isNaN(tabId) || tabId === -1 ) {
return 0; return 0;
} }
@ -329,8 +340,8 @@ vAPI.tabs.registerListeners = function() {
} }
if ( typeof vAPI.tabs.onPopupCreated === 'function' ) { if ( typeof vAPI.tabs.onPopupCreated === 'function' ) {
vAPI.tabs.onPopupCreated( vAPI.tabs.onPopupCreated(
details.tabId.toString(), details.tabId,
details.sourceTabId.toString() details.sourceTabId
); );
} }
}; };
@ -364,7 +375,7 @@ vAPI.tabs.registerListeners = function() {
if ( changeInfo.url ) { if ( changeInfo.url ) {
changeInfo.url = sanitizeURL(changeInfo.url); changeInfo.url = sanitizeURL(changeInfo.url);
} }
onUpdatedClient(tabId.toString(), changeInfo, tab); onUpdatedClient(tabId, changeInfo, tab);
}; };
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate); chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
@ -542,9 +553,7 @@ vAPI.tabs.open = function(details) {
vAPI.tabs.replace = function(tabId, url) { vAPI.tabs.replace = function(tabId, url) {
tabId = toChromiumTabId(tabId); tabId = toChromiumTabId(tabId);
if ( tabId === 0 ) { if ( tabId === 0 ) { return; }
return;
}
var targetURL = url; var targetURL = url;
@ -565,9 +574,7 @@ vAPI.tabs.replace = function(tabId, url) {
vAPI.tabs.remove = function(tabId) { vAPI.tabs.remove = function(tabId) {
tabId = toChromiumTabId(tabId); tabId = toChromiumTabId(tabId);
if ( tabId === 0 ) { if ( tabId === 0 ) { return; }
return;
}
var onTabRemoved = function() { var onTabRemoved = function() {
// https://code.google.com/p/chromium/issues/detail?id=410868#c8 // https://code.google.com/p/chromium/issues/detail?id=410868#c8
@ -605,9 +612,7 @@ vAPI.tabs.reload = function(tabId, bypassCache) {
vAPI.tabs.select = function(tabId) { vAPI.tabs.select = function(tabId) {
tabId = toChromiumTabId(tabId); tabId = toChromiumTabId(tabId);
if ( tabId === 0 ) { if ( tabId === 0 ) { return; }
return;
}
chrome.tabs.update(tabId, { active: true }, function(tab) { chrome.tabs.update(tabId, { active: true }, function(tab) {
if ( chrome.runtime.lastError ) { if ( chrome.runtime.lastError ) {
@ -789,7 +794,7 @@ vAPI.messaging.onPortMessage = (function() {
case 'connectionRefused': case 'connectionRefused':
toPort = messaging.ports.get(msg.fromToken); toPort = messaging.ports.get(msg.fromToken);
if ( toPort !== undefined ) { if ( toPort !== undefined ) {
msg.tabId = tabId && tabId.toString(); msg.tabId = tabId;
toPort.postMessage(request); toPort.postMessage(request);
} else { } else {
msg.what = 'connectionBroken'; msg.what = 'connectionBroken';
@ -797,7 +802,7 @@ vAPI.messaging.onPortMessage = (function() {
} }
break; break;
case 'connectionRequested': case 'connectionRequested':
msg.tabId = tabId && tabId.toString(); msg.tabId = tabId;
for ( toPort of messaging.ports.values() ) { for ( toPort of messaging.ports.values() ) {
toPort.postMessage(request); toPort.postMessage(request);
} }
@ -809,7 +814,7 @@ vAPI.messaging.onPortMessage = (function() {
port.name === msg.fromToken ? msg.toToken : msg.fromToken port.name === msg.fromToken ? msg.toToken : msg.fromToken
); );
if ( toPort !== undefined ) { if ( toPort !== undefined ) {
msg.tabId = tabId && tabId.toString(); msg.tabId = tabId;
toPort.postMessage(request); toPort.postMessage(request);
} else { } else {
msg.what = 'connectionBroken'; msg.what = 'connectionBroken';

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2017 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
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
@ -105,8 +105,6 @@ vAPI.net.registerListeners = function() {
}; };
var normalizeRequestDetails = function(details) { var normalizeRequestDetails = function(details) {
details.tabId = details.tabId.toString();
var type = details.type; var type = details.type;
// https://github.com/gorhill/uBlock/issues/1493 // https://github.com/gorhill/uBlock/issues/1493

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2014-2107 The uBlock Origin authors Copyright (C) 2014-2018 The 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
@ -833,10 +833,11 @@ var getOwnerWindow = function(target) {
/******************************************************************************/ /******************************************************************************/
vAPI.isBehindTheSceneTabId = function(tabId) { vAPI.isBehindTheSceneTabId = function(tabId) {
return tabId.toString() === '-1'; return tabId < 0;
}; };
vAPI.noTabId = '-1'; vAPI.noTabId = -1;
vAPI.anyTabId = -2;
/******************************************************************************/ /******************************************************************************/
@ -1283,7 +1284,7 @@ var tabWatcher = (function() {
} }
var tabId = browserToTabIdMap.get(browser); var tabId = browserToTabIdMap.get(browser);
if ( tabId === undefined ) { if ( tabId === undefined ) {
tabId = '' + tabIdGenerator++; tabId = tabIdGenerator++;
browserToTabIdMap.set(browser, tabId); browserToTabIdMap.set(browser, tabId);
tabIdToBrowserMap.set(tabId, Cu.getWeakReference(browser)); tabIdToBrowserMap.set(tabId, Cu.getWeakReference(browser));
} }
@ -1316,7 +1317,7 @@ var tabWatcher = (function() {
var removeBrowserEntry = function(tabId, browser) { var removeBrowserEntry = function(tabId, browser) {
if ( tabId && tabId !== vAPI.noTabId ) { if ( tabId && tabId !== vAPI.noTabId ) {
vAPI.tabs.onClosed(tabId); vAPI.tabs.onClosed(tabId);
delete vAPI.toolbarButton.tabs[tabId]; vAPI.toolbarButton.tabs.delete(tabId);
tabIdToBrowserMap.delete(tabId); tabIdToBrowserMap.delete(tabId);
} }
if ( browser ) { if ( browser ) {
@ -1539,7 +1540,7 @@ vAPI.setIcon = function(tabId, iconStatus, badge) {
if ( tabId === undefined ) { if ( tabId === undefined ) {
tabId = curTabId; tabId = curTabId;
} else if ( badge !== undefined ) { } else if ( badge !== undefined ) {
tb.tabs[tabId] = { badge: badge, img: iconStatus === 'on' }; tb.tabs.set(tabId, { badge: badge, img: iconStatus === 'on' });
} }
if ( curTabId && tabId === curTabId ) { if ( curTabId && tabId === curTabId ) {
@ -2028,7 +2029,7 @@ var httpObserver = {
}, },
// https://github.com/gorhill/uBlock/issues/959 // https://github.com/gorhill/uBlock/issues/959
syntheticPendingRequest: { frameId: 0, parentFrameId: -1, tabId: '', rawtype: 1 }, syntheticPendingRequest: { frameId: 0, parentFrameId: -1, tabId: 0, rawtype: 1 },
handleRequest: function(channel, URI, details) { handleRequest: function(channel, URI, details) {
var type = this.typeMap[details.rawtype] || 'other'; var type = this.typeMap[details.rawtype] || 'other';
@ -2437,7 +2438,7 @@ vAPI.toolbarButton = {
viewId: location.host + '-panel', viewId: location.host + '-panel',
label: vAPI.app.name, label: vAPI.app.name,
tooltiptext: vAPI.app.name, tooltiptext: vAPI.app.name,
tabs: {/*tabId: {badge: 0, img: boolean}*/}, tabs: new Map(/* tabId: { badge: 0, img: boolean } */),
init: null, init: null,
codePath: '' codePath: ''
}; };
@ -2473,8 +2474,8 @@ vAPI.toolbarButton = {
if ( tabId === undefined ) { if ( tabId === undefined ) {
return label; return label;
} }
var tabDetails = this.tabs[tabId]; var tabDetails = this.tabs.get(tabId);
if ( !tabDetails ) { if ( tabDetails === undefined ) {
return label; return label;
} }
if ( !tabDetails.img ) { if ( !tabDetails.img ) {
@ -2563,7 +2564,7 @@ vAPI.toolbarButton = {
return; return;
} }
var icon = this.tabs[tabId]; var icon = this.tabs.get(tabId);
button.setAttribute('badge', icon && icon.badge || ''); button.setAttribute('badge', icon && icon.badge || '');
button.classList.toggle('off', !icon || !icon.img); button.classList.toggle('off', !icon || !icon.img);
@ -3502,9 +3503,8 @@ vAPI.onLoadAllCompleted = function() {
// TODO: vAPI shouldn't know about uBlock. Just like in uMatrix, uBlock // TODO: vAPI shouldn't know about uBlock. Just like in uMatrix, uBlock
// should collect on its side all the opened tabs whenever it is ready. // should collect on its side all the opened tabs whenever it is ready.
var µb = µBlock; var µb = µBlock;
var tabId;
for ( var browser of tabWatcher.browsers() ) { for ( var browser of tabWatcher.browsers() ) {
tabId = tabWatcher.tabIdFromTarget(browser); var tabId = tabWatcher.tabIdFromTarget(browser);
µb.tabContextManager.commit(tabId, browser.currentURI.asciiSpec); µb.tabContextManager.commit(tabId, browser.currentURI.asciiSpec);
µb.bindTabToPageStats(tabId); µb.bindTabToPageStats(tabId);
} }

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block requests.
Copyright (C) 2017 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
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
@ -100,10 +100,16 @@ vAPI.net.registerListeners = function() {
var punycode = self.punycode; var punycode = self.punycode;
var reAsciiHostname = /^https?:\/\/[0-9a-z_.:@-]+[/?#]/; var reAsciiHostname = /^https?:\/\/[0-9a-z_.:@-]+[/?#]/;
var reNetworkURI = /^(?:ftps?|https?|wss?)/;
var parsedURL = new URL('about:blank'); var parsedURL = new URL('about:blank');
var normalizeRequestDetails = function(details) { var normalizeRequestDetails = function(details) {
details.tabId = details.tabId.toString(); if (
details.tabId === vAPI.noTabId &&
reNetworkURI.test(details.documentUrl)
) {
details.tabId = vAPI.anyTabId;
}
if ( mustPunycode && !reAsciiHostname.test(details.url) ) { if ( mustPunycode && !reAsciiHostname.test(details.url) ) {
parsedURL.href = details.url; parsedURL.href = details.url;

View File

@ -148,7 +148,7 @@ var µBlock = (function() { // jshint ignore:line
selfieAfter: 17 * oneMinute, selfieAfter: 17 * oneMinute,
pageStores: {}, pageStores: new Map(),
pageStoresToken: 0, pageStoresToken: 0,
storageQuota: vAPI.storage.QUOTA_BYTES, storageQuota: vAPI.storage.QUOTA_BYTES,

View File

@ -45,7 +45,7 @@ if (
var logger = self.logger; var logger = self.logger;
var inspectorConnectionId; var inspectorConnectionId;
var inspectedTabId = ''; var inspectedTabId = 0;
var inspectedURL = ''; var inspectedURL = '';
var inspectedHostname = ''; var inspectedHostname = '';
var inspector = uDom.nodeFromId('domInspector'); var inspector = uDom.nodeFromId('domInspector');
@ -468,7 +468,7 @@ var startDialog = (function() {
var onClicked = function(ev) { var onClicked = function(ev) {
ev.stopPropagation(); ev.stopPropagation();
if ( inspectedTabId === '' ) { return; } if ( inspectedTabId === 0 ) { return; }
var target = ev.target; var target = ev.target;
var parent = target.parentElement; var parent = target.parentElement;
@ -540,7 +540,7 @@ var onMouseOver = (function() {
}; };
return function(ev) { return function(ev) {
if ( inspectedTabId === '' ) { return; } if ( inspectedTabId === 0 ) { return; }
// Convenience: skip real-time highlighting if shift key is pressed. // Convenience: skip real-time highlighting if shift key is pressed.
if ( ev.shiftKey ) { return; } if ( ev.shiftKey ) { return; }
// Find closest `li` // Find closest `li`
@ -560,7 +560,7 @@ var onMouseOver = (function() {
/******************************************************************************/ /******************************************************************************/
var currentTabId = function() { var currentTabId = function() {
if ( showdomButton.classList.contains('active') === false ) { return ''; } if ( showdomButton.classList.contains('active') === false ) { return 0; }
return logger.tabIdFromPageSelector(); return logger.tabIdFromPageSelector();
}; };
@ -568,7 +568,7 @@ var currentTabId = function() {
var injectInspector = function() { var injectInspector = function() {
var tabId = currentTabId(); var tabId = currentTabId();
if ( tabId === '' ) { return; } if ( tabId === 0 ) { return; }
inspectedTabId = tabId; inspectedTabId = tabId;
messaging.send('loggerUI', { messaging.send('loggerUI', {
what: 'scriptlet', what: 'scriptlet',
@ -586,7 +586,7 @@ var shutdownInspector = function() {
} }
logger.removeAllChildren(domTree); logger.removeAllChildren(domTree);
inspector.classList.add('vCompact'); inspector.classList.add('vCompact');
inspectedTabId = ''; inspectedTabId = 0;
}; };
/******************************************************************************/ /******************************************************************************/
@ -658,7 +658,7 @@ var toggleOff = function() {
uDom.nodeFromSelector('#domInspector .permatoolbar .highlightMode').removeEventListener('click', toggleHighlightMode); uDom.nodeFromSelector('#domInspector .permatoolbar .highlightMode').removeEventListener('click', toggleHighlightMode);
uDom.nodeFromSelector('#domInspector .permatoolbar .revert').removeEventListener('click', revert); uDom.nodeFromSelector('#domInspector .permatoolbar .revert').removeEventListener('click', revert);
uDom.nodeFromSelector('#domInspector .permatoolbar .commit').removeEventListener('click', startDialog); uDom.nodeFromSelector('#domInspector .permatoolbar .commit').removeEventListener('click', startDialog);
inspectedTabId = ''; inspectedTabId = 0;
}; };
/******************************************************************************/ /******************************************************************************/

View File

@ -56,7 +56,7 @@ var tabIdFromPageSelector = logger.tabIdFromPageSelector = function() {
if ( tabClass === 'tab_active' && activeTabId !== undefined ) { if ( tabClass === 'tab_active' && activeTabId !== undefined ) {
return activeTabId; return activeTabId;
} }
return /^tab_\d+$/.test(tabClass) ? tabClass.slice(4) : ''; return /^tab_\d+$/.test(tabClass) ? parseInt(tabClass.slice(4), 10) : 0;
}; };
/******************************************************************************/ /******************************************************************************/
@ -79,8 +79,7 @@ var tdJunkyard = [];
var firstVarDataCol = 2; // currently, column 2 (0-based index) var firstVarDataCol = 2; // currently, column 2 (0-based index)
var lastVarDataIndex = 4; // currently, d0-d3 var lastVarDataIndex = 4; // currently, d0-d3
var maxEntries = 5000; var maxEntries = 5000;
var noTabId = ''; var allTabIds = new Map();
var allTabIds = {};
var allTabIdsToken; var allTabIdsToken;
var hiddenTemplate = document.querySelector('#hiddenTemplate > span'); var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/;
@ -113,7 +112,7 @@ var staticFilterTypes = {
/******************************************************************************/ /******************************************************************************/
var classNameFromTabId = function(tabId) { var classNameFromTabId = function(tabId) {
if ( tabId === noTabId ) { if ( tabId < 0 ) {
return 'tab_bts'; return 'tab_bts';
} }
if ( tabId !== '' ) { if ( tabId !== '' ) {
@ -353,7 +352,7 @@ var renderLogEntry = function(entry) {
if ( entry.tab ) { if ( entry.tab ) {
tr.classList.add('tab'); tr.classList.add('tab');
tr.classList.add(classNameFromTabId(entry.tab)); tr.classList.add(classNameFromTabId(entry.tab));
if ( entry.tab === noTabId ) { if ( entry.tab < 0 ) {
tr.cells[1].appendChild(createHiddenTextNode('bts')); tr.cells[1].appendChild(createHiddenTextNode('bts'));
} }
} }
@ -392,7 +391,7 @@ var renderLogEntries = function(response) {
// https://github.com/gorhill/uBlock/issues/1613#issuecomment-217637122 // https://github.com/gorhill/uBlock/issues/1613#issuecomment-217637122
// Unlikely, but it may happen: mark as void if associated tab no // Unlikely, but it may happen: mark as void if associated tab no
// longer exist. // longer exist.
if ( entry.tab && tabIds.hasOwnProperty(entry.tab) === false ) { if ( entry.tab && tabIds.has(entry.tab) === false ) {
tr.classList.remove('canMtx'); tr.classList.remove('canMtx');
} }
} }
@ -422,9 +421,8 @@ var synchronizeTabIds = function(newTabIds) {
var oldTabIds = allTabIds; var oldTabIds = allTabIds;
var autoDeleteVoidRows = selectValue === 'tab_active'; var autoDeleteVoidRows = selectValue === 'tab_active';
var rowVoided = false; var rowVoided = false;
for ( var tabId in oldTabIds ) { for ( var tabId of oldTabIds.keys() ) {
if ( oldTabIds.hasOwnProperty(tabId) === false ) { continue; } if ( newTabIds.has(tabId) ) { continue; }
if ( newTabIds.hasOwnProperty(tabId) ) { continue; }
// Mark or remove voided rows // Mark or remove voided rows
var trs = uDom('.tab_' + tabId); var trs = uDom('.tab_' + tabId);
if ( autoDeleteVoidRows ) { if ( autoDeleteVoidRows ) {
@ -439,20 +437,20 @@ var synchronizeTabIds = function(newTabIds) {
} }
} }
var tabIds = Object.keys(newTabIds).sort(function(a, b) { var tabIds = Array.from(newTabIds.keys()).sort(function(a, b) {
return newTabIds[a].localeCompare(newTabIds[b]); return newTabIds.get(a).localeCompare(newTabIds.get(b));
}); });
var option; var option;
for ( var i = 0, j = 3; i < tabIds.length; i++ ) { for ( var i = 0, j = 3; i < tabIds.length; i++ ) {
tabId = tabIds[i]; tabId = tabIds[i];
if ( tabId === noTabId ) { continue; } if ( tabId < 0 ) { continue; }
option = select.options[j]; option = select.options[j];
if ( !option ) { if ( !option ) {
option = document.createElement('option'); option = document.createElement('option');
select.appendChild(option); select.appendChild(option);
} }
// Truncate too long labels. // Truncate too long labels.
option.textContent = newTabIds[tabId].slice(0, 80); option.textContent = newTabIds.get(tabId).slice(0, 80);
option.value = classNameFromTabId(tabId); option.value = classNameFromTabId(tabId);
if ( option.value === selectValue ) { if ( option.value === selectValue ) {
select.selectedIndex = j; select.selectedIndex = j;
@ -500,14 +498,15 @@ var onLogBufferRead = function(response) {
return; return;
} }
// This tells us the behind-the-scene tab id
noTabId = response.noTabId;
// Tab id of currently active tab // Tab id of currently active tab
if ( response.activeTabId ) { if ( response.activeTabId ) {
activeTabId = response.activeTabId; activeTabId = response.activeTabId;
} }
if ( Array.isArray(response.tabIds) ) {
response.tabIds = new Map(response.tabIds);
}
// This may have changed meanwhile // This may have changed meanwhile
if ( response.maxEntries !== maxEntries ) { if ( response.maxEntries !== maxEntries ) {
maxEntries = response.maxEntries; maxEntries = response.maxEntries;
@ -625,7 +624,7 @@ var pageSelectorFromURLHash = (function() {
var reloadTab = function(ev) { var reloadTab = function(ev) {
var tabId = tabIdFromPageSelector(); var tabId = tabIdFromPageSelector();
if ( tabId === '' ) { return; } if ( tabId === 0 ) { return; }
messaging.send('loggerUI', { messaging.send('loggerUI', {
what: 'reloadTab', what: 'reloadTab',
tabId: tabId, tabId: tabId,
@ -965,7 +964,7 @@ var netFilteringManager = (function() {
// First, whether picker can be used // First, whether picker can be used
dialog.querySelector('.picker').classList.toggle( dialog.querySelector('.picker').classList.toggle(
'hide', 'hide',
targetTabId === noTabId || targetTabId < 0 ||
targetType !== 'image' || targetType !== 'image' ||
/(?:^| )[dlsu]b(?: |$)/.test(targetRow.className) /(?:^| )[dlsu]b(?: |$)/.test(targetRow.className)
); );
@ -1614,7 +1613,7 @@ var popupManager = (function() {
return; return;
} }
if ( localTabId === 'bts' ) { if ( localTabId === 'bts' ) {
realTabId = noTabId; realTabId = -1;
} }
container = uDom.nodeFromId('popupContainer'); container = uDom.nodeFromId('popupContainer');

View File

@ -1022,28 +1022,26 @@ vAPI.messaging.listen('dashboard', onMessage);
/******************************************************************************/ /******************************************************************************/
var µb = µBlock, var µb = µBlock,
extensionPageURL = vAPI.getURL(''); extensionOriginURL = vAPI.getURL('');
/******************************************************************************/ /******************************************************************************/
var getLoggerData = function(ownerId, activeTabId, callback) { var getLoggerData = function(ownerId, activeTabId, callback) {
var tabIds = {}; var tabIds = new Map();
for ( var tabId in µb.pageStores ) { for ( var entry of µb.pageStores ) {
var pageStore = µb.pageStoreFromTabId(tabId); var pageStore = entry[1];
if ( pageStore === null ) { continue; } if ( pageStore.rawURL.startsWith(extensionOriginURL) ) { continue; }
if ( pageStore.rawURL.startsWith(extensionPageURL) ) { continue; } tabIds.set(entry[0], pageStore.title);
tabIds[tabId] = pageStore.title;
} }
if ( activeTabId && tabIds.hasOwnProperty(activeTabId) === false ) { if ( activeTabId && tabIds.has(activeTabId) === false ) {
activeTabId = undefined; activeTabId = undefined;
} }
callback({ callback({
colorBlind: µb.userSettings.colorBlindFriendly, colorBlind: µb.userSettings.colorBlindFriendly,
entries: µb.logger.readAll(ownerId), entries: µb.logger.readAll(ownerId),
maxEntries: µb.userSettings.requestLogMaxEntries, maxEntries: µb.userSettings.requestLogMaxEntries,
noTabId: vAPI.noTabId,
activeTabId: activeTabId, activeTabId: activeTabId,
tabIds: tabIds, tabIds: Array.from(tabIds),
tabIdsToken: µb.pageStoresToken tabIdsToken: µb.pageStoresToken
}); });
}; };
@ -1093,11 +1091,7 @@ var onMessage = function(request, sender, callback) {
return; return;
} }
vAPI.tabs.get(null, function(tab) { vAPI.tabs.get(null, function(tab) {
getLoggerData( getLoggerData(request.ownerId, tab && tab.id, callback);
request.ownerId,
tab && tab.id.toString(),
callback
);
}); });
return; return;

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block 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
@ -284,7 +284,7 @@ PageStore.prototype.init = function(tabId, context) {
this.rawURL = tabContext.rawURL; this.rawURL = tabContext.rawURL;
this.hostnameToCountMap = new Map(); this.hostnameToCountMap = new Map();
this.contentLastModified = 0; this.contentLastModified = 0;
this.frames = Object.create(null); this.frames = new Map();
this.logData = undefined; this.logData = undefined;
this.perLoadBlockedRequestCount = 0; this.perLoadBlockedRequestCount = 0;
this.perLoadAllowedRequestCount = 0; this.perLoadAllowedRequestCount = 0;
@ -410,27 +410,26 @@ PageStore.prototype.dispose = function() {
/******************************************************************************/ /******************************************************************************/
PageStore.prototype.disposeFrameStores = function() { PageStore.prototype.disposeFrameStores = function() {
var frames = this.frames; for ( var frameStore of this.frames.values() ) {
for ( var k in frames ) { frameStore.dispose();
frames[k].dispose();
} }
this.frames = Object.create(null); this.frames.clear();
}; };
/******************************************************************************/ /******************************************************************************/
PageStore.prototype.getFrame = function(frameId) { PageStore.prototype.getFrame = function(frameId) {
return this.frames[frameId] || null; return this.frames.get(frameId) || null;
}; };
/******************************************************************************/ /******************************************************************************/
PageStore.prototype.setFrame = function(frameId, frameURL) { PageStore.prototype.setFrame = function(frameId, frameURL) {
var frameStore = this.frames[frameId]; var frameStore = this.frames.get(frameId);
if ( frameStore ) { if ( frameStore !== undefined ) {
frameStore.init(frameURL); frameStore.init(frameURL);
} else { } else {
this.frames[frameId] = FrameStore.factory(frameURL); this.frames.set(frameId, FrameStore.factory(frameURL));
} }
}; };
@ -445,8 +444,8 @@ PageStore.prototype.createContextFromPage = function() {
PageStore.prototype.createContextFromFrameId = function(frameId) { PageStore.prototype.createContextFromFrameId = function(frameId) {
var context = µb.tabContextManager.createContext(this.tabId); var context = µb.tabContextManager.createContext(this.tabId);
var frameStore = this.frames[frameId]; var frameStore = this.frames.get(frameId);
if ( frameStore ) { if ( frameStore !== undefined ) {
context.pageHostname = frameStore.pageHostname; context.pageHostname = frameStore.pageHostname;
context.pageDomain = frameStore.pageDomain; context.pageDomain = frameStore.pageDomain;
} else { } else {

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block 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
@ -128,7 +128,7 @@ housekeep itself.
*/ */
µb.tabContextManager = (function() { µb.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
@ -206,7 +206,7 @@ housekeep itself.
}; };
var TabContext = function(tabId) { var TabContext = function(tabId) {
this.tabId = tabId.toString(); this.tabId = tabId;
this.stack = []; this.stack = [];
this.rawURL = this.rawURL =
this.normalURL = this.normalURL =
@ -218,18 +218,16 @@ housekeep itself.
this.netFiltering = true; this.netFiltering = true;
this.netFilteringReadTime = 0; this.netFilteringReadTime = 0;
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) {
@ -363,7 +361,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) { var push = function(tabId, url) {
var entry = tabContexts[tabId]; var entry = tabContexts.get(tabId);
if ( entry === undefined ) { if ( entry === undefined ) {
entry = new TabContext(tabId); entry = new TabContext(tabId);
entry.autodestroy(); entry.autodestroy();
@ -376,13 +374,13 @@ housekeep itself.
// Find a tab context for a specific tab. // Find a tab context for a specific tab.
var lookup = function(tabId) { var lookup = function(tabId) {
return tabContexts[tabId] || null; return tabContexts.get(tabId) || null;
}; };
// Find a tab context for a specific tab. If none is found, attempt to // Find a tab context for a specific tab. If none is found, attempt to
// fix this. When all fail, the behind-the-scene context is returned. // fix this. When all fail, the behind-the-scene context is returned.
var mustLookup = function(tabId) { var mustLookup = function(tabId) {
var entry = tabContexts[tabId]; var entry = tabContexts.get(tabId);
if ( entry !== undefined ) { if ( entry !== undefined ) {
return entry; return entry;
} }
@ -407,13 +405,13 @@ 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);
}; };
// https://github.com/gorhill/uBlock/issues/1735 // https://github.com/gorhill/uBlock/issues/1735
// Filter for popups if actually committing. // Filter for popups if actually committing.
var commit = function(tabId, url) { var commit = function(tabId, url) {
var entry = tabContexts[tabId]; var entry = tabContexts.get(tabId);
if ( entry === undefined ) { if ( entry === undefined ) {
entry = push(tabId, url); entry = push(tabId, url);
} else if ( entry.commit(url) ) { } else if ( entry.commit(url) ) {
@ -423,7 +421,7 @@ housekeep itself.
}; };
var exists = function(tabId) { var exists = function(tabId) {
return tabContexts[tabId] !== undefined; return tabContexts.get(tabId) !== undefined;
}; };
// Behind-the-scene tab context // Behind-the-scene tab context
@ -434,6 +432,9 @@ housekeep itself.
entry.normalURL = µb.normalizePageURL(entry.tabId); entry.normalURL = µb.normalizePageURL(entry.tabId);
entry.rootHostname = µb.URI.hostnameFromURI(entry.normalURL); entry.rootHostname = µb.URI.hostnameFromURI(entry.normalURL);
entry.rootDomain = µb.URI.domainFromHostname(entry.rootHostname); entry.rootDomain = µb.URI.domainFromHostname(entry.rootHostname);
entry = new TabContext(vAPI.anyTabId);
entry.stack.push(new StackEntry('', true));
})(); })();
// Context object, typically to be used to feed filtering engines. // Context object, typically to be used to feed filtering engines.
@ -445,7 +446,7 @@ housekeep itself.
var tabContext = lookup(tabId); var tabContext = lookup(tabId);
this.rootHostname = tabContext.rootHostname; this.rootHostname = tabContext.rootHostname;
this.rootDomain = tabContext.rootDomain; this.rootDomain = tabContext.rootDomain;
this.pageHostname = this.pageHostname =
this.pageDomain = this.pageDomain =
this.requestURL = this.requestURL =
this.requestHostname = this.requestHostname =
@ -842,13 +843,15 @@ vAPI.tabs.registerListeners();
} }
// Reuse page store if one exists: this allows to guess if a tab is a popup // Reuse page store if one exists: this allows to guess if a tab is a popup
var pageStore = this.pageStores[tabId]; var pageStore = this.pageStores.get(tabId);
// Tab is not bound // Tab is not bound
if ( !pageStore ) { if ( pageStore === undefined ) {
this.updateTitle(tabId); this.updateTitle(tabId);
this.pageStoresToken = Date.now(); this.pageStoresToken = Date.now();
return (this.pageStores[tabId] = this.PageStore.factory(tabId, context)); pageStore = this.PageStore.factory(tabId, context);
this.pageStores.set(tabId, pageStore);
return pageStore;
} }
// https://github.com/chrisaljoudi/uBlock/issues/516 // https://github.com/chrisaljoudi/uBlock/issues/516
@ -878,10 +881,10 @@ vAPI.tabs.registerListeners();
µb.unbindTabFromPageStats = function(tabId) { µb.unbindTabFromPageStats = function(tabId) {
//console.debug('µBlock> unbindTabFromPageStats(%d)', tabId); //console.debug('µBlock> unbindTabFromPageStats(%d)', tabId);
var pageStore = this.pageStores[tabId]; var pageStore = this.pageStores.get(tabId);
if ( pageStore !== undefined ) { if ( pageStore !== undefined ) {
pageStore.dispose(); pageStore.dispose();
delete this.pageStores[tabId]; this.pageStores.delete(tabId);
this.pageStoresToken = Date.now(); this.pageStoresToken = Date.now();
} }
}; };
@ -889,29 +892,36 @@ vAPI.tabs.registerListeners();
/******************************************************************************/ /******************************************************************************/
µb.pageStoreFromTabId = function(tabId) { µb.pageStoreFromTabId = function(tabId) {
return this.pageStores[tabId] || null; return this.pageStores.get(tabId) || null;
}; };
µb.mustPageStoreFromTabId = function(tabId) { µb.mustPageStoreFromTabId = function(tabId) {
return this.pageStores[tabId] || this.pageStores[vAPI.noTabId]; return this.pageStores.get(tabId) || this.pageStores.get(vAPI.noTabId);
}; };
/******************************************************************************/ /******************************************************************************/
// Permanent page store for behind-the-scene requests. Must never be removed. // Permanent page store for behind-the-scene requests. Must never be removed.
µb.pageStores[vAPI.noTabId] = µb.PageStore.factory(vAPI.noTabId); (function() {
µb.pageStores[vAPI.noTabId].title = vAPI.i18n('logBehindTheScene'); var pageStore = µb.PageStore.factory(vAPI.noTabId);
µb.pageStores.set(pageStore.tabId, pageStore);
pageStore.title = vAPI.i18n('logBehindTheScene');
pageStore = µb.PageStore.factory(vAPI.anyTabId);
µb.pageStores.set(pageStore.tabId, pageStore);
pageStore.title = '[Any one of the known tabs]';
})();
/******************************************************************************/ /******************************************************************************/
// Update visual of extension icon. // Update visual of extension icon.
µb.updateBadgeAsync = (function() { µb.updateBadgeAsync = (function() {
var tabIdToTimer = Object.create(null); var tabIdToTimer = new Map();
var updateBadge = function(tabId) { var updateBadge = function(tabId) {
delete tabIdToTimer[tabId]; tabIdToTimer.delete(tabId);
var state = false; var state = false;
var badge = ''; var badge = '';
@ -928,82 +938,70 @@ vAPI.tabs.registerListeners();
}; };
return function(tabId) { return function(tabId) {
if ( tabIdToTimer[tabId] ) { if ( tabIdToTimer.has(tabId) ) { return; }
return; if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
} tabIdToTimer.set(
if ( vAPI.isBehindTheSceneTabId(tabId) ) { tabId,
return; vAPI.setTimeout(updateBadge.bind(this, tabId), 701)
} );
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 701);
}; };
})(); })();
/******************************************************************************/ /******************************************************************************/
µb.updateTitle = (function() { µb.updateTitle = (function() {
var tabIdToTimer = Object.create(null); var tabIdToTimer = new Map();
var tabIdToTryCount = Object.create(null);
var delay = 499; var delay = 499;
var tryNoMore = function(tabId) { var tryAgain = function(entry) {
delete tabIdToTryCount[tabId]; if ( entry.count === 1 ) { return false; }
}; entry.count -= 1;
tabIdToTimer.set(
var tryAgain = function(tabId) { entry.tabId,
var count = tabIdToTryCount[tabId]; vAPI.setTimeout(updateTitle.bind(null, entry), delay)
if ( count === undefined ) { );
return false;
}
if ( count === 1 ) {
delete tabIdToTryCount[tabId];
return false;
}
tabIdToTryCount[tabId] = count - 1;
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(µb, tabId), delay);
return true; return true;
}; };
var onTabReady = function(tabId, tab) { var onTabReady = function(entry, tab) {
if ( !tab ) { if ( !tab ) { return; }
return tryNoMore(tabId); var µb = µBlock;
} var pageStore = µb.pageStoreFromTabId(entry.tabId);
var pageStore = this.pageStoreFromTabId(tabId); if ( pageStore === null ) { return; }
if ( pageStore === null ) {
return tryNoMore(tabId);
}
// Firefox needs this: if you detach a tab, the new tab won't have // Firefox needs this: if you detach a tab, the new tab won't have
// its rawURL set. Concretely, this causes the logger to report an // its rawURL set. Concretely, this causes the logger to report an
// entry to itself in the logger's tab selector. // entry to itself in the logger's tab selector.
// TODO: Investigate for a fix vAPI-side. // TODO: Investigate for a fix vAPI-side.
pageStore.rawURL = tab.url; pageStore.rawURL = tab.url;
this.pageStoresToken = Date.now(); µb.pageStoresToken = Date.now();
if ( !tab.title && tryAgain(tabId) ) { if ( !tab.title && tryAgain(entry) ) { return; }
return;
}
// https://github.com/gorhill/uMatrix/issues/225 // https://github.com/gorhill/uMatrix/issues/225
// Sometimes title changes while page is loading. // Sometimes title changes while page is loading.
var settled = tab.title && tab.title === pageStore.title; var settled = tab.title && tab.title === pageStore.title;
pageStore.title = tab.title || tab.url || ''; pageStore.title = tab.title || tab.url || '';
this.pageStoresToken = Date.now(); if ( !settled ) {
if ( settled || !tryAgain(tabId) ) { tryAgain(entry);
tryNoMore(tabId);
} }
}; };
var updateTitle = function(tabId) { var updateTitle = function(entry) {
delete tabIdToTimer[tabId]; tabIdToTimer.delete(entry.tabId);
vAPI.tabs.get(tabId, onTabReady.bind(this, tabId)); vAPI.tabs.get(entry.tabId, onTabReady.bind(null, entry));
}; };
return function(tabId) { return function(tabId) {
if ( vAPI.isBehindTheSceneTabId(tabId) ) { if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
return; var timer = tabIdToTimer.get(tabId);
if ( timer !== undefined ) {
clearTimeout(timer);
} }
if ( tabIdToTimer[tabId] ) { tabIdToTimer.set(
clearTimeout(tabIdToTimer[tabId]); tabId,
} vAPI.setTimeout(
tabIdToTimer[tabId] = vAPI.setTimeout(updateTitle.bind(this, tabId), delay); updateTitle.bind(null, { tabId: tabId, count: 5 }),
tabIdToTryCount[tabId] = 5; delay
)
);
}; };
})(); })();
@ -1018,11 +1016,10 @@ var pageStoreJanitorSampleSize = 10;
var pageStoreJanitor = function() { var pageStoreJanitor = function() {
var vapiTabs = vAPI.tabs; var vapiTabs = vAPI.tabs;
var tabIds = Object.keys(µb.pageStores).sort(); var tabIds = Array.from(µb.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 ) {
//console.error('tab.js> pageStoreJanitor(): stale page store found:', µtabId);
µb.unbindTabFromPageStats(tabId); µb.unbindTabFromPageStats(tabId);
} }
}); });
@ -1030,14 +1027,10 @@ var pageStoreJanitor = function() {
if ( pageStoreJanitorSampleAt >= tabIds.length ) { if ( pageStoreJanitorSampleAt >= tabIds.length ) {
pageStoreJanitorSampleAt = 0; pageStoreJanitorSampleAt = 0;
} }
var tabId;
var n = Math.min(pageStoreJanitorSampleAt + pageStoreJanitorSampleSize, tabIds.length); var n = Math.min(pageStoreJanitorSampleAt + pageStoreJanitorSampleSize, tabIds.length);
for ( var i = pageStoreJanitorSampleAt; i < n; i++ ) { for ( var i = pageStoreJanitorSampleAt; i < n; i++ ) {
tabId = tabIds[i]; var tabId = tabIds[i];
// Do not remove behind-the-scene page store if ( vAPI.isBehindTheSceneTabId(tabId) ) { continue; }
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
continue;
}
checkTab(tabId); checkTab(tabId);
} }
pageStoreJanitorSampleAt = n; pageStoreJanitorSampleAt = n;

View File

@ -336,8 +336,8 @@ var toBlockDocResult = function(url, hostname, logData) {
var onBeforeBehindTheSceneRequest = function(details) { var onBeforeBehindTheSceneRequest = function(details) {
var µb = µBlock, var µb = µBlock,
pageStore = µb.pageStoreFromTabId(vAPI.noTabId); pageStore = µb.pageStoreFromTabId(details.tabId);
if ( !pageStore ) { return; } if ( pageStore === null ) { return; }
var result = 0, var result = 0,
context = pageStore.createContextFromPage(), context = pageStore.createContextFromPage(),
@ -348,6 +348,13 @@ var onBeforeBehindTheSceneRequest = function(details) {
context.requestHostname = µb.URI.hostnameFromURI(requestURL); context.requestHostname = µb.URI.hostnameFromURI(requestURL);
context.requestType = requestType; context.requestType = requestType;
if ( details.tabId === vAPI.anyTabId && context.pageHostname === '' ) {
context.pageHostname = µb.URI.hostnameFromURI(details.documentUrl);
context.pageDomain = µb.URI.domainFromHostname(context.pageHostname);
context.rootHostname = context.pageHostname;
context.rootDomain = context.pageDomain;
}
// https://bugs.chromium.org/p/chromium/issues/detail?id=637577#c15 // https://bugs.chromium.org/p/chromium/issues/detail?id=637577#c15
// Do not filter behind-the-scene network request of type `beacon`: there // Do not filter behind-the-scene network request of type `beacon`: there
// is no point. In any case, this will become a non-issue once // is no point. In any case, this will become a non-issue once
@ -361,7 +368,11 @@ var onBeforeBehindTheSceneRequest = function(details) {
// https://github.com/gorhill/uBlock/issues/3150 // https://github.com/gorhill/uBlock/issues/3150
// Ability to globally block CSP reports MUST also apply to // Ability to globally block CSP reports MUST also apply to
// behind-the-scene network requests. // behind-the-scene network requests.
if ( µb.userSettings.advancedUserEnabled || requestType === 'csp_report' ) { if (
details.tabId !== vAPI.noTabId ||
µb.userSettings.advancedUserEnabled ||
requestType === 'csp_report'
) {
result = pageStore.filterRequest(context); result = pageStore.filterRequest(context);
} }
@ -369,7 +380,7 @@ var onBeforeBehindTheSceneRequest = function(details) {
if ( µb.logger.isEnabled() ) { if ( µb.logger.isEnabled() ) {
µb.logger.writeOne( µb.logger.writeOne(
vAPI.noTabId, details.tabId,
'net', 'net',
pageStore.logData, pageStore.logData,
requestType, requestType,

View File

@ -1,7 +1,7 @@
/******************************************************************************* /*******************************************************************************
uBlock Origin - a browser extension to block requests. uBlock Origin - a browser extension to block 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
@ -510,20 +510,18 @@ var reInvalidHostname = /[^a-z0-9.\-\[\]:]/,
/******************************************************************************/ /******************************************************************************/
µBlock.logCosmeticFilters = (function() { µBlock.logCosmeticFilters = (function() {
var tabIdToTimerMap = {}; var tabIdToTimerMap = new Map();
var injectNow = function(tabId) { var injectNow = function(tabId) {
delete tabIdToTimerMap[tabId]; tabIdToTimerMap.delete(tabId);
µBlock.scriptlets.injectDeep(tabId, 'cosmetic-logger'); µBlock.scriptlets.injectDeep(tabId, 'cosmetic-logger');
}; };
var injectAsync = function(tabId) { var injectAsync = function(tabId) {
if ( tabIdToTimerMap.hasOwnProperty(tabId) ) { if ( tabIdToTimerMap.has(tabId) ) { return; }
return; tabIdToTimerMap.set(
} tabId,
tabIdToTimerMap[tabId] = vAPI.setTimeout( vAPI.setTimeout(injectNow.bind(null, tabId), 100)
injectNow.bind(null, tabId),
100
); );
}; };