text: /**
   * Copyright (c) Meta Platforms, Inc. and affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * @format
   */
  
  'use strict';
  
  const XMLHttpRequest = require('./XMLHttpRequest');
  const originalXHROpen = XMLHttpRequest.prototype.open;
  const originalXHRSend = XMLHttpRequest.prototype.send;
  const originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
  
  let openCallback;
  let sendCallback;
  let requestHeaderCallback;
  let headerReceivedCallback;
  let responseCallback;
  
  let isInterceptorEnabled = false;
  
  /**
   * A network interceptor which monkey-patches XMLHttpRequest methods
   * to gather all network requests/responses, in order to show their
   * information in the React Native inspector development tool.
   * This supports interception with XMLHttpRequest API, including Fetch API
   * and any other third party libraries that depend on XMLHttpRequest.
   */
  const XHRInterceptor = {
    /**
     * Invoked before XMLHttpRequest.open(...) is called.
     */
    setOpenCallback(callback) {
      openCallback = callback;
    },
  
    /**
     * Invoked before XMLHttpRequest.send(...) is called.
     */
    setSendCallback(callback) {
      sendCallback = callback;
    },
  
    /**
     * Invoked after xhr's readyState becomes xhr.HEADERS_RECEIVED.
     */
    setHeaderReceivedCallback(callback) {
      headerReceivedCallback = callback;
    },
  
    /**
     * Invoked after xhr's readyState becomes xhr.DONE.
     */
    setResponseCallback(callback) {
      responseCallback = callback;
    },
  
    /**
     * Invoked before XMLHttpRequest.setRequestHeader(...) is called.
     */
    setRequestHeaderCallback(callback) {
      requestHeaderCallback = callback;
    },
  
    isInterceptorEnabled() {
      return isInterceptorEnabled;
    },
  
    enableInterception() {
      if (isInterceptorEnabled) {
        return;
      }
      // Override `open` method for all XHR requests to intercept the request
      // method and url, then pass them through the `openCallback`.
      XMLHttpRequest.prototype.open = function (method, url) {
        if (openCallback) {
          openCallback(method, url, this);
        }
        originalXHROpen.apply(this, arguments);
      };
  
      // Override `setRequestHeader` method for all XHR requests to intercept
      // the request headers, then pass them through the `requestHeaderCallback`.
      XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
        if (requestHeaderCallback) {
          requestHeaderCallback(header, value, this);
        }
        originalXHRSetRequestHeader.apply(this, arguments);
      };
  
      // Override `send` method of all XHR requests to intercept the data sent,
      // register listeners to intercept the response, and invoke the callbacks.
      XMLHttpRequest.prototype.send = function (data) {
        if (sendCallback) {
          sendCallback(data, this);
        }
        if (this.addEventListener) {
          this.addEventListener(
            'readystatechange',
            () => {
              if (!isInterceptorEnabled) {
                return;
              }
              if (this.readyState === this.HEADERS_RECEIVED) {
                const contentTypeString = this.getResponseHeader('Content-Type');
                const contentLengthString =
                  this.getResponseHeader('Content-Length');
                let responseContentType, responseSize;
                if (contentTypeString) {
                  responseContentType = contentTypeString.split(';')[0];
                }
                if (contentLengthString) {
                  responseSize = parseInt(contentLengthString, 10);
                }
                if (headerReceivedCallback) {
                  headerReceivedCallback(
                    responseContentType,
                    responseSize,
                    this.getAllResponseHeaders(),
                    this,
                  );
                }
              }
              if (this.readyState === this.DONE) {
                if (responseCallback) {
                  responseCallback(
                    this.status,
                    this.timeout,
                    this.response,
                    this.responseURL,
                    this.responseType,
                    this,
                  );
                }
              }
            },
            false,
          );
        }
        originalXHRSend.apply(this, arguments);
      };
      isInterceptorEnabled = true;
    },
  
    // Unpatch XMLHttpRequest methods and remove the callbacks.
    disableInterception() {
      if (!isInterceptorEnabled) {
        return;
      }
      isInterceptorEnabled = false;
      XMLHttpRequest.prototype.send = originalXHRSend;
      XMLHttpRequest.prototype.open = originalXHROpen;
      XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
      responseCallback = null;
      openCallback = null;
      sendCallback = null;
      headerReceivedCallback = null;
      requestHeaderCallback = null;
    },
  };
  
  module.exports = XHRInterceptor;
  