Add trusted-click-element scriptlet · gorhill/uBlock@7af88b0 (original) (raw)
`@@ -224,9 +224,9 @@ function runAt(fn, when) {
`
224
224
``
225
225
`builtinScriptlets.push({
`
226
226
`name: 'run-at-html-element.fn',
`
227
``
`-
fn: runAtHtmlElement,
`
``
227
`+
fn: runAtHtmlElementFn,
`
228
228
`});
`
229
``
`-
function runAtHtmlElement(fn) {
`
``
229
`+
function runAtHtmlElementFn(fn) {
`
230
230
`if ( document.documentElement ) {
`
231
231
`fn();
`
232
232
`return;
`
`@@ -1160,7 +1160,7 @@ builtinScriptlets.push({
`
1160
1160
`// Issues to mind before changing anything:
`
1161
1161
`// https://github.com/uBlockOrigin/uBlock-issues/issues/2154
`
1162
1162
`function abortCurrentScript(...args) {
`
1163
``
`-
runAtHtmlElement(( ) => {
`
``
1163
`+
runAtHtmlElementFn(( ) => {
`
1164
1164
`abortCurrentScriptCore(...args);
`
1165
1165
`});
`
1166
1166
`}
`
`@@ -3882,4 +3882,113 @@ function trustedReplaceXhrResponse(
`
3882
3882
`};
`
3883
3883
`}
`
3884
3884
``
``
3885
`+
/*******************************************************************************
`
``
3886
`+
*
`
``
3887
`+
- trusted-click-element.js
`
``
3888
`+
*
`
``
3889
`+
- Reference API:
`
``
3890
`+
`
``
3891
`+
*
`
``
3892
`+
**/
`
``
3893
+
``
3894
`+
builtinScriptlets.push({
`
``
3895
`+
name: 'trusted-click-element.js',
`
``
3896
`+
requiresTrust: true,
`
``
3897
`+
fn: trustedClickElement,
`
``
3898
`+
world: 'ISOLATED',
`
``
3899
`+
dependencies: [
`
``
3900
`+
'run-at-html-element.fn',
`
``
3901
`+
'safe-self.fn',
`
``
3902
`+
],
`
``
3903
`+
});
`
``
3904
`+
function trustedClickElement(
`
``
3905
`+
selectors = '',
`
``
3906
`+
extraMatch = '', // not yet supported
`
``
3907
`+
delay = ''
`
``
3908
`+
) {
`
``
3909
`+
if ( extraMatch !== '' ) { return; }
`
``
3910
+
``
3911
`+
const selectorList = selectors.split(/\s*,\s*/)
`
``
3912
`+
.filter(s => {
`
``
3913
`+
try {
`
``
3914
`+
void document.querySelector(s);
`
``
3915
`+
} catch(_) {
`
``
3916
`+
return false;
`
``
3917
`+
}
`
``
3918
`+
return true;
`
``
3919
`+
});
`
``
3920
`+
if ( selectorList.length === 0 ) { return; }
`
``
3921
+
``
3922
`+
const clickDelay = parseInt(delay, 10) || 1;
`
``
3923
`+
const t0 = Date.now();
`
``
3924
`+
const tbye = t0 + 10000;
`
``
3925
`+
let tnext = t0;
`
``
3926
+
``
3927
`+
const terminate = ( ) => {
`
``
3928
`+
selectorList.length = 0;
`
``
3929
`+
next.stop();
`
``
3930
`+
observe.stop();
`
``
3931
`+
};
`
``
3932
+
``
3933
`+
const next = notFound => {
`
``
3934
`+
if ( selectorList.length === 0 ) { return terminate(); }
`
``
3935
`+
const tnow = Date.now();
`
``
3936
`+
if ( tnow >= tbye ) { return terminate(); }
`
``
3937
`+
if ( notFound ) { observe(); }
`
``
3938
`+
const delay = Math.max(notFound ? tbye - tnow : tnext - tnow, 1);
`
``
3939
`+
next.timer = setTimeout(( ) => {
`
``
3940
`+
next.timer = undefined;
`
``
3941
`+
process();
`
``
3942
`+
}, delay);
`
``
3943
`+
};
`
``
3944
`+
next.stop = ( ) => {
`
``
3945
`+
if ( next.timer === undefined ) { return; }
`
``
3946
`+
clearTimeout(next.timer);
`
``
3947
`+
next.timer = undefined;
`
``
3948
`+
};
`
``
3949
+
``
3950
`+
const observe = ( ) => {
`
``
3951
`+
if ( observe.observer !== undefined ) { return; }
`
``
3952
`+
observe.observer = new MutationObserver(( ) => {
`
``
3953
`+
if ( observe.timer !== undefined ) { return; }
`
``
3954
`+
observe.timer = setTimeout(( ) => {
`
``
3955
`+
observe.timer = undefined;
`
``
3956
`+
process();
`
``
3957
`+
}, 20);
`
``
3958
`+
});
`
``
3959
`+
observe.observer.observe(document, {
`
``
3960
`+
attributes: true,
`
``
3961
`+
childList: true,
`
``
3962
`+
subtree: true,
`
``
3963
`+
});
`
``
3964
`+
};
`
``
3965
`+
observe.stop = ( ) => {
`
``
3966
`+
if ( observe.timer !== undefined ) {
`
``
3967
`+
clearTimeout(observe.timer);
`
``
3968
`+
observe.timer = undefined;
`
``
3969
`+
}
`
``
3970
`+
if ( observe.observer ) {
`
``
3971
`+
observe.observer.disconnect();
`
``
3972
`+
observe.observer = undefined;
`
``
3973
`+
}
`
``
3974
`+
};
`
``
3975
+
``
3976
`+
const process = ( ) => {
`
``
3977
`+
next.stop();
`
``
3978
`+
if ( Date.now() < tnext ) { return next(); }
`
``
3979
`+
const selector = selectorList.shift();
`
``
3980
`+
if ( selector === undefined ) { return terminate(); }
`
``
3981
`+
const elem = document.querySelector(selector);
`
``
3982
`+
if ( elem === null ) {
`
``
3983
`+
selectorList.unshift(selector);
`
``
3984
`+
return next(true);
`
``
3985
`+
}
`
``
3986
`+
elem.click();
`
``
3987
`+
tnext += clickDelay;
`
``
3988
`+
next();
`
``
3989
`+
};
`
``
3990
+
``
3991
`+
runAtHtmlElementFn(process);
`
``
3992
`+
}
`
``
3993
+
3885
3994
`/******************************************************************************/
`