diff --git a/src/js/contentscript.js b/src/js/contentscript.js index 6f29027e1..3656b4177 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -1735,7 +1735,6 @@ vAPI.injectScriptlet = function(doc, text) { vAPI.messaging.send('contentscript', { what: 'retrieveContentScriptParameters', url: vAPI.effectiveSelf.location.href, - charset: document.characterSet, }).then(response => { bootstrapPhase1(response); }); diff --git a/src/js/messaging.js b/src/js/messaging.js index a76ca5d82..a8cb08450 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -557,6 +557,13 @@ const retrieveContentScriptParameters = function(sender, request) { return; } + // A content script may not always be able to successfully look up the + // effective context, hence in such case we try again to look up here + // using cached information about embedded frames. + if ( frameId !== 0 && request.url.startsWith('about:') ) { + request.url = pageStore.getEffectiveFrameURL(sender); + } + const noCosmeticFiltering = pageStore.noCosmeticFiltering === true; const response = { diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 0444e2018..5667878fb 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -181,12 +181,13 @@ const frameStoreJunkyard = []; const frameStoreJunkyardMax = 50; const FrameStore = class { - constructor(frameURL) { - this.init(frameURL); + constructor(frameURL, parentId) { + this.init(frameURL, parentId); } - init(frameURL) { + init(frameURL, parentId) { this.t0 = Date.now(); + this.parentId = parentId; this.exceptCname = undefined; this.clickToLoad = false; this.rawURL = frameURL; @@ -199,7 +200,6 @@ const FrameStore = class { } dispose() { - this.exceptCname = undefined; this.rawURL = this.hostname = this.domain = ''; if ( frameStoreJunkyard.length < frameStoreJunkyardMax ) { frameStoreJunkyard.push(this); @@ -207,12 +207,12 @@ const FrameStore = class { return null; } - static factory(frameURL) { + static factory(frameURL, parentId = -1) { const entry = frameStoreJunkyard.pop(); if ( entry === undefined ) { - return new FrameStore(frameURL); + return new FrameStore(frameURL, parentId); } - return entry.init(frameURL); + return entry.init(frameURL, parentId); } }; @@ -277,7 +277,7 @@ const PageStore = class { this.frameAddCount = 0; this.frames = new Map(); - this.setFrameURL(0, tabContext.rawURL); + this.setFrameURL({ url: tabContext.rawURL }); // https://github.com/uBlockOrigin/uBlock-issues/issues/314 const masterSwitch = tabContext.getNetFilteringSwitch(); @@ -324,7 +324,7 @@ const PageStore = class { // As part of https://github.com/chrisaljoudi/uBlock/issues/405 // URL changed, force a re-evaluation of filtering switch this.rawURL = tabContext.rawURL; - this.setFrameURL(0, this.rawURL); + this.setFrameURL({ url: this.rawURL }); return this; } @@ -375,14 +375,20 @@ const PageStore = class { return this.frames.get(frameId) || null; } - setFrameURL(frameId, frameURL) { + setFrameURL(details) { + let { frameId, url, parentFrameId } = details; + if ( frameId === undefined ) { frameId = 0; } + if ( parentFrameId === undefined ) { parentFrameId = -1; } let frameStore = this.frames.get(frameId); if ( frameStore !== undefined ) { - return frameURL === frameStore.rawURL - ? frameStore - : frameStore.init(frameURL); + if ( url === frameStore.rawURL ) { + frameStore.parentId = parentFrameId; + } else { + frameStore.init(url, parentFrameId); + } + return frameStore; } - frameStore = FrameStore.factory(frameURL); + frameStore = FrameStore.factory(url, parentFrameId); this.frames.set(frameId, frameStore); this.frameAddCount += 1; if ( (this.frameAddCount & 0b111111) === 0 ) { @@ -391,6 +397,20 @@ const PageStore = class { return frameStore; } + getEffectiveFrameURL(sender) { + let { frameId } = sender; + for (;;) { + const frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { break; } + if ( frameStore.rawURL.startsWith('about:') === false ) { + return frameStore.rawURL; + } + frameId = frameStore.parentId; + if ( frameId === -1 ) { break; } + } + return sender.frameURL; + } + // There is no event to tell us a specific subframe has been removed from // the main document. The code below will remove subframes which are no // longer present in the root document. Removing obsolete subframes is @@ -851,7 +871,7 @@ const PageStore = class { clickToLoad(frameId, frameURL) { let frameStore = this.getFrameStore(frameId); if ( frameStore === null ) { - frameStore = this.setFrameURL(frameId, frameURL); + frameStore = this.setFrameURL({ frameId, url: frameURL }); } this.netFilteringCache.forgetResult( this.tabHostname, diff --git a/src/js/tab.js b/src/js/tab.js index ebdce0c42..fe04dbe08 100644 --- a/src/js/tab.js +++ b/src/js/tab.js @@ -875,18 +875,23 @@ vAPI.Tabs = class extends vAPI.Tabs { onNavigation(details) { super.onNavigation(details); const µb = µBlock; - if ( details.frameId === 0 ) { - µb.tabContextManager.commit(details.tabId, details.url); - let pageStore = µb.bindTabToPageStore(details.tabId, 'tabCommitted'); - if ( pageStore ) { - pageStore.journalAddRootFrame('committed', details.url); + const { frameId, tabId, url } = details; + if ( frameId === 0 ) { + µb.tabContextManager.commit(tabId, url); + const pageStore = µb.bindTabToPageStore(tabId, 'tabCommitted'); + if ( pageStore !== null ) { + pageStore.journalAddRootFrame('committed', url); } } - if ( µb.canInjectScriptletsNow && µb.URI.isNetworkURI(details.url) ) { - const pageStore = µb.pageStoreFromTabId(details.tabId); - if ( pageStore !== null && pageStore.getNetFilteringSwitch() ) { - µb.scriptletFilteringEngine.injectNow(details); - } + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore === null ) { return; } + pageStore.setFrameURL(details); + if ( + µb.canInjectScriptletsNow && + µb.URI.isNetworkURI(url) && + pageStore.getNetFilteringSwitch() + ) { + µb.scriptletFilteringEngine.injectNow(details); } } diff --git a/src/js/traffic.js b/src/js/traffic.js index ce25ef13c..5ebf7586b 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -113,7 +113,7 @@ const onBeforeRequest = function(details) { details.parentFrameId !== -1 && details.aliasURL === undefined ) { - pageStore.setFrameURL(details.frameId, details.url); + pageStore.setFrameURL(details); } if ( result === 2 ) {