Imrpove no-xhr-if scriptlet · gorhill/uBlock@bf591d9 (original) (raw)

`@@ -1935,21 +1935,55 @@ builtinScriptlets.push({

`

1935

1935

`});

`

1936

1936

`function noXhrIf(

`

1937

1937

`propsToMatch = '',

`

1938

``

`-

randomize = ''

`

``

1938

`+

directive = ''

`

1939

1939

`) {

`

1940

1940

`if ( typeof propsToMatch !== 'string' ) { return; }

`

1941

1941

`const xhrInstances = new WeakMap();

`

1942

1942

`const propNeedles = parsePropertiesToMatch(propsToMatch, 'url');

`

1943

1943

`const log = propNeedles.size === 0 ? console.log.bind(console) : undefined;

`

``

1944

`+

const warOrigin = scriptletGlobals.get('warOrigin');

`

``

1945

`+

const generateRandomString = len => {

`

``

1946

`+

let s = '';

`

``

1947

`+

do { s += Math.random().toString(36).slice(2); }

`

``

1948

`+

while ( s.length < 10 );

`

``

1949

`+

return s.slice(0, len);

`

``

1950

`+

};

`

``

1951

`+

const generateContent = async directive => {

`

``

1952

`+

if ( directive === 'true' ) {

`

``

1953

`+

return generateRandomString(10);

`

``

1954

`+

}

`

``

1955

`+

if ( directive.startsWith('war:') ) {

`

``

1956

`+

if ( warOrigin === undefined ) { return ''; }

`

``

1957

`+

const warName = directive.slice(4);

`

``

1958

`+

const fullpath = [ warOrigin, '/', warName ];

`

``

1959

`+

const warSecret = scriptletGlobals.get('warSecret') || '';

`

``

1960

`+

if ( warSecret !== '' ) {

`

``

1961

`+

fullpath.push('?secret=', warSecret);

`

``

1962

`+

}

`

``

1963

`+

return new Promise(resolve => {

`

``

1964

`+

const warXHR = new XMLHttpRequest();

`

``

1965

`+

warXHR.responseType = 'text';

`

``

1966

`+

warXHR.onloadend = ev => {

`

``

1967

`+

resolve(ev.target.responseText || '');

`

``

1968

`+

};

`

``

1969

`+

warXHR.open('GET', fullpath.join(''));

`

``

1970

`+

warXHR.send();

`

``

1971

`+

});

`

``

1972

`+

}

`

``

1973

`+

return '';

`

``

1974

`+

};

`

1944

1975

`self.XMLHttpRequest = class extends self.XMLHttpRequest {

`

1945

1976

`open(method, url, ...args) {

`

1946

1977

`if ( log !== undefined ) {

`

1947

1978

`` log(uBO: xhr.open(${method}, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>u</mi><mi>r</mi><mi>l</mi></mrow><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">{url}, </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span></span><span class="mpunct">,</span></span></span></span>{args.join(', ')}));

``

1948

``

`-

} else {

`

1949

``

`-

const haystack = { method, url };

`

1950

``

`-

if ( matchObjectProperties(propNeedles, haystack) ) {

`

1951

``

`-

xhrInstances.set(this, haystack);

`

1952

``

`-

}

`

``

1979

`+

return super.open(method, url, ...args);

`

``

1980

`+

}

`

``

1981

`+

if ( warOrigin !== undefined && url.startsWith(warOrigin) ) {

`

``

1982

`+

return super.open(method, url, ...args);

`

``

1983

`+

}

`

``

1984

`+

const haystack = { method, url };

`

``

1985

`+

if ( matchObjectProperties(propNeedles, haystack) ) {

`

``

1986

`+

xhrInstances.set(this, haystack);

`

1953

1987

`}

`

1954

1988

`return super.open(method, url, ...args);

`

1955

1989

`}

`

`@@ -1958,50 +1992,66 @@ function noXhrIf(

`

1958

1992

`if ( haystack === undefined ) {

`

1959

1993

`return super.send(...args);

`

1960

1994

`}

`

1961

``

`-

Object.defineProperties(this, {

`

1962

``

`-

readyState: { value: 4 },

`

1963

``

`-

responseURL: { value: haystack.url },

`

1964

``

`-

status: { value: 200 },

`

1965

``

`-

statusText: { value: 'OK' },

`

``

1995

`+

let promise = Promise.resolve({

`

``

1996

`+

xhr: this,

`

``

1997

`+

directive,

`

``

1998

`+

props: {

`

``

1999

`+

readyState: { value: 4 },

`

``

2000

`+

response: { value: '' },

`

``

2001

`+

responseText: { value: '' },

`

``

2002

`+

responseXML: { value: null },

`

``

2003

`+

responseURL: { value: haystack.url },

`

``

2004

`+

status: { value: 200 },

`

``

2005

`+

statusText: { value: 'OK' },

`

``

2006

`+

},

`

1966

2007

`});

`

1967

``

`-

let response = '';

`

1968

``

`-

let responseText = '';

`

1969

``

`-

let responseXML = null;

`

1970

2008

`switch ( this.responseType ) {

`

1971

2009

`case 'arraybuffer':

`

1972

``

`-

response = new ArrayBuffer(0);

`

``

2010

`+

promise = promise.then(details => {

`

``

2011

`+

details.props.response.value = new ArrayBuffer(0);

`

``

2012

`+

return details;

`

``

2013

`+

});

`

1973

2014

`break;

`

1974

2015

`case 'blob':

`

1975

``

`-

response = new Blob([]);

`

``

2016

`+

promise = promise.then(details => {

`

``

2017

`+

details.props.response.value = new Blob([]);

`

``

2018

`+

return details;

`

``

2019

`+

});

`

1976

2020

`break;

`

1977

2021

`case 'document': {

`

1978

``

`-

const parser = new DOMParser();

`

1979

``

`-

const doc = parser.parseFromString('', 'text/html');

`

1980

``

`-

response = doc;

`

1981

``

`-

responseXML = doc;

`

``

2022

`+

promise = promise.then(details => {

`

``

2023

`+

const parser = new DOMParser();

`

``

2024

`+

const doc = parser.parseFromString('', 'text/html');

`

``

2025

`+

details.props.response.value = doc;

`

``

2026

`+

details.props.responseXML.value = doc;

`

``

2027

`+

return details;

`

``

2028

`+

});

`

1982

2029

`break;

`

1983

2030

`}

`

1984

2031

`case 'json':

`

1985

``

`-

response = {};

`

1986

``

`-

responseText = '{}';

`

``

2032

`+

promise = promise.then(details => {

`

``

2033

`+

details.props.response.value = {};

`

``

2034

`+

details.props.responseText.value = '{}';

`

``

2035

`+

return details;

`

``

2036

`+

});

`

1987

2037

`break;

`

1988

2038

`default:

`

1989

``

`-

if ( randomize !== 'true' ) { break; }

`

1990

``

`-

do {

`

1991

``

`-

response += Math.random().toString(36).slice(-2);

`

1992

``

`-

} while ( response.length < 10 );

`

1993

``

`-

response = response.slice(-10);

`

1994

``

`-

responseText = response;

`

``

2039

`+

if ( directive === '' ) { break; }

`

``

2040

`+

promise = promise.then(details => {

`

``

2041

`+

return generateContent(details.directive).then(text => {

`

``

2042

`+

details.props.response.value = text;

`

``

2043

`+

details.props.responseText.value = text;

`

``

2044

`+

return details;

`

``

2045

`+

});

`

``

2046

`+

});

`

1995

2047

`break;

`

1996

2048

`}

`

1997

``

`-

Object.defineProperties(this, {

`

1998

``

`-

response: { value: response },

`

1999

``

`-

responseText: { value: responseText },

`

2000

``

`-

responseXML: { value: responseXML },

`

``

2049

`+

promise.then(details => {

`

``

2050

`+

Object.defineProperties(details.xhr, details.props);

`

``

2051

`+

details.xhr.dispatchEvent(new Event('readystatechange'));

`

``

2052

`+

details.xhr.dispatchEvent(new Event('load'));

`

``

2053

`+

details.xhr.dispatchEvent(new Event('loadend'));

`

2001

2054

`});

`

2002

``

`-

this.dispatchEvent(new Event('readystatechange'));

`

2003

``

`-

this.dispatchEvent(new Event('load'));

`

2004

``

`-

this.dispatchEvent(new Event('loadend'));

`

2005

2055

`}

`

2006

2056

`};

`

2007

2057

`}

`