import EventEmitter from "../events.js"; import HookEvent from "../hook.js"; class Xhr extends EventEmitter { constructor(ctx) { super(); this.ctx = ctx; this.window = ctx.window; this.XMLHttpRequest = this.window.XMLHttpRequest; this.xhrProto = this.window.XMLHttpRequest ? this.window.XMLHttpRequest.prototype : {}; this.open = this.xhrProto.open; this.abort = this.xhrProto.abort; this.send = this.xhrProto.send; this.overrideMimeType = this.xhrProto.overrideMimeType this.getAllResponseHeaders = this.xhrProto.getAllResponseHeaders; this.getResponseHeader = this.xhrProto.getResponseHeader; this.setRequestHeader = this.xhrProto.setRequestHeader; this.responseURL = ctx.nativeMethods.getOwnPropertyDescriptor(this.xhrProto, 'responseURL'); this.responseText = ctx.nativeMethods.getOwnPropertyDescriptor(this.xhrProto, 'responseText'); }; override() { this.overrideOpen(); this.overrideSend(); this.overrideMimeType(); this.overrideGetResHeader(); this.overrideGetResHeaders(); this.overrideSetReqHeader(); }; overrideOpen() { this.ctx.override(this.xhrProto, 'open', (target, that, args) => { if (2 > args.length) return target.apply(that, args); let [ method, input, async = true, user = null, password = null ] = args; const event = new HookEvent({ method, input, async, user, password }, target, that); this.emit('open', event); if (event.intercepted) return event.returnValue; return event.target.call( event.that, event.data.method, event.data.input, event.data.async, event.data.user, event.data.password ); }); }; overrideResponseUrl() { this.ctx.overrideDescriptor(this.xhrProto, 'responseURL', { get: (target, that) => { const event = new HookEvent({ value: target.call(that) }, target, that); this.emit('responseUrl', event); if (event.intercepted) return event.returnValue; return event.data.value; }, }); }; overrideSend() { this.ctx.override(this.xhrProto, 'send', (target, that, [ body = null ]) => { const event = new HookEvent({ body }, target, that); this.emit('send', event); if (event.intercepted) return event.returnValue; return event.target.call( event.that, event.data.body, ); }); }; overrideSetReqHeader() { this.ctx.override(this.xhrProto, 'setRequestHeader', (target, that, args) => { if (2 > args.length) return target.apply(that, args); let [ name, value ] = args; const event = new HookEvent({ name, value }, target, that); this.emit('setReqHeader', event); if (event.intercepted) return event.returnValue; return event.target.call(event.that, event.data.name, event.data.value); }); }; overrideGetResHeaders() { this.ctx.override(this.xhrProto, 'getAllResponseHeaders', (target, that) => { const event = new HookEvent({ value: target.call(that) }, target, that); this.emit('getAllResponseHeaders', event); if (event.intercepted) return event.returnValue; return event.data.value; }); }; overrideGetResHeader() { this.ctx.override(this.xhrProto, 'getResponseHeader', (target, that, args) => { if (!args.length) return target.apply(that, args); let [ name ] = args; const event = new HookEvent({ name, value: target.call(that, name) }, target, that); if (event.intercepted) return event.returnValue; return event.data.value; }); }; }; export default Xhr