Skip to content

Commit

Permalink
Add ability to log original and modified text content in trusted-repl…
Browse files Browse the repository at this point in the history
…ace-xhr-response scriptlet
  • Loading branch information
AdamWr committed Jun 14, 2024
1 parent 8a02970 commit ee3c9c9
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/scriptlets/trusted-replace-xhr-response.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
* - `name` — string or regular expression for matching XMLHttpRequest property name
* - `value` — string or regular expression for matching the value of the option
* passed to `XMLHttpRequest.open()` call
* - `logContent` — optional, string to log original and modified text content of XMLHttpRequests.
*
* > Usage with no arguments will log XMLHttpRequest objects to browser console;
* > it may be useful for debugging but it is not allowed for prod versions of filter lists.
Expand Down Expand Up @@ -77,16 +78,22 @@ import {
* example.org#%#//scriptlet('trusted-replace-xhr-response', '/#EXT-X-VMAP-AD-BREAK[\s\S]*?/', '#EXT-X-ENDLIST', '/\.m3u8/ method:/GET|HEAD/') <!-- markdownlint-disable-line line-length -->
* ```
*
* 1. Remove all text content of all XMLHttpRequests for example.com
* 1. Remove all text content of all XMLHttpRequests for example.com
*
* ```adblock
* example.org#%#//scriptlet('trusted-replace-xhr-response', '*', '', 'example.com')
* ```
*
* 1. Replace "foo" text content with "bar" of all XMLHttpRequests for example.com and log original and modified text content
*
* ```adblock
* example.org#%#//scriptlet('trusted-replace-xhr-response', 'foo', 'bar', 'example.com', 'logContent')
* ```
*
* @added v1.7.3.
*/
/* eslint-enable max-len */
export function trustedReplaceXhrResponse(source, pattern = '', replacement = '', propsToMatch = '') {
export function trustedReplaceXhrResponse(source, pattern = '', replacement = '', propsToMatch = '', logContent) {
// do nothing if browser does not support Proxy (e.g. Internet Explorer)
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
if (typeof Proxy === 'undefined') {
Expand All @@ -101,6 +108,7 @@ export function trustedReplaceXhrResponse(source, pattern = '', replacement = ''
}

const shouldLog = pattern === '' && replacement === '';
const shouldLogContent = logContent === 'logContent';

const nativeOpen = window.XMLHttpRequest.prototype.open;
const nativeSend = window.XMLHttpRequest.prototype.send;
Expand Down Expand Up @@ -182,7 +190,13 @@ export function trustedReplaceXhrResponse(source, pattern = '', replacement = ''
? /(\n|.)*/
: toRegExp(pattern);

if (shouldLogContent) {
logMessage(source, `Original text content: ${content}`);
}
const modifiedContent = content.replace(patternRegexp, replacement);
if (shouldLogContent) {
logMessage(source, `Modified text content: ${modifiedContent}`);
}

// Manually put required values into target XHR object
// as thisArg can't be redefined and XHR objects can't be (re)assigned or copied
Expand Down
37 changes: 37 additions & 0 deletions tests/scriptlets/trusted-replace-xhr-response.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,43 @@ if (isSupported) {
xhr.send();
});

test('Matched, string pattern log', async (assert) => {
assert.expect(6);

console.log = (...args) => {
if (args.length === 1 && args[0].includes('Original text content:')) {
assert.ok(args[0].includes('Original text content: {\n "a1": 1,\n'), 'should log text in console');
}
if (args.length === 1 && args[0].includes('Modified text content:')) {
assert.ok(args[0].includes('Modified text content: foo bar'), 'should log text in console');
}
nativeConsole(...args);
};

const METHOD = 'GET';
const URL = `${FETCH_OBJECTS_PATH}/test01.json`;
const PATTERN = '*';
const REPLACEMENT = 'foo bar';
const LOG_CONTENT = 'logContent';
const MATCH_DATA = [PATTERN, REPLACEMENT, `${URL} method:${METHOD}`, LOG_CONTENT];

runScriptlet(name, MATCH_DATA);

const done = assert.async();

const xhr = new XMLHttpRequest();
xhr.open(METHOD, URL);
xhr.onload = () => {
assert.strictEqual(xhr.readyState, 4, 'Response done');
assert.notOk(xhr.response.includes(PATTERN), 'Response has been modified');
assert.ok(xhr.response.includes(REPLACEMENT), 'Response text has been modified');

assert.strictEqual(window.hit, 'FIRED', 'hit function fired');
done();
};
xhr.send();
});

test('Matched, regex pattern', async (assert) => {
const METHOD = 'GET';
const URL = `${FETCH_OBJECTS_PATH}/test01.json`;
Expand Down

0 comments on commit ee3c9c9

Please # to comment.