From b27848a060eee961e2403192097448467b3bc7b5 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 8 Mar 2020 16:15:58 -0400 Subject: [PATCH] Improve window.open-defuser scriptlet The new syntax deprecate the old syntax, though the old syntax will still be supported until it's no longer used in mainstream filter lists. The new syntax is: example.com##+js(window.open-defuser, pattern, seconds) `pattern`: A pattern to match for the defusing to take place. Patterns which starts and ends with `/` will be interpreted as regular expressions. To NOT match a pattern, prefix with `!`. `seconds`: If not present, no window will be opened and the scriptlet will return `null`. If present and a valid integer value, the defuser will return a valid window object even though no popup window is opened. The returned window object will cease to be valid after the specified number of seconds. --- .../window.open-defuser.js | 62 ++++++++++++++++--- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/web_accessible_resources/window.open-defuser.js b/src/web_accessible_resources/window.open-defuser.js index 72fba013e..27dd494c5 100644 --- a/src/web_accessible_resources/window.open-defuser.js +++ b/src/web_accessible_resources/window.open-defuser.js @@ -21,23 +21,65 @@ (function() { 'use strict'; - let result = parseInt('{{1}}', 10); - result = isNaN(result) === false && result === 0; - let needle = '{{2}}'; - if ( needle === '' || needle === '{{2}}' ) { - needle = '.?'; - } else if ( /^\/.+\/$/.test(needle) ) { - needle = needle.slice(1,-1); + let arg1 = '{{1}}'; + if ( arg1 === '{{1}}' ) { arg1 = ''; } + let arg2 = '{{2}}'; + if ( arg2 === '{{2}}' ) { arg2 = ''; } + let arg3 = '{{3}}'; + if ( arg3 === '{{3}}' ) { arg3 = ''; } + const newSyntax = /^[01]?$/.test(arg1) === false; + let pattern = ''; + let targetResult = true; + let autoRemoveAfter = -1; + if ( newSyntax ) { + pattern = arg1; + if ( pattern.startsWith('!') ) { + targetResult = false; + pattern = pattern.slice(1); + } + autoRemoveAfter = parseInt(arg2); + if ( isNaN(autoRemoveAfter) ) { + autoRemoveAfter = -1; + } } else { - needle = needle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + pattern = arg2; + if ( arg1 === '0' ) { + targetResult = false; + } } - needle = new RegExp(needle); + if ( pattern === '' ) { + pattern = '.?'; + } else if ( /^\/.+\/$/.test(pattern) ) { + pattern = pattern.slice(1,-1); + } else { + pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + } + const rePattern = new RegExp(pattern); window.open = new Proxy(window.open, { apply: function(target, thisArg, args) { const url = args[0]; - if ( needle.test(url) === result ) { + if ( rePattern.test(url) !== targetResult ) { return target.apply(thisArg, args); } + if ( autoRemoveAfter < 0 ) { return null; } + const iframe = document.createElement('iframe'); + iframe.src = url; + iframe.style.setProperty('display','none', 'important'); + iframe.style.setProperty('height','1px', 'important'); + iframe.style.setProperty('width','1px', 'important'); + document.body.appendChild(iframe); + setTimeout(( ) => iframe.remove(), autoRemoveAfter * 1000); + if ( arg3 === '' ) { return iframe.contentWindow; } + return new Proxy(iframe.contentWindow, { + get: function(target, prop) { + console.log('get', prop, '===', target[prop]); + return target[prop]; + }, + set: function(target, prop, value) { + console.log('set', prop, '=', value); + target[prop] = value; + }, + }); } }); })();