Add ability to lookup effective context from store of frames

Content scripts can't properly look up effective context
for sandboxed frames. This commit add ability to extract
effective context from already existing store of frames
used for each tab.
This commit is contained in:
Raymond Hill 2021-01-10 11:56:27 -05:00
parent 37c9f966ac
commit 114012ae11
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
5 changed files with 58 additions and 27 deletions

View file

@ -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);
});

View file

@ -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 = {

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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 ) {