Move XHRProxy code to the xhrInterceptor folder
Change-Id: I2d2e9a4b4c43b1ed75ed500ba202283e8f3b16b7
diff --git a/src/injections/xhrInterceptor.js b/src/injections/xhrInterceptor.js
deleted file mode 100644
index 07742dd..0000000
--- a/src/injections/xhrInterceptor.js
+++ /dev/null
@@ -1,205 +0,0 @@
-import {waitFor} from 'poll-until-promise';
-
-import {correctArrayKeys} from '../common/protojs';
-import ResponseModifier from '../xhrInterceptor/responseModifiers/index.js';
-import * as utils from '../xhrInterceptor/utils.js';
-
-const kSpecialEvents = ['load', 'loadend'];
-const kErrorEvents = ['error', 'timeout', 'abort'];
-
-const kCheckInterceptionOptions = {
- interval: 50,
- timeout: 100 * 1000,
-};
-
-function flattenOptions(options) {
- if (typeof options === 'boolean') return options;
- if (options) return options['capture'];
- return undefined;
-}
-
-// Slightly based in https://stackoverflow.com/a/24561614.
-class XHRProxy {
- constructor() {
- this.originalXMLHttpRequest = window.XMLHttpRequest;
- const classThis = this;
-
- this.messageID = 0;
- this.responseModifier = new ResponseModifier();
-
- window.XMLHttpRequest = function() {
- this.xhr = new classThis.originalXMLHttpRequest();
- this.$TWPTID = classThis.messageID++;
- this.$responseModified = false;
- this.$responseIntercepted = false;
- this.specialHandlers = {
- load: new Set(),
- loadend: new Set(),
- };
-
- const proxyThis = this;
- kSpecialEvents.forEach(eventName => {
- this.xhr.addEventListener(eventName, function() {
- let p;
- if (eventName === 'load') {
- p = classThis.responseModifier.intercept(proxyThis, this.response).then(() => {
- proxyThis.$responseIntercepted = true;
- });
- } else {
- p = waitFor(() => {
- if (proxyThis.$responseIntercepted) return Promise.resolve();
- return Promise.reject();
- }, kCheckInterceptionOptions);
- }
-
- p.then(() => {
- for (const e of proxyThis.specialHandlers[eventName]) {
- e[1](arguments);
- }
- });
- });
- });
- kErrorEvents.forEach(eventName => {
- this.xhr.addEventListener(eventName, function() {
- proxyThis.$responseIntercepted = true;
- });
- });
- };
-
- const methods = [
- 'open', 'abort', 'setRequestHeader', 'send', 'getResponseHeader',
- 'getAllResponseHeaders', 'dispatchEvent', 'overrideMimeType'
- ];
- methods.forEach(method => {
- window.XMLHttpRequest.prototype[method] = function() {
- const proxyThis = this;
-
- switch (method) {
- case 'open':
- this.$TWPTRequestURL = arguments[1] || location.href;
-
- var interceptors =
- utils.matchInterceptors('response', this.$TWPTRequestURL);
- if (interceptors.length > 0) {
- this.xhr.addEventListener('load', function() {
- var body = utils.getResponseJSON(proxyThis);
- if (body !== undefined)
- interceptors.forEach(i => {
- utils.triggerEvent(i.eventName, body, proxyThis.$TWPTID);
- });
- });
- }
- break;
-
- case 'setRequestHeader':
- let header = arguments[0];
- let value = arguments[1];
- if ('Content-Type'.localeCompare(
- header, undefined, {sensitivity: 'accent'}) == 0)
- this.$isArrayProto = (value == 'application/json+protobuf');
- break;
-
- case 'send':
- var interceptors = utils.matchInterceptors(
- 'request', this.$TWPTRequestURL || location.href);
- if (interceptors.length > 0) {
- let rawBody = arguments[0];
- let body;
- if (typeof (rawBody) === 'object' &&
- (rawBody instanceof Object.getPrototypeOf(Uint8Array))) {
- let dec = new TextDecoder('utf-8');
- body = dec.decode(rawBody);
- } else if (typeof (rawBody) === 'string') {
- body = rawBody;
- } else {
- console.error(
- 'Unexpected type of request body (' + typeof (rawBody) +
- ').',
- this.$TWPTRequestURL);
- return;
- }
-
- let JSONBody = JSON.parse(body);
- if (this.$isArrayProto) JSONBody = correctArrayKeys(JSONBody);
-
- interceptors.forEach(i => {
- utils.triggerEvent(i.eventName, JSONBody, this.$TWPTID);
- });
- }
- break;
- }
- return this.xhr[method].apply(this.xhr, arguments);
- };
- });
-
- window.XMLHttpRequest.prototype.addEventListener = function() {
- if (!kSpecialEvents.includes(arguments[0]))
- return this.xhr.addEventListener.apply(this.xhr, arguments);
-
- this.specialHandlers[arguments[0]].add(arguments);
- };
-
- window.XMLHttpRequest.prototype.removeEventListener = function(
- type, callback, options) {
- if (!kSpecialEvents.includes(type))
- return this.xhr.removeEventListener.apply(this.xhr, arguments);
-
- const flattenedOptions = flattenOptions(options);
- for (const e of this.specialHandlers[type]) {
- if (callback === e[1] && flattenOptions(e[2]) === flattenedOptions) {
- return this.specialHandlers[type].delete(e);
- }
- }
- };
-
- const scalars = [
- 'onabort',
- 'onerror',
- 'onload',
- 'onloadstart',
- 'onloadend',
- 'onprogress',
- 'onreadystatechange',
- 'readyState',
- 'responseText',
- 'responseType',
- 'responseXML',
- 'status',
- 'statusText',
- 'upload',
- 'withCredentials',
- 'DONE',
- 'UNSENT',
- 'HEADERS_RECEIVED',
- 'LOADING',
- 'OPENED'
- ];
- scalars.forEach(scalar => {
- Object.defineProperty(window.XMLHttpRequest.prototype, scalar, {
- get: function() {
- return this.xhr[scalar];
- },
- set: function(val) {
- this.xhr[scalar] = val;
- },
- });
- });
-
- Object.defineProperty(window.XMLHttpRequest.prototype, 'response', {
- get: function() {
- if (!this.$responseIntercepted) return undefined;
- if (this.$responseModified) return this.$newResponse;
- return this.xhr.response;
- },
- });
- Object.defineProperty(window.XMLHttpRequest.prototype, 'originalResponse', {
- get: function() {
- return this.xhr.response;
- },
- });
-
- return this;
- }
-}
-
-new XHRProxy();
diff --git a/src/injections/xhrProxy.js b/src/injections/xhrProxy.js
new file mode 100644
index 0000000..d33521c
--- /dev/null
+++ b/src/injections/xhrProxy.js
@@ -0,0 +1,3 @@
+import XHRProxy from '../xhrInterceptor/XHRProxy.js';
+
+new XHRProxy();