fix: add FetchProxy

This will let us intercept fetch requests (until now we're only proxying
XMLHttpRequest), in order to fix the issues we're experiencing with some
features.

Bug: twpowertools:229
Change-Id: I277473c05479ca39bb6183a51855382124890bde
diff --git a/src/xhrInterceptor/fetchProxy/FetchProxy.ts b/src/xhrInterceptor/fetchProxy/FetchProxy.ts
new file mode 100644
index 0000000..71031c5
--- /dev/null
+++ b/src/xhrInterceptor/fetchProxy/FetchProxy.ts
@@ -0,0 +1,40 @@
+import { InterceptorHandlerPort } from '../interceptors/InterceptorHandler.port';
+import MessageIdTracker from '../MessageIdTracker';
+import { ResponseModifierPort } from '../ResponseModifier.port';
+import FetchProxyCallHandler from './FetchProxyCallHandler';
+
+/**
+ * Class which lets us override window.fetch to proxy the requests through our
+ * internal interceptors to read/modify requests/responses.
+ */
+export default class FetchProxy {
+  private originalFetch: typeof window.fetch;
+  private isInterceptEnabled = false;
+
+  constructor(
+    private responseModifier: ResponseModifierPort,
+    private interceptorHandler: InterceptorHandlerPort,
+    private messageIdTracker: MessageIdTracker,
+  ) {}
+
+  enableInterception() {
+    if (this.isInterceptEnabled) return;
+
+    this.isInterceptEnabled = true;
+
+    this.originalFetch = window.fetch;
+    this.overrideFetch();
+  }
+
+  private overrideFetch() {
+    window.fetch = async (...args) => {
+      const fetchProxyCallhandler = new FetchProxyCallHandler(
+        this.responseModifier,
+        this.interceptorHandler,
+        this.messageIdTracker,
+        this.originalFetch,
+      );
+      return await fetchProxyCallhandler.proxiedFetch(...args);
+    };
+  }
+}