mirror of https://github.com/gorhill/uBlock.git
Mind discarded status of tabs when internally handling them
Related discussion: - https://bugzilla.mozilla.org/show_bug.cgi?id=1652925#c19 Content scripts should not be injected in discarded tabs, and a discarded tab should treated as if it does not exist.
This commit is contained in:
parent
3b46b2532d
commit
aed850978e
|
@ -52,38 +52,45 @@ vAPI.app.onShutdown = function() {
|
|||
// the extension was launched. It can be used to inject content scripts
|
||||
// in already opened web pages, to remove whatever nuisance could make it to
|
||||
// the web pages before uBlock was ready.
|
||||
//
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1652925#c19
|
||||
// Mind discarded tabs.
|
||||
|
||||
const initializeTabs = async function() {
|
||||
const manifest = browser.runtime.getManifest();
|
||||
if ( manifest instanceof Object === false ) { return; }
|
||||
|
||||
const tabs = await vAPI.tabs.query({ url: '<all_urls>' });
|
||||
const toCheck = [];
|
||||
const checker = {
|
||||
file: 'js/scriptlets/should-inject-contentscript.js'
|
||||
};
|
||||
for ( const tab of tabs ) {
|
||||
µb.tabContextManager.commit(tab.id, tab.url);
|
||||
µb.bindTabToPageStats(tab.id);
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/129
|
||||
// Find out whether content scripts need to be injected
|
||||
// programmatically. This may be necessary for web pages which
|
||||
// were loaded before uBO launched.
|
||||
toCheck.push(
|
||||
/^https?:\/\//.test(tab.url)
|
||||
? vAPI.tabs.executeScript(tab.id, checker)
|
||||
: false
|
||||
);
|
||||
const tabIds = [];
|
||||
{
|
||||
const checker = { file: 'js/scriptlets/should-inject-contentscript.js' };
|
||||
const tabs = await vAPI.tabs.query({ url: '<all_urls>' });
|
||||
for ( const tab of tabs ) {
|
||||
if ( tab.discarded === true ) { continue; }
|
||||
const { id, url } = tab;
|
||||
µb.tabContextManager.commit(id, url);
|
||||
µb.bindTabToPageStats(id);
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/129
|
||||
// Find out whether content scripts need to be injected
|
||||
// programmatically. This may be necessary for web pages which
|
||||
// were loaded before uBO launched.
|
||||
toCheck.push(
|
||||
/^https?:\/\//.test(url)
|
||||
? vAPI.tabs.executeScript(id, checker)
|
||||
.then(result => result, ( ) => false)
|
||||
: false
|
||||
);
|
||||
tabIds.push(id);
|
||||
}
|
||||
}
|
||||
const results = await Promise.all(toCheck);
|
||||
for ( let i = 0; i < results.length; i++ ) {
|
||||
const result = results[i];
|
||||
if ( result.length === 0 || result[0] !== true ) { continue; }
|
||||
// Inject dclarative content scripts programmatically.
|
||||
const tabId = tabs[i].id;
|
||||
// Inject declarative content scripts programmatically.
|
||||
for ( const contentScript of manifest.content_scripts ) {
|
||||
for ( const file of contentScript.js ) {
|
||||
vAPI.tabs.executeScript(tabId, {
|
||||
vAPI.tabs.executeScript(tabIds[i], {
|
||||
file: file,
|
||||
allFrames: contentScript.all_frames,
|
||||
runAt: contentScript.run_at
|
||||
|
|
|
@ -577,26 +577,22 @@ housekeep itself.
|
|||
tabContexts.delete(this.tabId);
|
||||
};
|
||||
|
||||
TabContext.prototype.onTab = function(tab) {
|
||||
if ( tab ) {
|
||||
this.gcTimer = vAPI.setTimeout(( ) => this.onGC(), gcPeriod);
|
||||
} else {
|
||||
this.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
TabContext.prototype.onGC = async function() {
|
||||
if ( vAPI.isBehindTheSceneTabId(this.tabId) ) { return; }
|
||||
// https://github.com/gorhill/uBlock/issues/1713
|
||||
// For unknown reasons, Firefox's setTimeout() will sometimes
|
||||
// causes the callback function to be called immediately, bypassing
|
||||
// the main event loop. For now this should prevent uBO from crashing
|
||||
// as a result of the bad setTimeout() behavior.
|
||||
// For unknown reasons, Firefox's setTimeout() will sometimes
|
||||
// causes the callback function to be called immediately, bypassing
|
||||
// the main event loop. For now this should prevent uBO from
|
||||
// crashing as a result of the bad setTimeout() behavior.
|
||||
if ( this.onGCBarrier ) { return; }
|
||||
this.onGCBarrier = true;
|
||||
this.gcTimer = null;
|
||||
const tab = await vAPI.tabs.get(this.tabId);
|
||||
this.onTab(tab);
|
||||
if ( tab instanceof Object === false || tab.discarded === true ) {
|
||||
this.destroy();
|
||||
} else {
|
||||
this.gcTimer = vAPI.setTimeout(( ) => this.onGC(), gcPeriod);
|
||||
}
|
||||
this.onGCBarrier = false;
|
||||
};
|
||||
|
||||
|
@ -1074,23 +1070,19 @@ vAPI.tabs = new vAPI.Tabs();
|
|||
/******************************************************************************/
|
||||
|
||||
µBlock.updateTitle = (( ) => {
|
||||
const tabIdToTimer = new Map();
|
||||
const tabIdToCount = new Map();
|
||||
const delay = 499;
|
||||
|
||||
const tryAgain = function(entry) {
|
||||
if ( entry.count === 1 ) { return false; }
|
||||
entry.count -= 1;
|
||||
tabIdToTimer.set(
|
||||
entry.tabId,
|
||||
vAPI.setTimeout(( ) => { updateTitle(entry); }, delay)
|
||||
);
|
||||
return true;
|
||||
};
|
||||
|
||||
const onTabReady = function(entry, tab) {
|
||||
if ( !tab ) { return; }
|
||||
const updateTitle = async function(tabId) {
|
||||
let count = tabIdToCount.get(tabId);
|
||||
if ( count === undefined ) { return; }
|
||||
tabIdToCount.delete(tabId);
|
||||
const tab = await vAPI.tabs.get(tabId);
|
||||
if ( tab instanceof Object === false || tab.discarded === true ) {
|
||||
return;
|
||||
}
|
||||
const µb = µBlock;
|
||||
const pageStore = µb.pageStoreFromTabId(entry.tabId);
|
||||
const pageStore = µb.pageStoreFromTabId(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
|
||||
|
@ -1098,35 +1090,32 @@ vAPI.tabs = new vAPI.Tabs();
|
|||
// TODO: Investigate for a fix vAPI-side.
|
||||
pageStore.rawURL = tab.url;
|
||||
µb.pageStoresToken = Date.now();
|
||||
if ( !tab.title && tryAgain(entry) ) { return; }
|
||||
// https://github.com/gorhill/uMatrix/issues/225
|
||||
// Sometimes title changes while page is loading.
|
||||
const settled = tab.title && tab.title === pageStore.title;
|
||||
// Sometimes title changes while page is loading.
|
||||
const settled =
|
||||
typeof tab.title === 'string' &&
|
||||
tab.title !== '' &&
|
||||
tab.title === pageStore.title;
|
||||
pageStore.title = tab.title || tab.url || '';
|
||||
if ( !settled ) {
|
||||
tryAgain(entry);
|
||||
}
|
||||
if ( settled ) { return; }
|
||||
if ( tabIdToCount.has(tabId) ) { return; }
|
||||
count -= 1;
|
||||
if ( count === 0 ) { return; }
|
||||
tabIdToCount.set(tabId, count);
|
||||
updateTitleAsync(tabId);
|
||||
};
|
||||
|
||||
const updateTitle = async function(entry) {
|
||||
tabIdToTimer.delete(entry.tabId);
|
||||
const tab = await vAPI.tabs.get(entry.tabId);
|
||||
onTabReady(entry, tab);
|
||||
const updateTitleAsync = function(tabId) {
|
||||
vAPI.setTimeout(( ) => { updateTitle(tabId); }, delay);
|
||||
};
|
||||
|
||||
return function(tabId) {
|
||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) { return; }
|
||||
const timer = tabIdToTimer.get(tabId);
|
||||
if ( timer !== undefined ) {
|
||||
clearTimeout(timer);
|
||||
const count = tabIdToCount.get(tabId);
|
||||
tabIdToCount.set(tabId, 5);
|
||||
if ( count === undefined ) {
|
||||
updateTitleAsync(tabId);
|
||||
}
|
||||
tabIdToTimer.set(
|
||||
tabId,
|
||||
vAPI.setTimeout(
|
||||
updateTitle.bind(null, { tabId: tabId, count: 5 }),
|
||||
delay
|
||||
)
|
||||
);
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -1140,13 +1129,14 @@ vAPI.tabs = new vAPI.Tabs();
|
|||
let pageStoreJanitorSampleAt = 0;
|
||||
let pageStoreJanitorSampleSize = 10;
|
||||
|
||||
const checkTab = async tabId => {
|
||||
const tab = await vAPI.tabs.get(tabId);
|
||||
if ( tab instanceof Object && tab.discarded !== true ) { return; }
|
||||
µBlock.unbindTabFromPageStats(tabId);
|
||||
};
|
||||
|
||||
const pageStoreJanitor = function() {
|
||||
const tabIds = Array.from(µBlock.pageStores.keys()).sort();
|
||||
const checkTab = async tabId => {
|
||||
const tab = await vAPI.tabs.get(tabId);
|
||||
if ( tab ) { return; }
|
||||
µBlock.unbindTabFromPageStats(tabId);
|
||||
};
|
||||
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
|
||||
pageStoreJanitorSampleAt = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue