blob: e736593a594950199b51958072ada3bcefd3e1bb [file] [log] [blame]
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +01001import MWOptionsWatcherClient from '../../common/mainWorldOptionsWatcher/Client.js';
Adrià Vilanova Martínez8a17fa82023-02-04 19:19:27 +01002import {convertJSONToResponse, convertJSONToResponseText, getResponseJSON} from '../utils.js';
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +01003
Adrià Vilanova Martínez4fb615f2023-02-04 18:55:16 +01004import createMessageRemoveParentRef from './createMessageRemoveParentRef.js';
Adrià Vilanova Martínez8a17fa82023-02-04 19:19:27 +01005import flattenThread from './flattenThread.js';
6import loadMoreThread from './loadMoreThread.js';
Adrià Vilanova Martíneza38faee2024-05-16 19:52:57 +02007import removeUserAbuseEventsInViewForum from './removeUserAbuseEventsInViewForum.js';
8import removeUserAbuseEventsInViewThread from './removeUserAbuseEventsInViewThread.js';
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +01009
10export const responseModifiers = [
Adrià Vilanova Martínez2d9be8d2022-12-28 00:50:14 +010011 loadMoreThread,
12 flattenThread,
Adrià Vilanova Martínez4fb615f2023-02-04 18:55:16 +010013 createMessageRemoveParentRef,
Adrià Vilanova Martíneza38faee2024-05-16 19:52:57 +020014 removeUserAbuseEventsInViewForum,
15 removeUserAbuseEventsInViewThread,
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +010016];
17
18// Content script target
19export const kCSTarget = 'TWPT-XHRInterceptorOptionsWatcher-CS';
20// Main world (AKA regular web page) target
21export const kMWTarget = 'TWPT-XHRInterceptorOptionsWatcher-MW';
22
23export default class ResponseModifier {
24 constructor() {
25 this.optionsWatcher = new MWOptionsWatcherClient(
26 Array.from(this.watchingFeatures()), kCSTarget, kMWTarget);
27 }
28
29 watchingFeatures(modifiers) {
30 if (!modifiers) modifiers = responseModifiers;
31
32 const union = new Set();
33 for (const m of modifiers) {
34 if (!m.featureGated) continue;
35 for (const feature of m.features) union.add(feature);
36 }
37 return union;
38 }
39
40 async #getMatchingModifiers(request) {
41 // First filter modifiers which match the request URL regex.
42 const urlModifiers = responseModifiers.filter(
43 modifier => request.$TWPTRequestURL.match(modifier.urlRegex));
44
45 // Now filter modifiers which require a certain feature to be enabled
46 // (feature-gated modifiers).
47 const featuresAreEnabled = await this.optionsWatcher.areEnabled(
48 Array.from(this.watchingFeatures(urlModifiers)));
49
50 // #!if !production
51 if (Object.keys(featuresAreEnabled).length > 0) {
Adrià Vilanova Martínez5b987932023-11-16 02:18:44 +010052 console.debug(
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +010053 '[XHR Interceptor - Response Modifier] Requested features',
54 featuresAreEnabled, 'for request', request.$TWPTRequestURL);
55 }
56 // #!endif
57
58 return urlModifiers.filter(modifier => {
59 return !modifier.featureGated || modifier.isEnabled(featuresAreEnabled);
60 });
61 }
62
Adrià Vilanova Martínezb47ec062023-01-15 17:43:26 +010063 async intercept(request) {
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +010064 const matchingModifiers = await this.#getMatchingModifiers(request);
65
66 // If we didn't find any matching modifiers, return the response right away.
Adrià Vilanova Martínezb47ec062023-01-15 17:43:26 +010067 if (matchingModifiers.length === 0) return request.xhr.response;
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +010068
69 // Otherwise, apply the modifiers sequentially and set the new response.
70 let json = getResponseJSON({
71 responseType: request.xhr.responseType,
72 response: request.xhr.response,
73 $TWPTRequestURL: request.$TWPTRequestURL,
74 $isArrayProto: request.$isArrayProto,
75 });
76 for (const modifier of matchingModifiers) {
77 json = await modifier.interceptor(request, json);
78 }
Adrià Vilanova Martínez8a17fa82023-02-04 19:19:27 +010079 request.$newResponse = convertJSONToResponse(request, json);
80 request.$newResponseText = convertJSONToResponseText(request, json);
Adrià Vilanova Martínezac2a5612022-12-27 21:51:40 +010081 request.$responseModified = true;
82 }
83}