mirror of https://github.com/gorhill/uBlock.git
code review for c5d85881181a: mind about:blank et al. iframes
This commit is contained in:
parent
db67c6bcc4
commit
0c5e2eb7ee
|
@ -878,30 +878,28 @@ vAPI.domCollapser = (function() {
|
||||||
attributeFilter: [ 'src' ]
|
attributeFilter: [ 'src' ]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The injected scriptlets are those which were injected in the current
|
||||||
|
// document, from within `bootstrapPhase1`, and which scriptlets are
|
||||||
|
// selectively looked-up from:
|
||||||
|
// https://github.com/uBlockOrigin/uAssets/blob/master/filters/resources.txt
|
||||||
var primeLocalIFrame = function(iframe) {
|
var primeLocalIFrame = function(iframe) {
|
||||||
// Should probably also copy injected styles.
|
|
||||||
// The injected scripts are those which were injected in the current
|
|
||||||
// document, from within the `contentscript-start.js / injectScripts`,
|
|
||||||
// and which scripts are selectively looked-up from:
|
|
||||||
// https://github.com/gorhill/uBlock/blob/master/assets/ublock/resources.txt
|
|
||||||
if ( vAPI.injectedScripts ) {
|
if ( vAPI.injectedScripts ) {
|
||||||
vAPI.injectScriptlet(iframe.contentDocument, vAPI.injectedScripts);
|
vAPI.injectScriptlet(iframe.contentDocument, vAPI.injectedScripts);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/162
|
||||||
|
// Be prepared to deal with possible change of src attribute.
|
||||||
var addIFrame = function(iframe, dontObserve) {
|
var addIFrame = function(iframe, dontObserve) {
|
||||||
// https://github.com/gorhill/uBlock/issues/162
|
|
||||||
// Be prepared to deal with possible change of src attribute.
|
|
||||||
if ( dontObserve !== true ) {
|
if ( dontObserve !== true ) {
|
||||||
iframeSourceObserver.observe(iframe, iframeSourceObserverOptions);
|
iframeSourceObserver.observe(iframe, iframeSourceObserverOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
var src = iframe.src;
|
var src = iframe.src;
|
||||||
if ( src === '' || typeof src !== 'string' ) {
|
if ( src === '' || typeof src !== 'string' ) {
|
||||||
primeLocalIFrame(iframe);
|
primeLocalIFrame(iframe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( src.lastIndexOf('http', 0) !== 0 ) { return; }
|
if ( src.startsWith('http') === false ) { return; }
|
||||||
toFilter[toFilter.length] = {
|
toFilter[toFilter.length] = {
|
||||||
type: 'sub_frame',
|
type: 'sub_frame',
|
||||||
url: iframe.src
|
url: iframe.src
|
||||||
|
|
|
@ -36,22 +36,109 @@
|
||||||
scriptletsRegister = new Map(),
|
scriptletsRegister = new Map(),
|
||||||
reEscapeScriptArg = /[\\'"]/g;
|
reEscapeScriptArg = /[\\'"]/g;
|
||||||
|
|
||||||
|
// Purpose of `contentscriptCode` below is too programmatically inject
|
||||||
|
// content script code which only purpose is to inject scriptlets. This
|
||||||
|
// essentially does the same as what uBO's declarative content script does,
|
||||||
|
// except that this allows to inject the scriptlets earlier than it is
|
||||||
|
// possible through the declarative content script.
|
||||||
|
//
|
||||||
|
// Declaratively:
|
||||||
|
// 1. Browser injects generic content script =>
|
||||||
|
// 2. Content script queries scriptlets =>
|
||||||
|
// 3. Main process sends scriptlets =>
|
||||||
|
// 4. Content script injects scriptlets
|
||||||
|
//
|
||||||
|
// Programmatically:
|
||||||
|
// 1. uBO injects specific scriptlets-aware content script =>
|
||||||
|
// 2. Content script injects scriptlets
|
||||||
|
//
|
||||||
|
// However currently this programmatic injection works well only on
|
||||||
|
// Chromium-based browsers, it does not work properly with Firefox. More
|
||||||
|
// investigations is needed to find out why this fails with Firefox.
|
||||||
|
// Consequently, the programmatic-injection code path is taken only with
|
||||||
|
// Chromium-based browsers.
|
||||||
|
|
||||||
let contentscriptCode = (function() {
|
let contentscriptCode = (function() {
|
||||||
let parts = [
|
let parts = [
|
||||||
'(',
|
'(',
|
||||||
function(hostname, scriptlets) {
|
function(hostname, scriptlets) {
|
||||||
if ( hostname !== window.location.hostname ) { return; }
|
if (
|
||||||
let d = document;
|
document.location === null ||
|
||||||
let script = d.createElement('script');
|
hostname !== document.location.hostname
|
||||||
try {
|
) {
|
||||||
script.appendChild(d.createTextNode(
|
return;
|
||||||
decodeURIComponent(scriptlets))
|
|
||||||
);
|
|
||||||
(d.head || d.documentElement).appendChild(script);
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
}
|
||||||
if ( script.parentNode ) {
|
let injectScriptlets = function(d) {
|
||||||
script.parentNode.removeChild(script);
|
let script = d.createElement('script');
|
||||||
|
try {
|
||||||
|
script.appendChild(d.createTextNode(
|
||||||
|
decodeURIComponent(scriptlets))
|
||||||
|
);
|
||||||
|
(d.head || d.documentElement).appendChild(script);
|
||||||
|
} catch (ex) {
|
||||||
|
}
|
||||||
|
if ( script.parentNode ) {
|
||||||
|
script.parentNode.removeChild(script);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
injectScriptlets(document);
|
||||||
|
let processIFrame = function(iframe) {
|
||||||
|
let src = iframe.src;
|
||||||
|
if ( /^https?:\/\//.test(src) === false ) {
|
||||||
|
injectScriptlets(iframe.contentDocument);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let observerTimer,
|
||||||
|
observerLists = [];
|
||||||
|
let observerAsync = function() {
|
||||||
|
for ( let nodelist of observerLists ) {
|
||||||
|
for ( let node of nodelist ) {
|
||||||
|
if ( node.nodeType !== 1 ) { continue; }
|
||||||
|
if ( node.parentElement === null ) { continue; }
|
||||||
|
if ( node.localName === 'iframe' ) {
|
||||||
|
processIFrame(node);
|
||||||
|
}
|
||||||
|
if ( node.childElementCount === 0 ) { continue; }
|
||||||
|
let iframes = node.querySelectorAll('iframe');
|
||||||
|
for ( let iframe of iframes ) {
|
||||||
|
processIFrame(iframe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
observerLists = [];
|
||||||
|
observerTimer = undefined;
|
||||||
|
};
|
||||||
|
let ready = function(ev) {
|
||||||
|
if ( ev !== undefined ) {
|
||||||
|
window.removeEventListener(ev.type, ready);
|
||||||
|
}
|
||||||
|
let iframes = document.getElementsByTagName('iframe');
|
||||||
|
if ( iframes.length !== 0 ) {
|
||||||
|
observerLists.push(iframes);
|
||||||
|
observerTimer = setTimeout(observerAsync, 1);
|
||||||
|
}
|
||||||
|
let observer = new MutationObserver(function(mutations) {
|
||||||
|
for ( let mutation of mutations ) {
|
||||||
|
if ( mutation.addedNodes.length !== 0 ) {
|
||||||
|
observerLists.push(mutation.addedNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
observerLists.length !== 0 &&
|
||||||
|
observerTimer === undefined
|
||||||
|
) {
|
||||||
|
observerTimer = setTimeout(observerAsync, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(
|
||||||
|
document.documentElement,
|
||||||
|
{ childList: true, subtree: true }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
if ( document.readyState === 'loading' ) {
|
||||||
|
window.addEventListener('DOMContentLoaded', ready);
|
||||||
|
} else {
|
||||||
|
ready();
|
||||||
}
|
}
|
||||||
}.toString(),
|
}.toString(),
|
||||||
')(',
|
')(',
|
||||||
|
@ -283,9 +370,6 @@
|
||||||
|
|
||||||
if ( out.length === 0 ) { return; }
|
if ( out.length === 0 ) { return; }
|
||||||
|
|
||||||
if ( µb.hiddenSettings.debugScriptlets ) {
|
|
||||||
out.unshift('debugger;');
|
|
||||||
}
|
|
||||||
return out.join('\n');
|
return out.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -305,12 +389,15 @@
|
||||||
let scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
let scriptlets = µb.scriptletFilteringEngine.retrieve(request);
|
||||||
if ( scriptlets === undefined ) { return; }
|
if ( scriptlets === undefined ) { return; }
|
||||||
let code = contentscriptCode.assemble(request.hostname, scriptlets);
|
let code = contentscriptCode.assemble(request.hostname, scriptlets);
|
||||||
|
if ( µb.hiddenSettings.debugScriptlets ) {
|
||||||
|
code = 'debugger;\n' + code;
|
||||||
|
}
|
||||||
chrome.tabs.executeScript(
|
chrome.tabs.executeScript(
|
||||||
details.tabId,
|
details.tabId,
|
||||||
{
|
{
|
||||||
code: code,
|
code: code,
|
||||||
frameId: details.frameId,
|
frameId: details.frameId,
|
||||||
matchAboutBlank: true,
|
matchAboutBlank: false,
|
||||||
runAt: 'document_start'
|
runAt: 'document_start'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue