/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import {Cookie} from './Cookie.js';
import {Events as NetworkRequestEvents, NetworkRequest} from './NetworkRequest.js';
import {Capability, SDKModel, SDKModelObserver, Target} from './SDKModel.js';  // eslint-disable-line no-unused-vars

/**
 * @unrestricted
 */
export class NetworkManager extends SDKModel {
  /**
   * @param {!Target} target
   */
  constructor(target) {
    super(target);
    this._dispatcher = new NetworkDispatcher(this);
    this._networkAgent = target.networkAgent();
    target.registerNetworkDispatcher(this._dispatcher);
    if (Common.moduleSetting('cacheDisabled').get()) {
      this._networkAgent.setCacheDisabled(true);
    }

    this._networkAgent.enable(undefined, undefined, MAX_EAGER_POST_REQUEST_BODY_LENGTH);

    this._bypassServiceWorkerSetting = Common.settings.createSetting('bypassServiceWorker', false);
    if (this._bypassServiceWorkerSetting.get()) {
      this._bypassServiceWorkerChanged();
    }
    this._bypassServiceWorkerSetting.addChangeListener(this._bypassServiceWorkerChanged, this);

    Common.moduleSetting('cacheDisabled').addChangeListener(this._cacheDisabledSettingChanged, this);
  }

  /**
   * @param {!NetworkRequest} request
   * @return {?NetworkManager}
   */
  static forRequest(request) {
    return request[_networkManagerForRequestSymbol];
  }

  /**
   * @param {!NetworkRequest} request
   * @return {boolean}
   */
  static canReplayRequest(request) {
    return !!request[_networkManagerForRequestSymbol] && request.resourceType() === Common.resourceTypes.XHR;
  }

  /**
   * @param {!NetworkRequest} request
   */
  static replayRequest(request) {
    const manager = request[_networkManagerForRequestSymbol];
    if (!manager) {
      return;
    }
    manager._networkAgent.replayXHR(request.requestId());
  }

  /**
   * @param {!NetworkRequest} request
   * @param {string} query
   * @param {boolean} caseSensitive
   * @param {boolean} isRegex
   * @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
   */
  static async searchInRequest(request, query, caseSensitive, isRegex) {
    const manager = NetworkManager.forRequest(request);
    if (!manager) {
      return [];
    }
    const response = await manager._networkAgent.invoke_searchInResponseBody(
        {requestId: request.requestId(), query: query, caseSensitive: caseSensitive, isRegex: isRegex});
    return response.result || [];
  }

  /**
   * @param {!NetworkRequest} request
   * @return {!Promise<!SDK.NetworkRequest.ContentData>}
   */
  static async requestContentData(request) {
    if (request.resourceType() === Common.resourceTypes.WebSocket) {
      return {error: 'Content for WebSockets is currently not supported', content: null, encoded: false};
    }
    if (!request.finished) {
      await request.once(NetworkRequestEvents.FinishedLoading);
    }
    const manager = NetworkManager.forRequest(request);
    if (!manager) {
      return {error: 'No network manager for request', content: null, encoded: false};
    }
    const response = await manager._networkAgent.invoke_getResponseBody({requestId: request.requestId()});
    const error = response[Protocol.Error] || null;
    return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
  }

  /**
   * @param {!NetworkRequest} request
   * @return {!Promise<?string>}
   */
  static requestPostData(request) {
    const manager = NetworkManager.forRequest(request);
    if (manager) {
      return manager._networkAgent.getRequestPostData(request.backendRequestId());
    }
    console.error('No network manager for request');
    return /** @type {!Promise<?string>} */ (Promise.resolve(null));
  }

  /**
   * @param {!SDK.NetworkManager.Conditions} conditions
   * @return {!Protocol.Network.ConnectionType}
   * TODO(allada): this belongs to NetworkConditionsSelector, which should hardcode/guess it.
   */
  static _connectionType(conditions) {
    if (!conditions.download && !conditions.upload) {
      return Protocol.Network.ConnectionType.None;
    }
    let types = NetworkManager._connectionTypes;
    if (!types) {
      NetworkManager._connectionTypes = [];
      types = NetworkManager._connectionTypes;
      types.push(['2g', Protocol.Network.ConnectionType.Cellular2g]);
      types.push(['3g', Protocol.Network.ConnectionType.Cellular3g]);
      types.push(['4g', Protocol.Network.ConnectionType.Cellular4g]);
      types.push(['bluetooth', Protocol.Network.ConnectionType.Bluetooth]);
      types.push(['wifi', Protocol.Network.ConnectionType.Wifi]);
      types.push(['wimax', Protocol.Network.ConnectionType.Wimax]);
    }
    for (const type of types) {
      if (conditions.title.toLowerCase().indexOf(type[0]) !== -1) {
        return type[1];
      }
    }
    return Protocol.Network.ConnectionType.Other;
  }

  /**
   * @param {!Object} headers
   * @return {!Object<string, string>}
   */
  static lowercaseHeaders(headers) {
    const newHeaders = {};
    for (const headerName in headers) {
      newHeaders[headerName.toLowerCase()] = headers[headerName];
    }
    return newHeaders;
  }

  /**
   * @param {string} url
   * @return {!NetworkRequest}
   */
  inflightRequestForURL(url) {
    return this._dispatcher._inflightRequestsByURL[url];
  }

  /**
   * @param {!Common.Event} event
   */
  _cacheDisabledSettingChanged(event) {
    const enabled = /** @type {boolean} */ (event.data);
    this._networkAgent.setCacheDisabled(enabled);
  }

  /**
   * @override
   */
  dispose() {
    Common.moduleSetting('cacheDisabled').removeChangeListener(this._cacheDisabledSettingChanged, this);
  }

  _bypassServiceWorkerChanged() {
    this._networkAgent.setBypassServiceWorker(this._bypassServiceWorkerSetting.get());
  }
}

/** @enum {symbol} */
export const Events = {
  RequestStarted: Symbol('RequestStarted'),
  RequestUpdated: Symbol('RequestUpdated'),
  RequestFinished: Symbol('RequestFinished'),
  RequestUpdateDropped: Symbol('RequestUpdateDropped'),
  ResponseReceived: Symbol('ResponseReceived'),
  MessageGenerated: Symbol('MessageGenerated'),
  RequestRedirected: Symbol('RequestRedirected'),
  LoadingFinished: Symbol('LoadingFinished'),
};

const _MIMETypes = {
  'text/html': {'document': true},
  'text/xml': {'document': true},
  'text/plain': {'document': true},
  'application/xhtml+xml': {'document': true},
  'image/svg+xml': {'document': true},
  'text/css': {'stylesheet': true},
  'text/xsl': {'stylesheet': true},
  'text/vtt': {'texttrack': true},
  'application/pdf': {'document': true},
};

/** @type {!SDK.NetworkManager.Conditions} */
export const NoThrottlingConditions = {
  title: ls`Online`,
  download: -1,
  upload: -1,
  latency: 0
};

/** @type {!SDK.NetworkManager.Conditions} */
export const OfflineConditions = {
  title: Common.UIString('Offline'),
  download: 0,
  upload: 0,
  latency: 0,
};

/** @type {!SDK.NetworkManager.Conditions} */
export const Slow3GConditions = {
  title: Common.UIString('Slow 3G'),
  download: 500 * 1024 / 8 * .8,
  upload: 500 * 1024 / 8 * .8,
  latency: 400 * 5,
};

/** @type {!SDK.NetworkManager.Conditions} */
export const Fast3GConditions = {
  title: Common.UIString('Fast 3G'),
  download: 1.6 * 1024 * 1024 / 8 * .9,
  upload: 750 * 1024 / 8 * .9,
  latency: 150 * 3.75,
};

const _networkManagerForRequestSymbol = Symbol('NetworkManager');
const MAX_EAGER_POST_REQUEST_BODY_LENGTH = 64 * 1024;  // bytes

/**
 * @implements {Protocol.NetworkDispatcher}
 * @unrestricted
 */
export class NetworkDispatcher {
  /**
   * @param {!NetworkManager} manager
   */
  constructor(manager) {
    this._manager = manager;
    /** @type {!Object<!Protocol.Network.RequestId, !NetworkRequest>} */
    this._inflightRequestsById = {};
    /** @type {!Object<string, !NetworkRequest>} */
    this._inflightRequestsByURL = {};
    /** @type {!Map<string, !RedirectExtraInfoBuilder>} */
    this._requestIdToRedirectExtraInfoBuilder = new Map();
  }

  /**
   * @param {!Protocol.Network.Headers} headersMap
   * @return {!Array.<!SDK.NetworkRequest.NameValue>}
   */
  _headersMapToHeadersArray(headersMap) {
    const result = [];
    for (const name in headersMap) {
      const values = headersMap[name].split('\n');
      for (let i = 0; i < values.length; ++i) {
        result.push({name: name, value: values[i]});
      }
    }
    return result;
  }

  /**
   * @param {!NetworkRequest} networkRequest
   * @param {!Protocol.Network.Request} request
   */
  _updateNetworkRequestWithRequest(networkRequest, request) {
    networkRequest.requestMethod = request.method;
    networkRequest.setRequestHeaders(this._headersMapToHeadersArray(request.headers));
    networkRequest.setRequestFormData(!!request.hasPostData, request.postData || null);
    networkRequest.setInitialPriority(request.initialPriority);
    networkRequest.mixedContentType = request.mixedContentType || Protocol.Security.MixedContentType.None;
    networkRequest.setReferrerPolicy(request.referrerPolicy);
  }

  /**
   * @param {!NetworkRequest} networkRequest
   * @param {!Protocol.Network.Response=} response
   */
  _updateNetworkRequestWithResponse(networkRequest, response) {
    if (response.url && networkRequest.url() !== response.url) {
      networkRequest.setUrl(response.url);
    }
    networkRequest.mimeType = response.mimeType;
    networkRequest.statusCode = response.status;
    networkRequest.statusText = response.statusText;
    if (!networkRequest.hasExtraResponseInfo()) {
      networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers);
    }

    if (response.encodedDataLength >= 0) {
      networkRequest.setTransferSize(response.encodedDataLength);
    }

    if (response.requestHeaders && !networkRequest.hasExtraRequestInfo()) {
      // TODO(http://crbug.com/1004979): Stop using response.requestHeaders and
      //   response.requestHeadersText once shared workers
      //   emit Network.*ExtraInfo events for their network requests.
      networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
      networkRequest.setRequestHeadersText(response.requestHeadersText || '');
    }

    networkRequest.connectionReused = response.connectionReused;
    networkRequest.connectionId = String(response.connectionId);
    if (response.remoteIPAddress) {
      networkRequest.setRemoteAddress(response.remoteIPAddress, response.remotePort || -1);
    }

    if (response.fromServiceWorker) {
      networkRequest.fetchedViaServiceWorker = true;
    }

    if (response.fromDiskCache) {
      networkRequest.setFromDiskCache();
    }

    if (response.fromPrefetchCache) {
      networkRequest.setFromPrefetchCache();
    }

    networkRequest.timing = response.timing;

    networkRequest.protocol = response.protocol || '';

    networkRequest.setSecurityState(response.securityState);

    if (!this._mimeTypeIsConsistentWithType(networkRequest)) {
      const message = Common.UIString(
          'Resource interpreted as %s but transferred with MIME type %s: "%s".', networkRequest.resourceType().title(),
          networkRequest.mimeType, networkRequest.url());
      this._manager.dispatchEventToListeners(
          Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: true});
    }

    if (response.securityDetails) {
      networkRequest.setSecurityDetails(response.securityDetails);
    }
  }

  /**
   * @param {!NetworkRequest} networkRequest
   * @return {boolean}
   */
  _mimeTypeIsConsistentWithType(networkRequest) {
    // If status is an error, content is likely to be of an inconsistent type,
    // as it's going to be an error message. We do not want to emit a warning
    // for this, though, as this will already be reported as resource loading failure.
    // Also, if a URL like http://localhost/wiki/load.php?debug=true&lang=en produces text/css and gets reloaded,
    // it is 304 Not Modified and its guessed mime-type is text/php, which is wrong.
    // Don't check for mime-types in 304-resources.
    if (networkRequest.hasErrorStatusCode() || networkRequest.statusCode === 304 || networkRequest.statusCode === 204) {
      return true;
    }

    const resourceType = networkRequest.resourceType();
    if (resourceType !== Common.resourceTypes.Stylesheet && resourceType !== Common.resourceTypes.Document &&
        resourceType !== Common.resourceTypes.TextTrack) {
      return true;
    }


    if (!networkRequest.mimeType) {
      return true;
    }  // Might be not known for cached resources with null responses.

    if (networkRequest.mimeType in _MIMETypes) {
      return resourceType.name() in _MIMETypes[networkRequest.mimeType];
    }

    return false;
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.ResourcePriority} newPriority
   * @param {!Protocol.Network.MonotonicTime} timestamp
   */
  resourceChangedPriority(requestId, newPriority, timestamp) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (networkRequest) {
      networkRequest.setPriority(newPriority);
    }
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.SignedExchangeInfo} info
   */
  signedExchangeReceived(requestId, info) {
    // While loading a signed exchange, a signedExchangeReceived event is sent
    // between two requestWillBeSent events.
    // 1. The first requestWillBeSent is sent while starting the navigation (or
    //    prefetching).
    // 2. This signedExchangeReceived event is sent when the browser detects the
    //    signed exchange.
    // 3. The second requestWillBeSent is sent with the generated redirect
    //    response and a new redirected request which URL is the inner request
    //    URL of the signed exchange.
    let networkRequest = this._inflightRequestsById[requestId];
    // |requestId| is available only for navigation requests. If the request was
    // sent from a renderer process for prefetching, it is not available. In the
    // case, need to fallback to look for the URL.
    // TODO(crbug/841076): Sends the request ID of prefetching to the browser
    // process and DevTools to find the matching request.
    if (!networkRequest) {
      networkRequest = this._inflightRequestsByURL[info.outerResponse.url];
      if (!networkRequest) {
        return;
      }
    }
    networkRequest.setSignedExchangeInfo(info);
    networkRequest.setResourceType(Common.resourceTypes.SignedExchange);

    this._updateNetworkRequestWithResponse(networkRequest, info.outerResponse);
    this._updateNetworkRequest(networkRequest);
    this._manager.dispatchEventToListeners(Events.ResponseReceived, networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.LoaderId} loaderId
   * @param {string} documentURL
   * @param {!Protocol.Network.Request} request
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.TimeSinceEpoch} wallTime
   * @param {!Protocol.Network.Initiator} initiator
   * @param {!Protocol.Network.Response=} redirectResponse
   * @param {!Protocol.Network.ResourceType=} resourceType
   * @param {!Protocol.Page.FrameId=} frameId
   */
  requestWillBeSent(
      requestId, loaderId, documentURL, request, time, wallTime, initiator, redirectResponse, resourceType, frameId) {
    let networkRequest = this._inflightRequestsById[requestId];
    if (networkRequest) {
      // FIXME: move this check to the backend.
      if (!redirectResponse) {
        return;
      }
      // If signedExchangeReceived event has already been sent for the request,
      // ignores the internally generated |redirectResponse|. The
      // |outerResponse| of SignedExchangeInfo was set to |networkRequest| in
      // signedExchangeReceived().
      if (!networkRequest.signedExchangeInfo()) {
        this.responseReceived(
            requestId, loaderId, time, Protocol.Network.ResourceType.Other, redirectResponse, frameId);
      }
      networkRequest = this._appendRedirect(requestId, time, request.url);
      this._manager.dispatchEventToListeners(Events.RequestRedirected, networkRequest);
    } else {
      networkRequest =
          this._createNetworkRequest(requestId, frameId || '', loaderId, request.url, documentURL, initiator);
    }
    networkRequest.hasNetworkData = true;
    this._updateNetworkRequestWithRequest(networkRequest, request);
    networkRequest.setIssueTime(time, wallTime);
    networkRequest.setResourceType(
        resourceType ? Common.resourceTypes[resourceType] : Protocol.Network.ResourceType.Other);

    this._getExtraInfoBuilder(requestId).addRequest(networkRequest);

    this._startNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   */
  requestServedFromCache(requestId) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.setFromMemoryCache();
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.LoaderId} loaderId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.ResourceType} resourceType
   * @param {!Protocol.Network.Response} response
   * @param {!Protocol.Page.FrameId=} frameId
   */
  responseReceived(requestId, loaderId, time, resourceType, response, frameId) {
    const networkRequest = this._inflightRequestsById[requestId];
    const lowercaseHeaders = NetworkManager.lowercaseHeaders(response.headers);
    if (!networkRequest) {
      // We missed the requestWillBeSent.
      const eventData = {};
      eventData.url = response.url;
      eventData.frameId = frameId || '';
      eventData.loaderId = loaderId;
      eventData.resourceType = resourceType;
      eventData.mimeType = response.mimeType;
      const lastModifiedHeader = lowercaseHeaders['last-modified'];
      eventData.lastModified = lastModifiedHeader ? new Date(lastModifiedHeader) : null;
      this._manager.dispatchEventToListeners(Events.RequestUpdateDropped, eventData);
      return;
    }

    networkRequest.responseReceivedTime = time;
    networkRequest.setResourceType(Common.resourceTypes[resourceType]);

    // net::ParsedCookie::kMaxCookieSize = 4096 (net/cookies/parsed_cookie.h)
    if ('set-cookie' in lowercaseHeaders && lowercaseHeaders['set-cookie'].length > 4096) {
      const values = lowercaseHeaders['set-cookie'].split('\n');
      for (let i = 0; i < values.length; ++i) {
        if (values[i].length <= 4096) {
          continue;
        }
        const message = Common.UIString(
            'Set-Cookie header is ignored in response from url: %s. Cookie length should be less than or equal to 4096 characters.',
            response.url);
        this._manager.dispatchEventToListeners(
            Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
      }
    }

    this._updateNetworkRequestWithResponse(networkRequest, response);

    this._updateNetworkRequest(networkRequest);
    this._manager.dispatchEventToListeners(Events.ResponseReceived, networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {number} dataLength
   * @param {number} encodedDataLength
   */
  dataReceived(requestId, time, dataLength, encodedDataLength) {
    let networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      networkRequest = this._maybeAdoptMainResourceRequest(requestId);
    }
    if (!networkRequest) {
      return;
    }

    networkRequest.resourceSize += dataLength;
    if (encodedDataLength !== -1) {
      networkRequest.increaseTransferSize(encodedDataLength);
    }
    networkRequest.endTime = time;

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} finishTime
   * @param {number} encodedDataLength
   * @param {boolean=} shouldReportCorbBlocking
   */
  loadingFinished(requestId, finishTime, encodedDataLength, shouldReportCorbBlocking) {
    let networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      networkRequest = this._maybeAdoptMainResourceRequest(requestId);
    }
    if (!networkRequest) {
      return;
    }
    this._getExtraInfoBuilder(requestId).finished();
    this._finishNetworkRequest(networkRequest, finishTime, encodedDataLength, shouldReportCorbBlocking);
    this._manager.dispatchEventToListeners(Events.LoadingFinished, networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.ResourceType} resourceType
   * @param {string} localizedDescription
   * @param {boolean=} canceled
   * @param {!Protocol.Network.BlockedReason=} blockedReason
   */
  loadingFailed(requestId, time, resourceType, localizedDescription, canceled, blockedReason) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.failed = true;
    networkRequest.setResourceType(Common.resourceTypes[resourceType]);
    networkRequest.canceled = !!canceled;
    if (blockedReason) {
      networkRequest.setBlockedReason(blockedReason);
      if (blockedReason === Protocol.Network.BlockedReason.Inspector) {
        const message = Common.UIString('Request was blocked by DevTools: "%s".', networkRequest.url());
        this._manager.dispatchEventToListeners(
            Events.MessageGenerated, {message: message, requestId: requestId, warning: true});
      }
    }
    networkRequest.localizedFailDescription = localizedDescription;
    this._getExtraInfoBuilder(requestId).finished();
    this._finishNetworkRequest(networkRequest, time, -1);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {string} requestURL
   * @param {!Protocol.Network.Initiator=} initiator
   */
  webSocketCreated(requestId, requestURL, initiator) {
    const networkRequest = new NetworkRequest(requestId, requestURL, '', '', '', initiator || null);
    networkRequest[_networkManagerForRequestSymbol] = this._manager;
    networkRequest.setResourceType(Common.resourceTypes.WebSocket);
    this._startNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.TimeSinceEpoch} wallTime
   * @param {!Protocol.Network.WebSocketRequest} request
   */
  webSocketWillSendHandshakeRequest(requestId, time, wallTime, request) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.requestMethod = 'GET';
    networkRequest.setRequestHeaders(this._headersMapToHeadersArray(request.headers));
    networkRequest.setIssueTime(time, wallTime);

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.WebSocketResponse} response
   */
  webSocketHandshakeResponseReceived(requestId, time, response) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.statusCode = response.status;
    networkRequest.statusText = response.statusText;
    networkRequest.responseHeaders = this._headersMapToHeadersArray(response.headers);
    networkRequest.responseHeadersText = response.headersText || '';
    if (response.requestHeaders) {
      networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
    }
    if (response.requestHeadersText) {
      networkRequest.setRequestHeadersText(response.requestHeadersText);
    }
    networkRequest.responseReceivedTime = time;
    networkRequest.protocol = 'websocket';

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.WebSocketFrame} response
   */
  webSocketFrameReceived(requestId, time, response) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.addProtocolFrame(response, time, false);
    networkRequest.responseReceivedTime = time;

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {!Protocol.Network.WebSocketFrame} response
   */
  webSocketFrameSent(requestId, time, response) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.addProtocolFrame(response, time, true);
    networkRequest.responseReceivedTime = time;

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {string} errorMessage
   */
  webSocketFrameError(requestId, time, errorMessage) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }

    networkRequest.addProtocolFrameError(errorMessage, time);
    networkRequest.responseReceivedTime = time;

    this._updateNetworkRequest(networkRequest);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   */
  webSocketClosed(requestId, time) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }
    this._finishNetworkRequest(networkRequest, time, -1);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {string} eventName
   * @param {string} eventId
   * @param {string} data
   */
  eventSourceMessageReceived(requestId, time, eventName, eventId, data) {
    const networkRequest = this._inflightRequestsById[requestId];
    if (!networkRequest) {
      return;
    }
    networkRequest.addEventSourceMessage(time, eventName, eventId, data);
  }

  /**
   * @override
   * @param {!Protocol.Network.InterceptionId} interceptionId
   * @param {!Protocol.Network.Request} request
   * @param {!Protocol.Page.FrameId} frameId
   * @param {!Protocol.Network.ResourceType} resourceType
   * @param {boolean} isNavigationRequest
   * @param {boolean=} isDownload
   * @param {string=} redirectUrl
   * @param {!Protocol.Network.AuthChallenge=} authChallenge
   * @param {!Protocol.Network.ErrorReason=} responseErrorReason
   * @param {number=} responseStatusCode
   * @param {!Protocol.Network.Headers=} responseHeaders
   * @param {!Protocol.Network.RequestId=} requestId
   */
  requestIntercepted(
      interceptionId, request, frameId, resourceType, isNavigationRequest, isDownload, redirectUrl, authChallenge,
      responseErrorReason, responseStatusCode, responseHeaders, requestId) {
    SDK.multitargetNetworkManager._requestIntercepted(new InterceptedRequest(
        this._manager.target().networkAgent(), interceptionId, request, frameId, resourceType, isNavigationRequest,
        isDownload, redirectUrl, authChallenge, responseErrorReason, responseStatusCode, responseHeaders, requestId));
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Array<!Protocol.Network.BlockedCookieWithReason>} blockedCookies
   * @param {!Protocol.Network.Headers} headers
   */
  requestWillBeSentExtraInfo(requestId, blockedCookies, headers) {
    /** @type {!SDK.NetworkRequest.ExtraRequestInfo} */
    const extraRequestInfo = {
      blockedRequestCookies: blockedCookies.map(blockedCookie => {
        return {blockedReasons: blockedCookie.blockedReasons, cookie: Cookie.fromProtocolCookie(blockedCookie.cookie)};
      }),
      requestHeaders: this._headersMapToHeadersArray(headers)
    };
    this._getExtraInfoBuilder(requestId).addRequestExtraInfo(extraRequestInfo);
  }

  /**
   * @override
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Array<!Protocol.Network.BlockedSetCookieWithReason>} blockedCookies
   * @param {!Protocol.Network.Headers} headers
   * @param {string=} headersText
   */
  responseReceivedExtraInfo(requestId, blockedCookies, headers, headersText) {
    /** @type {!SDK.NetworkRequest.ExtraResponseInfo} */
    const extraResponseInfo = {
      blockedResponseCookies: blockedCookies.map(blockedCookie => {
        return {
          blockedReasons: blockedCookie.blockedReasons,
          cookieLine: blockedCookie.cookieLine,
          cookie: blockedCookie.cookie ? Cookie.fromProtocolCookie(blockedCookie.cookie) : null
        };
      }),
      responseHeaders: this._headersMapToHeadersArray(headers),
      responseHeadersText: headersText
    };
    this._getExtraInfoBuilder(requestId).addResponseExtraInfo(extraResponseInfo);
  }

  /**
   * @suppress {missingOverride}
   * @param {string} url
   * @param {string} firstPartyUrl
   * @param {!Array<!Protocol.Network.BlockedSetCookieWithReason>} blockedCookies
   */
  cookiesChanged(url, firstPartyUrl, blockedCookies) {
    // TODO(chromium:1032063): Implement this protocol message handler.
  }

  /**
   * @param {string} requestId
   * @return {!RedirectExtraInfoBuilder}
   */
  _getExtraInfoBuilder(requestId) {
    if (!this._requestIdToRedirectExtraInfoBuilder.get(requestId)) {
      const deleteCallback = () => {
        this._requestIdToRedirectExtraInfoBuilder.delete(requestId);
      };
      this._requestIdToRedirectExtraInfoBuilder.set(requestId, new RedirectExtraInfoBuilder(deleteCallback));
    }
    return this._requestIdToRedirectExtraInfoBuilder.get(requestId);
  }

  /**
   * @param {!Protocol.Network.RequestId} requestId
   * @param {!Protocol.Network.MonotonicTime} time
   * @param {string} redirectURL
   * @return {!NetworkRequest}
   */
  _appendRedirect(requestId, time, redirectURL) {
    const originalNetworkRequest = this._inflightRequestsById[requestId];
    let redirectCount = 0;
    for (let redirect = originalNetworkRequest.redirectSource(); redirect; redirect = redirect.redirectSource()) {
      redirectCount++;
    }

    originalNetworkRequest.markAsRedirect(redirectCount);
    this._finishNetworkRequest(originalNetworkRequest, time, -1);
    const newNetworkRequest = this._createNetworkRequest(
        requestId, originalNetworkRequest.frameId, originalNetworkRequest.loaderId, redirectURL,
        originalNetworkRequest.documentURL, originalNetworkRequest.initiator());
    newNetworkRequest.setRedirectSource(originalNetworkRequest);
    originalNetworkRequest.setRedirectDestination(newNetworkRequest);
    return newNetworkRequest;
  }

  /**
   * @param {string} requestId
   * @return {?NetworkRequest}
   */
  _maybeAdoptMainResourceRequest(requestId) {
    const request = SDK.multitargetNetworkManager._inflightMainResourceRequests.get(requestId);
    if (!request) {
      return null;
    }
    const oldDispatcher = NetworkManager.forRequest(request)._dispatcher;
    delete oldDispatcher._inflightRequestsById[requestId];
    delete oldDispatcher._inflightRequestsByURL[request.url()];
    this._inflightRequestsById[requestId] = request;
    this._inflightRequestsByURL[request.url()] = request;
    request[_networkManagerForRequestSymbol] = this._manager;
    return request;
  }

  /**
   * @param {!NetworkRequest} networkRequest
   */
  _startNetworkRequest(networkRequest) {
    this._inflightRequestsById[networkRequest.requestId()] = networkRequest;
    this._inflightRequestsByURL[networkRequest.url()] = networkRequest;
    // The following relies on the fact that loaderIds and requestIds are
    // globally unique and that the main request has them equal.
    if (networkRequest.loaderId === networkRequest.requestId()) {
      SDK.multitargetNetworkManager._inflightMainResourceRequests.set(networkRequest.requestId(), networkRequest);
    }

    this._manager.dispatchEventToListeners(Events.RequestStarted, networkRequest);
  }

  /**
   * @param {!NetworkRequest} networkRequest
   */
  _updateNetworkRequest(networkRequest) {
    this._manager.dispatchEventToListeners(Events.RequestUpdated, networkRequest);
  }

  /**
   * @param {!NetworkRequest} networkRequest
   * @param {!Protocol.Network.MonotonicTime} finishTime
   * @param {number} encodedDataLength
   * @param {boolean=} shouldReportCorbBlocking
   */
  _finishNetworkRequest(networkRequest, finishTime, encodedDataLength, shouldReportCorbBlocking) {
    networkRequest.endTime = finishTime;
    networkRequest.finished = true;
    if (encodedDataLength >= 0) {
      const redirectSource = networkRequest.redirectSource();
      if (redirectSource && redirectSource.signedExchangeInfo()) {
        networkRequest.setTransferSize(0);
        redirectSource.setTransferSize(encodedDataLength);
        this._updateNetworkRequest(redirectSource);
      } else {
        networkRequest.setTransferSize(encodedDataLength);
      }
    }
    this._manager.dispatchEventToListeners(Events.RequestFinished, networkRequest);
    delete this._inflightRequestsById[networkRequest.requestId()];
    delete this._inflightRequestsByURL[networkRequest.url()];
    SDK.multitargetNetworkManager._inflightMainResourceRequests.delete(networkRequest.requestId());

    if (shouldReportCorbBlocking) {
      const message = Common.UIString(
          `Cross-Origin Read Blocking (CORB) blocked cross-origin response %s with MIME type %s. See https://www.chromestatus.com/feature/5629709824032768 for more details.`,
          networkRequest.url(), networkRequest.mimeType);
      this._manager.dispatchEventToListeners(
          Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: true});
    }

    if (Common.moduleSetting('monitoringXHREnabled').get() &&
        networkRequest.resourceType().category() === Common.resourceCategories.XHR) {
      let message;
      const failedToLoad = networkRequest.failed || networkRequest.hasErrorStatusCode();
      if (failedToLoad) {
        message = Common.UIString(
            '%s failed loading: %s "%s".', networkRequest.resourceType().title(), networkRequest.requestMethod,
            networkRequest.url());
      } else {
        message = Common.UIString(
            '%s finished loading: %s "%s".', networkRequest.resourceType().title(), networkRequest.requestMethod,
            networkRequest.url());
      }

      this._manager.dispatchEventToListeners(
          Events.MessageGenerated, {message: message, requestId: networkRequest.requestId(), warning: false});
    }
  }

  /**
   * @param {!Protocol.Network.RequestId} requestId
   * @param {string} frameId
   * @param {!Protocol.Network.LoaderId} loaderId
   * @param {string} url
   * @param {string} documentURL
   * @param {?Protocol.Network.Initiator} initiator
   */
  _createNetworkRequest(requestId, frameId, loaderId, url, documentURL, initiator) {
    const request = new NetworkRequest(requestId, url, documentURL, frameId, loaderId, initiator);
    request[_networkManagerForRequestSymbol] = this._manager;
    return request;
  }
}

/**
 * @implements {SDKModelObserver<!NetworkManager>}
 * @unrestricted
 */
export class MultitargetNetworkManager extends Common.Object {
  constructor() {
    super();
    this._userAgentOverride = '';
    /** @type {!Set<!Protocol.NetworkAgent>} */
    this._agents = new Set();
    /** @type {!Map<string, !NetworkRequest>} */
    this._inflightMainResourceRequests = new Map();
    /** @type {!SDK.NetworkManager.Conditions} */
    this._networkConditions = NoThrottlingConditions;
    /** @type {?Promise} */
    this._updatingInterceptionPatternsPromise = null;

    // TODO(allada) Remove these and merge it with request interception.
    this._blockingEnabledSetting = Common.moduleSetting('requestBlockingEnabled');
    this._blockedPatternsSetting = Common.settings.createSetting('networkBlockedPatterns', []);
    this._effectiveBlockedURLs = [];
    this._updateBlockedPatterns();

    /** @type {!Platform.Multimap<!SDK.MultitargetNetworkManager.RequestInterceptor, !SDK.MultitargetNetworkManager.InterceptionPattern>} */
    this._urlsForRequestInterceptor = new Platform.Multimap();

    SDK.targetManager.observeModels(NetworkManager, this);
  }

  /**
   * @param {string} uaString
   * @return {string}
   */
  static patchUserAgentWithChromeVersion(uaString) {
    // Patches Chrome/CriOS version from user agent ("1.2.3.4" when user agent is: "Chrome/1.2.3.4").
    // Edge also contains an appVersion which should be patched to match the Chrome major version.
    // Otherwise, ignore it. This assumes additional appVersions appear after the Chrome version.
    const chromeRegex = new RegExp('(?:^|\\W)Chrome/(\\S+)');
    const chromeMatch = navigator.userAgent.match(chromeRegex);
    if (chromeMatch && chromeMatch.length > 1) {
      // "1.2.3.4" becomes "1.0.100.0"
      const additionalAppVersion = chromeMatch[1].split('.', 1)[0] + '.0.100.0';
      return String.sprintf(uaString, chromeMatch[1], additionalAppVersion);
    }
    return uaString;
  }

  /**
   * @override
   * @param {!NetworkManager} networkManager
   */
  modelAdded(networkManager) {
    const networkAgent = networkManager.target().networkAgent();
    if (this._extraHeaders) {
      networkAgent.setExtraHTTPHeaders(this._extraHeaders);
    }
    if (this._currentUserAgent()) {
      networkAgent.setUserAgentOverride(this._currentUserAgent());
    }
    if (this._effectiveBlockedURLs.length) {
      networkAgent.setBlockedURLs(this._effectiveBlockedURLs);
    }
    if (this.isIntercepting()) {
      networkAgent.setRequestInterception(this._urlsForRequestInterceptor.valuesArray());
    }
    this._agents.add(networkAgent);
    if (this.isThrottling()) {
      this._updateNetworkConditions(networkAgent);
    }
  }

  /**
   * @override
   * @param {!NetworkManager} networkManager
   */
  modelRemoved(networkManager) {
    for (const entry of this._inflightMainResourceRequests) {
      const manager = NetworkManager.forRequest(/** @type {!NetworkRequest} */ (entry[1]));
      if (manager !== networkManager) {
        continue;
      }
      this._inflightMainResourceRequests.delete(/** @type {string} */ (entry[0]));
    }
    this._agents.delete(networkManager.target().networkAgent());
  }

  /**
   * @return {boolean}
   */
  isThrottling() {
    return this._networkConditions.download >= 0 || this._networkConditions.upload >= 0 ||
        this._networkConditions.latency > 0;
  }

  /**
   * @return {boolean}
   */
  isOffline() {
    return !this._networkConditions.download && !this._networkConditions.upload;
  }

  /**
   * @param {!SDK.NetworkManager.Conditions} conditions
   */
  setNetworkConditions(conditions) {
    this._networkConditions = conditions;
    for (const agent of this._agents) {
      this._updateNetworkConditions(agent);
    }
    this.dispatchEventToListeners(MultitargetNetworkManager.Events.ConditionsChanged);
  }

  /**
   * @return {!SDK.NetworkManager.Conditions}
   */
  networkConditions() {
    return this._networkConditions;
  }

  /**
   * @param {!Protocol.NetworkAgent} networkAgent
   */
  _updateNetworkConditions(networkAgent) {
    const conditions = this._networkConditions;
    if (!this.isThrottling()) {
      networkAgent.emulateNetworkConditions(false, 0, 0, 0);
    } else {
      networkAgent.emulateNetworkConditions(
          this.isOffline(), conditions.latency, conditions.download < 0 ? 0 : conditions.download,
          conditions.upload < 0 ? 0 : conditions.upload, NetworkManager._connectionType(conditions));
    }
  }

  /**
   * @param {!Protocol.Network.Headers} headers
   */
  setExtraHTTPHeaders(headers) {
    this._extraHeaders = headers;
    for (const agent of this._agents) {
      agent.setExtraHTTPHeaders(this._extraHeaders);
    }
  }

  /**
   * @return {string}
   */
  _currentUserAgent() {
    return this._customUserAgent ? this._customUserAgent : this._userAgentOverride;
  }

  _updateUserAgentOverride() {
    const userAgent = this._currentUserAgent();
    for (const agent of this._agents) {
      agent.setUserAgentOverride(userAgent);
    }
  }

  /**
   * @param {string} userAgent
   */
  setUserAgentOverride(userAgent) {
    if (this._userAgentOverride === userAgent) {
      return;
    }
    this._userAgentOverride = userAgent;
    if (!this._customUserAgent) {
      this._updateUserAgentOverride();
    }
    this.dispatchEventToListeners(MultitargetNetworkManager.Events.UserAgentChanged);
  }

  /**
   * @return {string}
   */
  userAgentOverride() {
    return this._userAgentOverride;
  }

  /**
   * @param {string} userAgent
   */
  setCustomUserAgentOverride(userAgent) {
    this._customUserAgent = userAgent;
    this._updateUserAgentOverride();
  }

  // TODO(allada) Move all request blocking into interception and let view manage blocking.
  /**
   * @return {!Array<!SDK.NetworkManager.BlockedPattern>}
   */
  blockedPatterns() {
    return this._blockedPatternsSetting.get().slice();
  }

  /**
   * @return {boolean}
   */
  blockingEnabled() {
    return this._blockingEnabledSetting.get();
  }

  /**
   * @return {boolean}
   */
  isBlocking() {
    return !!this._effectiveBlockedURLs.length;
  }

  /**
   * @param {!Array<!SDK.NetworkManager.BlockedPattern>} patterns
   */
  setBlockedPatterns(patterns) {
    this._blockedPatternsSetting.set(patterns);
    this._updateBlockedPatterns();
    this.dispatchEventToListeners(MultitargetNetworkManager.Events.BlockedPatternsChanged);
  }

  /**
   * @param {boolean} enabled
   */
  setBlockingEnabled(enabled) {
    if (this._blockingEnabledSetting.get() === enabled) {
      return;
    }
    this._blockingEnabledSetting.set(enabled);
    this._updateBlockedPatterns();
    this.dispatchEventToListeners(MultitargetNetworkManager.Events.BlockedPatternsChanged);
  }

  _updateBlockedPatterns() {
    const urls = [];
    if (this._blockingEnabledSetting.get()) {
      for (const pattern of this._blockedPatternsSetting.get()) {
        if (pattern.enabled) {
          urls.push(pattern.url);
        }
      }
    }

    if (!urls.length && !this._effectiveBlockedURLs.length) {
      return;
    }
    this._effectiveBlockedURLs = urls;
    for (const agent of this._agents) {
      agent.setBlockedURLs(this._effectiveBlockedURLs);
    }
  }

  /**
   * @return {boolean}
   */
  isIntercepting() {
    return !!this._urlsForRequestInterceptor.size;
  }

  /**
   * @param {!Array<!SDK.MultitargetNetworkManager.InterceptionPattern>} patterns
   * @param {!SDK.MultitargetNetworkManager.RequestInterceptor} requestInterceptor
   * @return {!Promise}
   */
  setInterceptionHandlerForPatterns(patterns, requestInterceptor) {
    // Note: requestInterceptors may recieve interception requests for patterns they did not subscribe to.
    this._urlsForRequestInterceptor.deleteAll(requestInterceptor);
    for (const newPattern of patterns) {
      this._urlsForRequestInterceptor.set(requestInterceptor, newPattern);
    }
    return this._updateInterceptionPatternsOnNextTick();
  }

  /**
   * @return {!Promise}
   */
  _updateInterceptionPatternsOnNextTick() {
    // This is used so we can register and unregister patterns in loops without sending lots of protocol messages.
    if (!this._updatingInterceptionPatternsPromise) {
      this._updatingInterceptionPatternsPromise = Promise.resolve().then(this._updateInterceptionPatterns.bind(this));
    }
    return this._updatingInterceptionPatternsPromise;
  }

  /**
   * @return {!Promise}
   */
  _updateInterceptionPatterns() {
    if (!Common.moduleSetting('cacheDisabled').get()) {
      Common.moduleSetting('cacheDisabled').set(true);
    }
    this._updatingInterceptionPatternsPromise = null;
    const promises = /** @type {!Array<!Promise>} */ ([]);
    for (const agent of this._agents) {
      promises.push(agent.setRequestInterception(this._urlsForRequestInterceptor.valuesArray()));
    }
    this.dispatchEventToListeners(MultitargetNetworkManager.Events.InterceptorsChanged);
    return Promise.all(promises);
  }

  /**
   * @param {!InterceptedRequest} interceptedRequest
   */
  async _requestIntercepted(interceptedRequest) {
    for (const requestInterceptor of this._urlsForRequestInterceptor.keysArray()) {
      await requestInterceptor(interceptedRequest);
      if (interceptedRequest.hasResponded()) {
        return;
      }
    }
    if (!interceptedRequest.hasResponded()) {
      interceptedRequest.continueRequestWithoutChange();
    }
  }

  clearBrowserCache() {
    for (const agent of this._agents) {
      agent.clearBrowserCache();
    }
  }

  clearBrowserCookies() {
    for (const agent of this._agents) {
      agent.clearBrowserCookies();
    }
  }

  /**
   * @param {string} origin
   * @return {!Promise<!Array<string>>}
   */
  getCertificate(origin) {
    const target = SDK.targetManager.mainTarget();
    return target.networkAgent().getCertificate(origin).then(certificate => certificate || []);
  }

  /**
   * @param {string} url
   * @param {function(number, !Object.<string, string>, string, number)} callback
   */
  loadResource(url, callback) {
    const headers = {};

    const currentUserAgent = this._currentUserAgent();
    if (currentUserAgent) {
      headers['User-Agent'] = currentUserAgent;
    }

    if (Common.moduleSetting('cacheDisabled').get()) {
      headers['Cache-Control'] = 'no-cache';
    }

    Host.ResourceLoader.load(url, headers, callback);
  }
}

/** @enum {symbol} */
MultitargetNetworkManager.Events = {
  BlockedPatternsChanged: Symbol('BlockedPatternsChanged'),
  ConditionsChanged: Symbol('ConditionsChanged'),
  UserAgentChanged: Symbol('UserAgentChanged'),
  InterceptorsChanged: Symbol('InterceptorsChanged')
};

export class InterceptedRequest {
  /**
   * @param {!Protocol.NetworkAgent} networkAgent
   * @param {!Protocol.Network.InterceptionId} interceptionId
   * @param {!Protocol.Network.Request} request
   * @param {!Protocol.Page.FrameId} frameId
   * @param {!Protocol.Network.ResourceType} resourceType
   * @param {boolean} isNavigationRequest
   * @param {boolean=} isDownload
   * @param {string=} redirectUrl
   * @param {!Protocol.Network.AuthChallenge=} authChallenge
   * @param {!Protocol.Network.ErrorReason=} responseErrorReason
   * @param {number=} responseStatusCode
   * @param {!Protocol.Network.Headers=} responseHeaders
   * @param {!Protocol.Network.RequestId=} requestId
   */
  constructor(
      networkAgent, interceptionId, request, frameId, resourceType, isNavigationRequest, isDownload, redirectUrl,
      authChallenge, responseErrorReason, responseStatusCode, responseHeaders, requestId) {
    this._networkAgent = networkAgent;
    this._interceptionId = interceptionId;
    this._hasResponded = false;
    this.request = request;
    this.frameId = frameId;
    this.resourceType = resourceType;
    this.isNavigationRequest = isNavigationRequest;
    this.isDownload = !!isDownload;
    this.redirectUrl = redirectUrl;
    this.authChallenge = authChallenge;
    this.responseErrorReason = responseErrorReason;
    this.responseStatusCode = responseStatusCode;
    this.responseHeaders = responseHeaders;
    this.requestId = requestId;
  }

  /**
   * @return {boolean}
   */
  hasResponded() {
    return this._hasResponded;
  }

  /**
   * @param {!Blob} contentBlob
   */
  async continueRequestWithContent(contentBlob) {
    this._hasResponded = true;
    const headers = [
      'HTTP/1.1 200 OK',
      'Date: ' + (new Date()).toUTCString(),
      'Server: Chrome Devtools Request Interceptor',
      'Connection: closed',
      'Content-Length: ' + contentBlob.size,
      'Content-Type: ' + contentBlob.type || 'text/x-unknown',
    ];
    const encodedResponse = await blobToBase64(new Blob([headers.join('\r\n'), '\r\n\r\n', contentBlob]));
    this._networkAgent.continueInterceptedRequest(this._interceptionId, undefined, encodedResponse);

    /**
     * @param {!Blob} blob
     * @return {!Promise<string>}
     */
    async function blobToBase64(blob) {
      const reader = new FileReader();
      const fileContentsLoadedPromise = new Promise(resolve => reader.onloadend = resolve);
      reader.readAsDataURL(blob);
      await fileContentsLoadedPromise;
      if (reader.error) {
        console.error('Could not convert blob to base64.', reader.error);
        return '';
      }
      const result = reader.result;
      if (result === undefined) {
        console.error('Could not convert blob to base64.');
        return '';
      }
      return result.substring(result.indexOf(',') + 1);
    }
  }

  continueRequestWithoutChange() {
    console.assert(!this._hasResponded);
    this._hasResponded = true;
    this._networkAgent.continueInterceptedRequest(this._interceptionId);
  }

  /**
   * @param {!Protocol.Network.ErrorReason} errorReason
   */
  continueRequestWithError(errorReason) {
    console.assert(!this._hasResponded);
    this._hasResponded = true;
    this._networkAgent.continueInterceptedRequest(this._interceptionId, errorReason);
  }

  /**
   * @return {!Promise<!SDK.NetworkRequest.ContentData>}
   */
  async responseBody() {
    const response =
        await this._networkAgent.invoke_getResponseBodyForInterception({interceptionId: this._interceptionId});
    const error = response[Protocol.Error] || null;
    return {error: error, content: error ? null : response.body, encoded: response.base64Encoded};
  }
}

/**
 * Helper class to match requests created from requestWillBeSent with
 * requestWillBeSentExtraInfo and responseReceivedExtraInfo when they have the
 * same requestId due to redirects.
 */
class RedirectExtraInfoBuilder {
  /**
   * @param {function()} deleteCallback
   */
  constructor(deleteCallback) {
    /** @type {!Array<!NetworkRequest>} */
    this._requests = [];
    /** @type {!Array<?SDK.NetworkRequest.ExtraRequestInfo>} */
    this._requestExtraInfos = [];
    /** @type {!Array<?SDK.NetworkRequest.ExtraResponseInfo>} */
    this._responseExtraInfos = [];
    /** @type {boolean} */
    this._finished = false;
    /** @type {boolean} */
    this._hasExtraInfo = false;
    /** @type {function()} */
    this._deleteCallback = deleteCallback;
  }

  /**
   * @param {!NetworkRequest} req
   */
  addRequest(req) {
    this._requests.push(req);
    this._sync(this._requests.length - 1);
  }

  /**
   * @param {!SDK.NetworkRequest.ExtraRequestInfo} info
   */
  addRequestExtraInfo(info) {
    this._hasExtraInfo = true;
    this._requestExtraInfos.push(info);
    this._sync(this._requestExtraInfos.length - 1);
  }

  /**
   * @param {!SDK.NetworkRequest.ExtraResponseInfo} info
   */
  addResponseExtraInfo(info) {
    this._responseExtraInfos.push(info);
    this._sync(this._responseExtraInfos.length - 1);
  }

  finished() {
    this._finished = true;
    this._deleteIfComplete();
  }

  /**
   * @param {number} index
   */
  _sync(index) {
    const req = this._requests[index];
    if (!req) {
      return;
    }

    const requestExtraInfo = this._requestExtraInfos[index];
    if (requestExtraInfo) {
      req.addExtraRequestInfo(requestExtraInfo);
      this._requestExtraInfos[index] = null;
    }

    const responseExtraInfo = this._responseExtraInfos[index];
    if (responseExtraInfo) {
      req.addExtraResponseInfo(responseExtraInfo);
      this._responseExtraInfos[index] = null;
    }

    this._deleteIfComplete();
  }

  _deleteIfComplete() {
    if (!this._finished) {
      return;
    }

    if (this._hasExtraInfo) {
      // if we haven't gotten the last responseExtraInfo event, we have to wait for it.
      if (!this._requests.peekLast().hasExtraResponseInfo()) {
        return;
      }
    }

    this._deleteCallback();
  }
}

SDKModel.register(NetworkManager, Capability.Network, true);
