mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +01:00
parent
64682ab8a1
commit
2c901588c7
12 changed files with 191 additions and 188 deletions
|
@ -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) {
|
||||
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) {
|
||||
if ( typeof tabId === 'string' ) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
}
|
||||
if ( typeof tabId === 'string' ) { debugger; }
|
||||
if ( typeof tabId !== 'number' || isNaN(tabId) || tabId === -1 ) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -329,8 +340,8 @@ vAPI.tabs.registerListeners = function() {
|
|||
}
|
||||
if ( typeof vAPI.tabs.onPopupCreated === 'function' ) {
|
||||
vAPI.tabs.onPopupCreated(
|
||||
details.tabId.toString(),
|
||||
details.sourceTabId.toString()
|
||||
details.tabId,
|
||||
details.sourceTabId
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -364,7 +375,7 @@ vAPI.tabs.registerListeners = function() {
|
|||
if ( changeInfo.url ) {
|
||||
changeInfo.url = sanitizeURL(changeInfo.url);
|
||||
}
|
||||
onUpdatedClient(tabId.toString(), changeInfo, tab);
|
||||
onUpdatedClient(tabId, changeInfo, tab);
|
||||
};
|
||||
|
||||
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
|
||||
|
@ -542,9 +553,7 @@ vAPI.tabs.open = function(details) {
|
|||
|
||||
vAPI.tabs.replace = function(tabId, url) {
|
||||
tabId = toChromiumTabId(tabId);
|
||||
if ( tabId === 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( tabId === 0 ) { return; }
|
||||
|
||||
var targetURL = url;
|
||||
|
||||
|
@ -565,9 +574,7 @@ vAPI.tabs.replace = function(tabId, url) {
|
|||
|
||||
vAPI.tabs.remove = function(tabId) {
|
||||
tabId = toChromiumTabId(tabId);
|
||||
if ( tabId === 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( tabId === 0 ) { return; }
|
||||
|
||||
var onTabRemoved = function() {
|
||||
// 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) {
|
||||
tabId = toChromiumTabId(tabId);
|
||||
if ( tabId === 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( tabId === 0 ) { return; }
|
||||
|
||||
chrome.tabs.update(tabId, { active: true }, function(tab) {
|
||||
if ( chrome.runtime.lastError ) {
|
||||
|
@ -789,7 +794,7 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
case 'connectionRefused':
|
||||
toPort = messaging.ports.get(msg.fromToken);
|
||||
if ( toPort !== undefined ) {
|
||||
msg.tabId = tabId && tabId.toString();
|
||||
msg.tabId = tabId;
|
||||
toPort.postMessage(request);
|
||||
} else {
|
||||
msg.what = 'connectionBroken';
|
||||
|
@ -797,7 +802,7 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
}
|
||||
break;
|
||||
case 'connectionRequested':
|
||||
msg.tabId = tabId && tabId.toString();
|
||||
msg.tabId = tabId;
|
||||
for ( toPort of messaging.ports.values() ) {
|
||||
toPort.postMessage(request);
|
||||
}
|
||||
|
@ -809,7 +814,7 @@ vAPI.messaging.onPortMessage = (function() {
|
|||
port.name === msg.fromToken ? msg.toToken : msg.fromToken
|
||||
);
|
||||
if ( toPort !== undefined ) {
|
||||
msg.tabId = tabId && tabId.toString();
|
||||
msg.tabId = tabId;
|
||||
toPort.postMessage(request);
|
||||
} else {
|
||||
msg.what = 'connectionBroken';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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) {
|
||||
details.tabId = details.tabId.toString();
|
||||
|
||||
var type = details.type;
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1493
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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) {
|
||||
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);
|
||||
if ( tabId === undefined ) {
|
||||
tabId = '' + tabIdGenerator++;
|
||||
tabId = tabIdGenerator++;
|
||||
browserToTabIdMap.set(browser, tabId);
|
||||
tabIdToBrowserMap.set(tabId, Cu.getWeakReference(browser));
|
||||
}
|
||||
|
@ -1316,7 +1317,7 @@ var tabWatcher = (function() {
|
|||
var removeBrowserEntry = function(tabId, browser) {
|
||||
if ( tabId && tabId !== vAPI.noTabId ) {
|
||||
vAPI.tabs.onClosed(tabId);
|
||||
delete vAPI.toolbarButton.tabs[tabId];
|
||||
vAPI.toolbarButton.tabs.delete(tabId);
|
||||
tabIdToBrowserMap.delete(tabId);
|
||||
}
|
||||
if ( browser ) {
|
||||
|
@ -1539,7 +1540,7 @@ vAPI.setIcon = function(tabId, iconStatus, badge) {
|
|||
if ( tabId === undefined ) {
|
||||
tabId = curTabId;
|
||||
} 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 ) {
|
||||
|
@ -2028,7 +2029,7 @@ var httpObserver = {
|
|||
},
|
||||
|
||||
// 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) {
|
||||
var type = this.typeMap[details.rawtype] || 'other';
|
||||
|
@ -2437,7 +2438,7 @@ vAPI.toolbarButton = {
|
|||
viewId: location.host + '-panel',
|
||||
label: vAPI.app.name,
|
||||
tooltiptext: vAPI.app.name,
|
||||
tabs: {/*tabId: {badge: 0, img: boolean}*/},
|
||||
tabs: new Map(/* tabId: { badge: 0, img: boolean } */),
|
||||
init: null,
|
||||
codePath: ''
|
||||
};
|
||||
|
@ -2473,8 +2474,8 @@ vAPI.toolbarButton = {
|
|||
if ( tabId === undefined ) {
|
||||
return label;
|
||||
}
|
||||
var tabDetails = this.tabs[tabId];
|
||||
if ( !tabDetails ) {
|
||||
var tabDetails = this.tabs.get(tabId);
|
||||
if ( tabDetails === undefined ) {
|
||||
return label;
|
||||
}
|
||||
if ( !tabDetails.img ) {
|
||||
|
@ -2563,7 +2564,7 @@ vAPI.toolbarButton = {
|
|||
return;
|
||||
}
|
||||
|
||||
var icon = this.tabs[tabId];
|
||||
var icon = this.tabs.get(tabId);
|
||||
|
||||
button.setAttribute('badge', icon && icon.badge || '');
|
||||
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
|
||||
// should collect on its side all the opened tabs whenever it is ready.
|
||||
var µb = µBlock;
|
||||
var tabId;
|
||||
for ( var browser of tabWatcher.browsers() ) {
|
||||
tabId = tabWatcher.tabIdFromTarget(browser);
|
||||
var tabId = tabWatcher.tabIdFromTarget(browser);
|
||||
µb.tabContextManager.commit(tabId, browser.currentURI.asciiSpec);
|
||||
µb.bindTabToPageStats(tabId);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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 reAsciiHostname = /^https?:\/\/[0-9a-z_.:@-]+[/?#]/;
|
||||
var reNetworkURI = /^(?:ftps?|https?|wss?)/;
|
||||
var parsedURL = new URL('about:blank');
|
||||
|
||||
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) ) {
|
||||
parsedURL.href = details.url;
|
||||
|
|
|
@ -148,7 +148,7 @@ var µBlock = (function() { // jshint ignore:line
|
|||
|
||||
selfieAfter: 17 * oneMinute,
|
||||
|
||||
pageStores: {},
|
||||
pageStores: new Map(),
|
||||
pageStoresToken: 0,
|
||||
|
||||
storageQuota: vAPI.storage.QUOTA_BYTES,
|
||||
|
|
|
@ -45,7 +45,7 @@ if (
|
|||
|
||||
var logger = self.logger;
|
||||
var inspectorConnectionId;
|
||||
var inspectedTabId = '';
|
||||
var inspectedTabId = 0;
|
||||
var inspectedURL = '';
|
||||
var inspectedHostname = '';
|
||||
var inspector = uDom.nodeFromId('domInspector');
|
||||
|
@ -468,7 +468,7 @@ var startDialog = (function() {
|
|||
var onClicked = function(ev) {
|
||||
ev.stopPropagation();
|
||||
|
||||
if ( inspectedTabId === '' ) { return; }
|
||||
if ( inspectedTabId === 0 ) { return; }
|
||||
|
||||
var target = ev.target;
|
||||
var parent = target.parentElement;
|
||||
|
@ -540,7 +540,7 @@ var onMouseOver = (function() {
|
|||
};
|
||||
|
||||
return function(ev) {
|
||||
if ( inspectedTabId === '' ) { return; }
|
||||
if ( inspectedTabId === 0 ) { return; }
|
||||
// Convenience: skip real-time highlighting if shift key is pressed.
|
||||
if ( ev.shiftKey ) { return; }
|
||||
// Find closest `li`
|
||||
|
@ -560,7 +560,7 @@ var onMouseOver = (function() {
|
|||
/******************************************************************************/
|
||||
|
||||
var currentTabId = function() {
|
||||
if ( showdomButton.classList.contains('active') === false ) { return ''; }
|
||||
if ( showdomButton.classList.contains('active') === false ) { return 0; }
|
||||
return logger.tabIdFromPageSelector();
|
||||
};
|
||||
|
||||
|
@ -568,7 +568,7 @@ var currentTabId = function() {
|
|||
|
||||
var injectInspector = function() {
|
||||
var tabId = currentTabId();
|
||||
if ( tabId === '' ) { return; }
|
||||
if ( tabId === 0 ) { return; }
|
||||
inspectedTabId = tabId;
|
||||
messaging.send('loggerUI', {
|
||||
what: 'scriptlet',
|
||||
|
@ -586,7 +586,7 @@ var shutdownInspector = function() {
|
|||
}
|
||||
logger.removeAllChildren(domTree);
|
||||
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 .revert').removeEventListener('click', revert);
|
||||
uDom.nodeFromSelector('#domInspector .permatoolbar .commit').removeEventListener('click', startDialog);
|
||||
inspectedTabId = '';
|
||||
inspectedTabId = 0;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -56,7 +56,7 @@ var tabIdFromPageSelector = logger.tabIdFromPageSelector = function() {
|
|||
if ( tabClass === 'tab_active' && activeTabId !== undefined ) {
|
||||
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 lastVarDataIndex = 4; // currently, d0-d3
|
||||
var maxEntries = 5000;
|
||||
var noTabId = '';
|
||||
var allTabIds = {};
|
||||
var allTabIds = new Map();
|
||||
var allTabIdsToken;
|
||||
var hiddenTemplate = document.querySelector('#hiddenTemplate > span');
|
||||
var reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/;
|
||||
|
@ -113,7 +112,7 @@ var staticFilterTypes = {
|
|||
/******************************************************************************/
|
||||
|
||||
var classNameFromTabId = function(tabId) {
|
||||
if ( tabId === noTabId ) {
|
||||
if ( tabId < 0 ) {
|
||||
return 'tab_bts';
|
||||
}
|
||||
if ( tabId !== '' ) {
|
||||
|
@ -353,7 +352,7 @@ var renderLogEntry = function(entry) {
|
|||
if ( entry.tab ) {
|
||||
tr.classList.add('tab');
|
||||
tr.classList.add(classNameFromTabId(entry.tab));
|
||||
if ( entry.tab === noTabId ) {
|
||||
if ( entry.tab < 0 ) {
|
||||
tr.cells[1].appendChild(createHiddenTextNode('bts'));
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +391,7 @@ var renderLogEntries = function(response) {
|
|||
// https://github.com/gorhill/uBlock/issues/1613#issuecomment-217637122
|
||||
// Unlikely, but it may happen: mark as void if associated tab no
|
||||
// longer exist.
|
||||
if ( entry.tab && tabIds.hasOwnProperty(entry.tab) === false ) {
|
||||
if ( entry.tab && tabIds.has(entry.tab) === false ) {
|
||||
tr.classList.remove('canMtx');
|
||||
}
|
||||
}
|
||||
|
@ -422,9 +421,8 @@ var synchronizeTabIds = function(newTabIds) {
|
|||
var oldTabIds = allTabIds;
|
||||
var autoDeleteVoidRows = selectValue === 'tab_active';
|
||||
var rowVoided = false;
|
||||
for ( var tabId in oldTabIds ) {
|
||||
if ( oldTabIds.hasOwnProperty(tabId) === false ) { continue; }
|
||||
if ( newTabIds.hasOwnProperty(tabId) ) { continue; }
|
||||
for ( var tabId of oldTabIds.keys() ) {
|
||||
if ( newTabIds.has(tabId) ) { continue; }
|
||||
// Mark or remove voided rows
|
||||
var trs = uDom('.tab_' + tabId);
|
||||
if ( autoDeleteVoidRows ) {
|
||||
|
@ -439,20 +437,20 @@ var synchronizeTabIds = function(newTabIds) {
|
|||
}
|
||||
}
|
||||
|
||||
var tabIds = Object.keys(newTabIds).sort(function(a, b) {
|
||||
return newTabIds[a].localeCompare(newTabIds[b]);
|
||||
var tabIds = Array.from(newTabIds.keys()).sort(function(a, b) {
|
||||
return newTabIds.get(a).localeCompare(newTabIds.get(b));
|
||||
});
|
||||
var option;
|
||||
for ( var i = 0, j = 3; i < tabIds.length; i++ ) {
|
||||
tabId = tabIds[i];
|
||||
if ( tabId === noTabId ) { continue; }
|
||||
if ( tabId < 0 ) { continue; }
|
||||
option = select.options[j];
|
||||
if ( !option ) {
|
||||
option = document.createElement('option');
|
||||
select.appendChild(option);
|
||||
}
|
||||
// Truncate too long labels.
|
||||
option.textContent = newTabIds[tabId].slice(0, 80);
|
||||
option.textContent = newTabIds.get(tabId).slice(0, 80);
|
||||
option.value = classNameFromTabId(tabId);
|
||||
if ( option.value === selectValue ) {
|
||||
select.selectedIndex = j;
|
||||
|
@ -500,14 +498,15 @@ var onLogBufferRead = function(response) {
|
|||
return;
|
||||
}
|
||||
|
||||
// This tells us the behind-the-scene tab id
|
||||
noTabId = response.noTabId;
|
||||
|
||||
// Tab id of currently active tab
|
||||
if ( response.activeTabId ) {
|
||||
activeTabId = response.activeTabId;
|
||||
}
|
||||
|
||||
if ( Array.isArray(response.tabIds) ) {
|
||||
response.tabIds = new Map(response.tabIds);
|
||||
}
|
||||
|
||||
// This may have changed meanwhile
|
||||
if ( response.maxEntries !== maxEntries ) {
|
||||
maxEntries = response.maxEntries;
|
||||
|
@ -625,7 +624,7 @@ var pageSelectorFromURLHash = (function() {
|
|||
|
||||
var reloadTab = function(ev) {
|
||||
var tabId = tabIdFromPageSelector();
|
||||
if ( tabId === '' ) { return; }
|
||||
if ( tabId === 0 ) { return; }
|
||||
messaging.send('loggerUI', {
|
||||
what: 'reloadTab',
|
||||
tabId: tabId,
|
||||
|
@ -965,7 +964,7 @@ var netFilteringManager = (function() {
|
|||
// First, whether picker can be used
|
||||
dialog.querySelector('.picker').classList.toggle(
|
||||
'hide',
|
||||
targetTabId === noTabId ||
|
||||
targetTabId < 0 ||
|
||||
targetType !== 'image' ||
|
||||
/(?:^| )[dlsu]b(?: |$)/.test(targetRow.className)
|
||||
);
|
||||
|
@ -1614,7 +1613,7 @@ var popupManager = (function() {
|
|||
return;
|
||||
}
|
||||
if ( localTabId === 'bts' ) {
|
||||
realTabId = noTabId;
|
||||
realTabId = -1;
|
||||
}
|
||||
|
||||
container = uDom.nodeFromId('popupContainer');
|
||||
|
|
|
@ -1022,28 +1022,26 @@ vAPI.messaging.listen('dashboard', onMessage);
|
|||
/******************************************************************************/
|
||||
|
||||
var µb = µBlock,
|
||||
extensionPageURL = vAPI.getURL('');
|
||||
extensionOriginURL = vAPI.getURL('');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var getLoggerData = function(ownerId, activeTabId, callback) {
|
||||
var tabIds = {};
|
||||
for ( var tabId in µb.pageStores ) {
|
||||
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||
if ( pageStore === null ) { continue; }
|
||||
if ( pageStore.rawURL.startsWith(extensionPageURL) ) { continue; }
|
||||
tabIds[tabId] = pageStore.title;
|
||||
var tabIds = new Map();
|
||||
for ( var entry of µb.pageStores ) {
|
||||
var pageStore = entry[1];
|
||||
if ( pageStore.rawURL.startsWith(extensionOriginURL) ) { continue; }
|
||||
tabIds.set(entry[0], pageStore.title);
|
||||
}
|
||||
if ( activeTabId && tabIds.hasOwnProperty(activeTabId) === false ) {
|
||||
if ( activeTabId && tabIds.has(activeTabId) === false ) {
|
||||
activeTabId = undefined;
|
||||
}
|
||||
callback({
|
||||
colorBlind: µb.userSettings.colorBlindFriendly,
|
||||
entries: µb.logger.readAll(ownerId),
|
||||
maxEntries: µb.userSettings.requestLogMaxEntries,
|
||||
noTabId: vAPI.noTabId,
|
||||
activeTabId: activeTabId,
|
||||
tabIds: tabIds,
|
||||
tabIds: Array.from(tabIds),
|
||||
tabIdsToken: µb.pageStoresToken
|
||||
});
|
||||
};
|
||||
|
@ -1093,11 +1091,7 @@ var onMessage = function(request, sender, callback) {
|
|||
return;
|
||||
}
|
||||
vAPI.tabs.get(null, function(tab) {
|
||||
getLoggerData(
|
||||
request.ownerId,
|
||||
tab && tab.id.toString(),
|
||||
callback
|
||||
);
|
||||
getLoggerData(request.ownerId, tab && tab.id, callback);
|
||||
});
|
||||
return;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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.hostnameToCountMap = new Map();
|
||||
this.contentLastModified = 0;
|
||||
this.frames = Object.create(null);
|
||||
this.frames = new Map();
|
||||
this.logData = undefined;
|
||||
this.perLoadBlockedRequestCount = 0;
|
||||
this.perLoadAllowedRequestCount = 0;
|
||||
|
@ -410,27 +410,26 @@ PageStore.prototype.dispose = function() {
|
|||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.disposeFrameStores = function() {
|
||||
var frames = this.frames;
|
||||
for ( var k in frames ) {
|
||||
frames[k].dispose();
|
||||
for ( var frameStore of this.frames.values() ) {
|
||||
frameStore.dispose();
|
||||
}
|
||||
this.frames = Object.create(null);
|
||||
this.frames.clear();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.getFrame = function(frameId) {
|
||||
return this.frames[frameId] || null;
|
||||
return this.frames.get(frameId) || null;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
PageStore.prototype.setFrame = function(frameId, frameURL) {
|
||||
var frameStore = this.frames[frameId];
|
||||
if ( frameStore ) {
|
||||
var frameStore = this.frames.get(frameId);
|
||||
if ( frameStore !== undefined ) {
|
||||
frameStore.init(frameURL);
|
||||
} 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) {
|
||||
var context = µb.tabContextManager.createContext(this.tabId);
|
||||
var frameStore = this.frames[frameId];
|
||||
if ( frameStore ) {
|
||||
var frameStore = this.frames.get(frameId);
|
||||
if ( frameStore !== undefined ) {
|
||||
context.pageHostname = frameStore.pageHostname;
|
||||
context.pageDomain = frameStore.pageDomain;
|
||||
} else {
|
||||
|
|
159
src/js/tab.js
159
src/js/tab.js
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -128,7 +128,7 @@ housekeep itself.
|
|||
*/
|
||||
|
||||
µb.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
|
||||
|
@ -206,7 +206,7 @@ housekeep itself.
|
|||
};
|
||||
|
||||
var TabContext = function(tabId) {
|
||||
this.tabId = tabId.toString();
|
||||
this.tabId = tabId;
|
||||
this.stack = [];
|
||||
this.rawURL =
|
||||
this.normalURL =
|
||||
|
@ -218,18 +218,16 @@ housekeep itself.
|
|||
this.netFiltering = true;
|
||||
this.netFilteringReadTime = 0;
|
||||
|
||||
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) {
|
||||
|
@ -363,7 +361,7 @@ housekeep itself.
|
|||
// These are to be used for the API of the tab context manager.
|
||||
|
||||
var push = function(tabId, url) {
|
||||
var entry = tabContexts[tabId];
|
||||
var entry = tabContexts.get(tabId);
|
||||
if ( entry === undefined ) {
|
||||
entry = new TabContext(tabId);
|
||||
entry.autodestroy();
|
||||
|
@ -376,13 +374,13 @@ housekeep itself.
|
|||
|
||||
// Find a tab context for a specific tab.
|
||||
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
|
||||
// fix this. When all fail, the behind-the-scene context is returned.
|
||||
var mustLookup = function(tabId) {
|
||||
var entry = tabContexts[tabId];
|
||||
var entry = tabContexts.get(tabId);
|
||||
if ( entry !== undefined ) {
|
||||
return entry;
|
||||
}
|
||||
|
@ -407,13 +405,13 @@ 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);
|
||||
};
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1735
|
||||
// Filter for popups if actually committing.
|
||||
var commit = function(tabId, url) {
|
||||
var entry = tabContexts[tabId];
|
||||
var entry = tabContexts.get(tabId);
|
||||
if ( entry === undefined ) {
|
||||
entry = push(tabId, url);
|
||||
} else if ( entry.commit(url) ) {
|
||||
|
@ -423,7 +421,7 @@ housekeep itself.
|
|||
};
|
||||
|
||||
var exists = function(tabId) {
|
||||
return tabContexts[tabId] !== undefined;
|
||||
return tabContexts.get(tabId) !== undefined;
|
||||
};
|
||||
|
||||
// Behind-the-scene tab context
|
||||
|
@ -434,6 +432,9 @@ housekeep itself.
|
|||
entry.normalURL = µb.normalizePageURL(entry.tabId);
|
||||
entry.rootHostname = µb.URI.hostnameFromURI(entry.normalURL);
|
||||
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.
|
||||
|
@ -445,7 +446,7 @@ housekeep itself.
|
|||
var tabContext = lookup(tabId);
|
||||
this.rootHostname = tabContext.rootHostname;
|
||||
this.rootDomain = tabContext.rootDomain;
|
||||
this.pageHostname =
|
||||
this.pageHostname =
|
||||
this.pageDomain =
|
||||
this.requestURL =
|
||||
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
|
||||
var pageStore = this.pageStores[tabId];
|
||||
var pageStore = this.pageStores.get(tabId);
|
||||
|
||||
// Tab is not bound
|
||||
if ( !pageStore ) {
|
||||
if ( pageStore === undefined ) {
|
||||
this.updateTitle(tabId);
|
||||
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
|
||||
|
@ -878,10 +881,10 @@ vAPI.tabs.registerListeners();
|
|||
|
||||
µb.unbindTabFromPageStats = function(tabId) {
|
||||
//console.debug('µBlock> unbindTabFromPageStats(%d)', tabId);
|
||||
var pageStore = this.pageStores[tabId];
|
||||
var pageStore = this.pageStores.get(tabId);
|
||||
if ( pageStore !== undefined ) {
|
||||
pageStore.dispose();
|
||||
delete this.pageStores[tabId];
|
||||
this.pageStores.delete(tabId);
|
||||
this.pageStoresToken = Date.now();
|
||||
}
|
||||
};
|
||||
|
@ -889,29 +892,36 @@ vAPI.tabs.registerListeners();
|
|||
/******************************************************************************/
|
||||
|
||||
µb.pageStoreFromTabId = function(tabId) {
|
||||
return this.pageStores[tabId] || null;
|
||||
return this.pageStores.get(tabId) || null;
|
||||
};
|
||||
|
||||
µ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.
|
||||
|
||||
µb.pageStores[vAPI.noTabId] = µb.PageStore.factory(vAPI.noTabId);
|
||||
µb.pageStores[vAPI.noTabId].title = vAPI.i18n('logBehindTheScene');
|
||||
(function() {
|
||||
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.
|
||||
|
||||
µb.updateBadgeAsync = (function() {
|
||||
var tabIdToTimer = Object.create(null);
|
||||
var tabIdToTimer = new Map();
|
||||
|
||||
var updateBadge = function(tabId) {
|
||||
delete tabIdToTimer[tabId];
|
||||
tabIdToTimer.delete(tabId);
|
||||
|
||||
var state = false;
|
||||
var badge = '';
|
||||
|
@ -928,82 +938,70 @@ vAPI.tabs.registerListeners();
|
|||
};
|
||||
|
||||
return function(tabId) {
|
||||
if ( tabIdToTimer[tabId] ) {
|
||||
return;
|
||||
}
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
return;
|
||||
}
|
||||
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 701);
|
||||
if ( tabIdToTimer.has(tabId) ) { return; }
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
|
||||
tabIdToTimer.set(
|
||||
tabId,
|
||||
vAPI.setTimeout(updateBadge.bind(this, tabId), 701)
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µb.updateTitle = (function() {
|
||||
var tabIdToTimer = Object.create(null);
|
||||
var tabIdToTryCount = Object.create(null);
|
||||
var tabIdToTimer = new Map();
|
||||
var delay = 499;
|
||||
|
||||
var tryNoMore = function(tabId) {
|
||||
delete tabIdToTryCount[tabId];
|
||||
};
|
||||
|
||||
var tryAgain = function(tabId) {
|
||||
var count = tabIdToTryCount[tabId];
|
||||
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);
|
||||
var tryAgain = function(entry) {
|
||||
if ( entry.count === 1 ) { return false; }
|
||||
entry.count -= 1;
|
||||
tabIdToTimer.set(
|
||||
entry.tabId,
|
||||
vAPI.setTimeout(updateTitle.bind(null, entry), delay)
|
||||
);
|
||||
return true;
|
||||
};
|
||||
|
||||
var onTabReady = function(tabId, tab) {
|
||||
if ( !tab ) {
|
||||
return tryNoMore(tabId);
|
||||
}
|
||||
var pageStore = this.pageStoreFromTabId(tabId);
|
||||
if ( pageStore === null ) {
|
||||
return tryNoMore(tabId);
|
||||
}
|
||||
var onTabReady = function(entry, tab) {
|
||||
if ( !tab ) { return; }
|
||||
var µb = µBlock;
|
||||
var pageStore = µb.pageStoreFromTabId(entry.tabId);
|
||||
if ( pageStore === null ) { return; }
|
||||
// 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
|
||||
// entry to itself in the logger's tab selector.
|
||||
// TODO: Investigate for a fix vAPI-side.
|
||||
pageStore.rawURL = tab.url;
|
||||
this.pageStoresToken = Date.now();
|
||||
if ( !tab.title && tryAgain(tabId) ) {
|
||||
return;
|
||||
}
|
||||
µb.pageStoresToken = Date.now();
|
||||
if ( !tab.title && tryAgain(entry) ) { return; }
|
||||
// https://github.com/gorhill/uMatrix/issues/225
|
||||
// Sometimes title changes while page is loading.
|
||||
var settled = tab.title && tab.title === pageStore.title;
|
||||
pageStore.title = tab.title || tab.url || '';
|
||||
this.pageStoresToken = Date.now();
|
||||
if ( settled || !tryAgain(tabId) ) {
|
||||
tryNoMore(tabId);
|
||||
if ( !settled ) {
|
||||
tryAgain(entry);
|
||||
}
|
||||
};
|
||||
|
||||
var updateTitle = function(tabId) {
|
||||
delete tabIdToTimer[tabId];
|
||||
vAPI.tabs.get(tabId, onTabReady.bind(this, tabId));
|
||||
var updateTitle = function(entry) {
|
||||
tabIdToTimer.delete(entry.tabId);
|
||||
vAPI.tabs.get(entry.tabId, onTabReady.bind(null, entry));
|
||||
};
|
||||
|
||||
return function(tabId) {
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
return;
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
|
||||
var 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(null, { tabId: tabId, count: 5 }),
|
||||
delay
|
||||
)
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -1018,11 +1016,10 @@ var pageStoreJanitorSampleSize = 10;
|
|||
|
||||
var pageStoreJanitor = function() {
|
||||
var vapiTabs = vAPI.tabs;
|
||||
var tabIds = Object.keys(µb.pageStores).sort();
|
||||
var tabIds = Array.from(µb.pageStores.keys()).sort();
|
||||
var checkTab = function(tabId) {
|
||||
vapiTabs.get(tabId, function(tab) {
|
||||
if ( !tab ) {
|
||||
//console.error('tab.js> pageStoreJanitor(): stale page store found:', µtabId);
|
||||
µb.unbindTabFromPageStats(tabId);
|
||||
}
|
||||
});
|
||||
|
@ -1030,14 +1027,10 @@ var pageStoreJanitor = function() {
|
|||
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
|
||||
pageStoreJanitorSampleAt = 0;
|
||||
}
|
||||
var tabId;
|
||||
var n = Math.min(pageStoreJanitorSampleAt + pageStoreJanitorSampleSize, tabIds.length);
|
||||
for ( var i = pageStoreJanitorSampleAt; i < n; i++ ) {
|
||||
tabId = tabIds[i];
|
||||
// Do not remove behind-the-scene page store
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||
continue;
|
||||
}
|
||||
var tabId = tabIds[i];
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { continue; }
|
||||
checkTab(tabId);
|
||||
}
|
||||
pageStoreJanitorSampleAt = n;
|
||||
|
|
|
@ -336,8 +336,8 @@ var toBlockDocResult = function(url, hostname, logData) {
|
|||
|
||||
var onBeforeBehindTheSceneRequest = function(details) {
|
||||
var µb = µBlock,
|
||||
pageStore = µb.pageStoreFromTabId(vAPI.noTabId);
|
||||
if ( !pageStore ) { return; }
|
||||
pageStore = µb.pageStoreFromTabId(details.tabId);
|
||||
if ( pageStore === null ) { return; }
|
||||
|
||||
var result = 0,
|
||||
context = pageStore.createContextFromPage(),
|
||||
|
@ -348,6 +348,13 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
|||
context.requestHostname = µb.URI.hostnameFromURI(requestURL);
|
||||
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
|
||||
// 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
|
||||
|
@ -361,7 +368,11 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
|||
// https://github.com/gorhill/uBlock/issues/3150
|
||||
// Ability to globally block CSP reports MUST also apply to
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@ -369,7 +380,7 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
|||
|
||||
if ( µb.logger.isEnabled() ) {
|
||||
µb.logger.writeOne(
|
||||
vAPI.noTabId,
|
||||
details.tabId,
|
||||
'net',
|
||||
pageStore.logData,
|
||||
requestType,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
|
||||
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
|
||||
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() {
|
||||
var tabIdToTimerMap = {};
|
||||
var tabIdToTimerMap = new Map();
|
||||
|
||||
var injectNow = function(tabId) {
|
||||
delete tabIdToTimerMap[tabId];
|
||||
tabIdToTimerMap.delete(tabId);
|
||||
µBlock.scriptlets.injectDeep(tabId, 'cosmetic-logger');
|
||||
};
|
||||
|
||||
var injectAsync = function(tabId) {
|
||||
if ( tabIdToTimerMap.hasOwnProperty(tabId) ) {
|
||||
return;
|
||||
}
|
||||
tabIdToTimerMap[tabId] = vAPI.setTimeout(
|
||||
injectNow.bind(null, tabId),
|
||||
100
|
||||
if ( tabIdToTimerMap.has(tabId) ) { return; }
|
||||
tabIdToTimerMap.set(
|
||||
tabId,
|
||||
vAPI.setTimeout(injectNow.bind(null, tabId), 100)
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue