/*
 * Copyright (C) 2013-2019 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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.
 */

// FIXME: NetworkManager lacks advanced multi-target support. (Network.loadResource invocations per-target)

WI.NetworkManager = class NetworkManager extends WI.Object
{
    constructor()
    {
        super();

        this._frameIdentifierMap = new Map;
        this._mainFrame = null;
        this._resourceRequestIdentifierMap = new Map;
        this._orphanedResources = new Map;
        this._webSocketIdentifierToURL = new Map;

        this._waitingForMainFrameResourceTreePayload = true;
        this._transitioningPageTarget = false;

        this._sourceMapURLMap = new Map;
        this._downloadingSourceMaps = new Set;

        this._localResourceOverrides = [];
        this._harImportLocalResourceMap = new Set;

        this._pendingLocalResourceOverrideSaves = null;
        this._saveLocalResourceOverridesDebouncer = null;

        // FIXME: Provide dedicated UI to toggle Network Interception globally?
        this._interceptionEnabled = true;

        // COMPATIBILITY (iOS 14.0): Inspector.activateExtraDomains was removed in favor of a declared debuggable type
        WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._extraDomainsActivated, this);

        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);

        if (NetworkManager.supportsOverridingResponses()) {
            WI.Resource.addEventListener(WI.SourceCode.Event.ContentDidChange, this._handleResourceContentChangedForLocalResourceOverride, this);
            WI.Resource.addEventListener(WI.Resource.Event.RequestDataDidChange, this._handleResourceContentChangedForLocalResourceOverride, this);
            WI.LocalResourceOverride.addEventListener(WI.LocalResourceOverride.Event.DisabledChanged, this._handleResourceOverrideDisabledChanged, this);

            WI.Target.registerInitializationPromise((async () => {
                let serializedLocalResourceOverrides = await WI.objectStores.localResourceOverrides.getAll();

                this._restoringLocalResourceOverrides = true;
                for (let serializedLocalResourceOverride of serializedLocalResourceOverrides) {
                    let localResourceOverride = WI.LocalResourceOverride.fromJSON(serializedLocalResourceOverride);

                    let supported = false;
                    switch (localResourceOverride.type) {
                    case WI.LocalResourceOverride.InterceptType.Request:
                        supported = WI.NetworkManager.supportsOverridingRequests();
                        break;

                    case WI.LocalResourceOverride.InterceptType.Response:
                        supported = WI.NetworkManager.supportsOverridingResponses();
                        break;

                    case WI.LocalResourceOverride.InterceptType.ResponseSkippingNetwork:
                        supported = WI.NetworkManager.supportsOverridingRequestsWithResponses();
                        break;
                    }
                    if (!supported)
                        continue;

                    const key = null;
                    WI.objectStores.localResourceOverrides.associateObject(localResourceOverride, key, serializedLocalResourceOverride);

                    this.addLocalResourceOverride(localResourceOverride);
                }
                this._restoringLocalResourceOverrides = false;
            })());
        }

        this._bootstrapScript = null;
        if (NetworkManager.supportsBootstrapScript()) {
            this._bootstrapScriptEnabledSetting = new WI.Setting("bootstrap-script-enabled", true);

            WI.Target.registerInitializationPromise((async () => {
                let bootstrapScriptSource = await WI.objectStores.general.get(NetworkManager.bootstrapScriptSourceObjectStoreKey);
                if (bootstrapScriptSource !== undefined)
                    this.createBootstrapScript(bootstrapScriptSource);
            })());
        }
    }

    // Static

    static supportsShowCertificate()
    {
        return InspectorFrontendHost.supportsShowCertificate
            && InspectorBackend.hasCommand("Network.getSerializedCertificate");
    }

    static supportsOverridingRequests()
    {
        // COMPATIBILITY (iOS 13.4): Network.interceptWithRequest did not exist yet.
        return InspectorBackend.hasCommand("Network.interceptWithRequest");
    }

    static supportsOverridingRequestsWithResponses()
    {
        // COMPATIBILITY (iOS 13.4): Network.interceptRequestWithResponse did not exist yet.
        return InspectorBackend.hasCommand("Network.interceptRequestWithResponse");
    }

    static supportsOverridingResponses()
    {
        // COMPATIBILITY (iOS 13.0): Network.interceptWithResponse did not exist yet.
        return InspectorBackend.hasCommand("Network.interceptWithResponse");
    }

    static supportsBootstrapScript()
    {
        return InspectorBackend.hasCommand("Page.setBootstrapScript");
    }

    static get bootstrapScriptURL()
    {
        return "web-inspector://bootstrap.js";
    }

    static get bootstrapScriptSourceObjectStoreKey()
    {
        return "bootstrap-script-source";
    }

    static synthesizeImportError(message)
    {
        message = WI.UIString("HAR Import Error: %s").format(message);

        if (window.InspectorTest) {
            console.error(message);
            return;
        }

        let consoleMessage = new WI.ConsoleMessage(WI.mainTarget, WI.ConsoleMessage.MessageSource.Other, WI.ConsoleMessage.MessageLevel.Error, message);
        consoleMessage.shouldRevealConsole = true;

        WI.consoleLogViewController.appendConsoleMessage(consoleMessage);
    }

    // Target

    initializeTarget(target)
    {
        if (target.hasDomain("Page")) {
            target.PageAgent.enable();
            target.PageAgent.getResourceTree(this._processMainFrameResourceTreePayload.bind(this));

            // COMPATIBILITY (iOS 13.0): Page.setBootstrapScript did not exist yet.
            if (target.hasCommand("Page.setBootstrapScript") && this._bootstrapScript && this._bootstrapScriptEnabledSetting.value)
                target.PageAgent.setBootstrapScript(this._bootstrapScript.content);
        }

        if (target.hasDomain("ServiceWorker"))
            target.ServiceWorkerAgent.getInitializationInfo(this._processServiceWorkerConfiguration.bind(this));

        if (target.hasDomain("Network")) {
            target.NetworkAgent.enable();

            // COMPATIBILITY (iOS 10.3): Network.setDisableResourceCaching did not exist.
            if (target.hasCommand("Network.setResourceCachingDisabled"))
                target.NetworkAgent.setResourceCachingDisabled(WI.settings.resourceCachingDisabled.value);

            // COMPATIBILITY (iOS 13.0): Network.setInterceptionEnabled did not exist.
            if (target.hasCommand("Network.setInterceptionEnabled")) {
                if (this._interceptionEnabled)
                    target.NetworkAgent.setInterceptionEnabled(this._interceptionEnabled);

                for (let localResourceOverride of this._localResourceOverrides) {
                    if (!localResourceOverride.disabled)
                        this._addInterception(localResourceOverride, target);
                }
            }
        }

        if (target.type === WI.TargetType.Worker)
            this.adoptOrphanedResourcesForTarget(target);
    }

    transitionPageTarget()
    {
        this._transitioningPageTarget = true;
        this._waitingForMainFrameResourceTreePayload = true;
    }

    // Public

    get mainFrame() { return this._mainFrame; }
    get localResourceOverrides() { return this._localResourceOverrides; }
    get bootstrapScript() { return this._bootstrapScript; }

    get frames()
    {
        return Array.from(this._frameIdentifierMap.values());
    }

    get interceptionEnabled()
    {
        return this._interceptionEnabled;
    }

    set interceptionEnabled(enabled)
    {
        if (this._interceptionEnabled === enabled)
            return;

        this._interceptionEnabled = enabled;

        for (let target of WI.targets) {
            // COMPATIBILITY (iOS 13.0): Network.setInterceptionEnabled did not exist.
            if (target.hasCommand("Network.setInterceptionEnabled"))
                target.NetworkAgent.setInterceptionEnabled(this._interceptionEnabled);
        }
    }

    frameForIdentifier(frameId)
    {
        return this._frameIdentifierMap.get(frameId) || null;
    }

    resourceForRequestIdentifier(requestIdentifier)
    {
        return this._resourceRequestIdentifierMap.get(requestIdentifier) || null;
    }

    downloadSourceMap(sourceMapURL, baseURL, originalSourceCode)
    {
        if (!WI.settings.sourceMapsEnabled.value)
            return;

        // The baseURL could have come from a "//# sourceURL". Attempt to get a
        // reasonable absolute URL for the base by using the main resource's URL.
        if (WI.networkManager.mainFrame)
            baseURL = absoluteURL(baseURL, WI.networkManager.mainFrame.url);

        if (sourceMapURL.startsWith("data:")) {
            this._loadAndParseSourceMap(sourceMapURL, baseURL, originalSourceCode);
            return;
        }

        sourceMapURL = absoluteURL(sourceMapURL, baseURL);
        if (!sourceMapURL)
            return;

        console.assert(originalSourceCode.url);
        if (!originalSourceCode.url)
            return;

        // FIXME: <rdar://problem/13265694> Source Maps: Better handle when multiple resources reference the same SourceMap

        if (this._sourceMapURLMap.has(sourceMapURL) || this._downloadingSourceMaps.has(sourceMapURL))
            return;

        let loadAndParseSourceMap = () => {
            this._loadAndParseSourceMap(sourceMapURL, baseURL, originalSourceCode);
        };

        if (!WI.networkManager.mainFrame) {
            // If we don't have a main frame, then we are likely in the middle of building the resource tree.
            // Delaying until the next runloop is enough in this case to then start loading the source map.
            setTimeout(loadAndParseSourceMap, 0);
            return;
        }

        loadAndParseSourceMap();
    }

    get bootstrapScriptEnabled()
    {
        console.assert(NetworkManager.supportsBootstrapScript());
        console.assert(this._bootstrapScript);

        return this._bootstrapScriptEnabledSetting.value;
    }

    set bootstrapScriptEnabled(enabled)
    {
        console.assert(NetworkManager.supportsBootstrapScript());
        console.assert(this._bootstrapScript);

        this._bootstrapScriptEnabledSetting.value = !!enabled;

        let source = this._bootstrapScriptEnabledSetting.value ? this._bootstrapScript.content : undefined;

        // COMPATIBILITY (iOS 13.0): Page.setBootstrapScript did not exist yet.
        for (let target of WI.targets) {
            if (target.hasCommand("Page.setBootstrapScript"))
                target.PageAgent.setBootstrapScript(source);
        }

        this.dispatchEventToListeners(NetworkManager.Event.BootstrapScriptEnabledChanged, {bootstrapScript: this._bootstrapScript});
    }

    async createBootstrapScript(source)
    {
        console.assert(NetworkManager.supportsBootstrapScript());

        if (this._bootstrapScript)
            return;

        if (!arguments.length)
            source = await WI.objectStores.general.get(NetworkManager.bootstrapScriptSourceObjectStoreKey);

        if (!source) {
            source = `
/*
 * ${WI.UIString("The Inspector Bootstrap Script is guaranteed to be the first script evaluated in any page, as well as any sub-frames.")}
 * ${WI.UIString("It is evaluated immediately after the global object is created, before any other content has loaded.")}
 * 
 * ${WI.UIString("Modifications made here will take effect on the next load of any page or sub-frame.")}
 * ${WI.UIString("The contents and enabled state will be preserved across Web Inspector sessions.")}
 * 
 * ${WI.UIString("Some examples of ways to use this script include (but are not limited to):")}
 *  - ${WI.UIString("overriding built-in functions to log call traces or add %s statements").format(WI.unlocalizedString("`debugger`"))}
 *  - ${WI.UIString("ensuring that common debugging functions are available on every page via the Console")}
 * 
 * ${WI.UIString("More information is available at <https://webkit.org/web-inspector/inspector-bootstrap-script/>.")}
 */
`.trimStart();
        }

        const target = null;
        const url = null;
        const sourceURL = NetworkManager.bootstrapScriptURL;
        this._bootstrapScript = new WI.LocalScript(target, url, sourceURL, WI.Script.SourceType.Program, source, {injected: true, editable: true});
        this._bootstrapScript.addEventListener(WI.SourceCode.Event.ContentDidChange, this._handleBootstrapScriptContentDidChange, this);
        this._handleBootstrapScriptContentDidChange();

        this.dispatchEventToListeners(NetworkManager.Event.BootstrapScriptCreated, {bootstrapScript: this._bootstrapScript});
    }

    destroyBootstrapScript()
    {
        console.assert(NetworkManager.supportsBootstrapScript());

        if (!this._bootstrapScript)
            return;

        let bootstrapScript = this._bootstrapScript;

        this._bootstrapScript = null;
        WI.objectStores.general.delete(NetworkManager.bootstrapScriptSourceObjectStoreKey);

        // COMPATIBILITY (iOS 13.0): Page.setBootstrapScript did not exist yet.
        for (let target of WI.targets) {
            if (target.hasCommand("Page.setBootstrapScript"))
                target.PageAgent.setBootstrapScript();
        }

        this.dispatchEventToListeners(NetworkManager.Event.BootstrapScriptDestroyed, {bootstrapScript});
    }

    addLocalResourceOverride(localResourceOverride)
    {
        console.assert(localResourceOverride instanceof WI.LocalResourceOverride);

        console.assert(!this._localResourceOverrides.includes(localResourceOverride));
        this._localResourceOverrides.push(localResourceOverride);

        if (!this._restoringLocalResourceOverrides)
            WI.objectStores.localResourceOverrides.putObject(localResourceOverride);

        if (!localResourceOverride.disabled)
            this._addInterception(localResourceOverride);

        this.dispatchEventToListeners(WI.NetworkManager.Event.LocalResourceOverrideAdded, {localResourceOverride});
    }

    removeLocalResourceOverride(localResourceOverride)
    {
        console.assert(localResourceOverride instanceof WI.LocalResourceOverride);

        if (!this._localResourceOverrides.remove(localResourceOverride)) {
            console.assert(false, "Attempted to remove a local resource override that was not known.");
            return;
        }

        if (this._pendingLocalResourceOverrideSaves)
            this._pendingLocalResourceOverrideSaves.delete(localResourceOverride);

        if (!this._restoringLocalResourceOverrides)
            WI.objectStores.localResourceOverrides.deleteObject(localResourceOverride);

        if (!localResourceOverride.disabled)
            this._removeInterception(localResourceOverride);

        this.dispatchEventToListeners(WI.NetworkManager.Event.LocalResourceOverrideRemoved, {localResourceOverride});
    }

    localResourceOverridesForURL(url)
    {
        // Order local resource overrides based on how closely they match the given URL. As an example,
        // a regular expression is likely going to match more URLs than a case-insensitive string.
        const rankFunctions = [
            (localResourceOverride) => localResourceOverride.isCaseSensitive && !localResourceOverride.isRegex,  // exact match
            (localResourceOverride) => !localResourceOverride.isCaseSensitive && !localResourceOverride.isRegex, // case-insensitive
            (localResourceOverride) => localResourceOverride.isCaseSensitive && localResourceOverride.isRegex,   // case-sensitive regex
            (localResourceOverride) => !localResourceOverride.isCaseSensitive && localResourceOverride.isRegex,  // case-insensitive regex
        ];
        return this._localResourceOverrides
            .filter((localResourceOverride) => localResourceOverride.matches(url))
            .sort((a, b) => {
                let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
                let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
                return aRank - bRank;
            });
    }

    canBeOverridden(resource)
    {
        if (!(resource instanceof WI.Resource))
            return false;

        if (resource instanceof WI.SourceMapResource)
            return false;

        if (resource.localResourceOverride)
            return false;

        const schemes = ["http:", "https:", "file:"];
        if (!schemes.some((scheme) => resource.url.startsWith(scheme)))
            return false;

        if (this.localResourceOverridesForURL(resource.url).length)
            return false;

        switch (resource.type) {
        case WI.Resource.Type.Document:
        case WI.Resource.Type.StyleSheet:
        case WI.Resource.Type.Script:
        case WI.Resource.Type.XHR:
        case WI.Resource.Type.Fetch:
        case WI.Resource.Type.Image:
        case WI.Resource.Type.Font:
        case WI.Resource.Type.Other:
            break;
        case WI.Resource.Type.Ping:
        case WI.Resource.Type.Beacon:
            // Responses aren't really expected for Ping/Beacon.
            return false;
        case WI.Resource.Type.WebSocket:
            // Non-HTTP traffic.
            console.assert(false, "Scheme check above should have been sufficient.");
            return false;
        }

        return true;
    }

    resourcesForURL(url)
    {
        let resources = new Set;
        if (this._mainFrame) {
            if (this._mainFrame.mainResource.url === url)
                resources.add(this._mainFrame.mainResource);

            const recursivelySearchChildFrames = true;
            resources.addAll(this._mainFrame.resourcesForURL(url, recursivelySearchChildFrames));
        }
        return resources;
    }

    adoptOrphanedResourcesForTarget(target)
    {
        let resources = this._orphanedResources.take(target.identifier);
        if (!resources)
            return;

        for (let resource of resources)
            target.adoptResource(resource);
    }

    processHAR({json, error})
    {
        if (error) {
            WI.NetworkManager.synthesizeImportError(error);
            return null;
        }

        if (typeof json !== "object" || json === null) {
            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid JSON"));
            return null;
        }

        if (typeof json.log !== "object" || typeof json.log.version !== "string") {
            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
            return null;
        }

        if (json.log.version !== "1.2") {
            WI.NetworkManager.synthesizeImportError(WI.UIString("unsupported HAR version"));
            return null;
        }

        if (!Array.isArray(json.log.entries) || !Array.isArray(json.log.pages) || !json.log.pages[0] || !json.log.pages[0].startedDateTime) {
            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
            return null;
        }

        let mainResourceSentWalltime = WI.HARBuilder.dateFromHARDate(json.log.pages[0].startedDateTime) / 1000;
        if (isNaN(mainResourceSentWalltime)) {
            WI.NetworkManager.synthesizeImportError(WI.UIString("invalid HAR"));
            return null;
        }

        let localResources = [];

        for (let entry of json.log.entries) {
            let localResource = WI.LocalResource.fromHAREntry(entry, mainResourceSentWalltime);
            this._harImportLocalResourceMap.add(localResource);
            localResources.push(localResource);
        }

        return localResources;
    }

    // PageObserver

    frameDidNavigate(framePayload)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        var frameWasLoadedInstantly = false;

        var frame = this.frameForIdentifier(framePayload.id);
        if (!frame) {
            // If the frame wasn't known before now, then the main resource was loaded instantly (about:blank, etc.)
            // Make a new resource (which will make the frame). Mark will mark it as loaded at the end too since we
            // don't expect any more events about the load finishing for these frames.
            let resourceOptions = {
                loaderIdentifier: framePayload.loaderId,
            };
            let frameOptions = {
                name: framePayload.name,
                securityOrigin: framePayload.securityOrigin,
            };
            let frameResource = this._addNewResourceToFrameOrTarget(framePayload.url, framePayload.id, resourceOptions, frameOptions);
            frame = frameResource.parentFrame;
            frameWasLoadedInstantly = true;

            console.assert(frame);
            if (!frame)
                return;
        }

        if (framePayload.loaderId === frame.provisionalLoaderIdentifier) {
            // There was a provisional load in progress, commit it.
            frame.commitProvisionalLoad(framePayload.securityOrigin);
        } else {
            let mainResource = null;
            if (frame.mainResource.url !== framePayload.url || frame.loaderIdentifier !== framePayload.loaderId) {
                // Navigations like back/forward do not have provisional loads, so create a new main resource here.
                mainResource = new WI.Resource(framePayload.url, {
                    mimeType: framePayload.mimeType,
                    loaderIdentifier: framePayload.loaderId,
                });
            } else {
                // The main resource is already correct, so reuse it.
                mainResource = frame.mainResource;
            }

            frame.initialize(framePayload.name, framePayload.securityOrigin, framePayload.loaderId, mainResource);
        }

        var oldMainFrame = this._mainFrame;

        if (framePayload.parentId) {
            var parentFrame = this.frameForIdentifier(framePayload.parentId);
            console.assert(parentFrame);

            if (frame === this._mainFrame)
                this._mainFrame = null;

            if (frame.parentFrame !== parentFrame)
                parentFrame.addChildFrame(frame);
        } else {
            if (frame.parentFrame)
                frame.parentFrame.removeChildFrame(frame);
            this._mainFrame = frame;
        }

        if (this._mainFrame !== oldMainFrame)
            this._mainFrameDidChange(oldMainFrame);

        if (frameWasLoadedInstantly)
            frame.mainResource.markAsFinished();
    }

    frameDidDetach(frameId)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        var frame = this.frameForIdentifier(frameId);
        if (!frame)
            return;

        if (frame.parentFrame)
            frame.parentFrame.removeChildFrame(frame);

        this._frameIdentifierMap.delete(frame.id);

        var oldMainFrame = this._mainFrame;

        if (frame === this._mainFrame)
            this._mainFrame = null;

        frame.clearExecutionContexts();

        this.dispatchEventToListeners(WI.NetworkManager.Event.FrameWasRemoved, {frame});

        if (this._mainFrame !== oldMainFrame)
            this._mainFrameDidChange(oldMainFrame);
    }

    // NetworkObserver

    resourceRequestWillBeSent(requestIdentifier, frameIdentifier, loaderIdentifier, request, type, redirectResponse, timestamp, walltime, initiator, targetId)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        var elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
        if (resource) {
            // This is an existing request which is being redirected, update the resource.
            console.assert(resource.parentFrame.id === frameIdentifier);
            console.assert(resource.loaderIdentifier === loaderIdentifier);
            console.assert(!targetId);
            resource.updateForRedirectResponse(request, redirectResponse, elapsedTime, walltime);
            return;
        }

        // This is a new request, make a new resource and add it to the right frame.
        resource = this._addNewResourceToFrameOrTarget(request.url, frameIdentifier, {
            type,
            loaderIdentifier,
            targetId,
            requestIdentifier,
            requestMethod: request.method,
            requestHeaders: request.headers,
            requestData: request.postData,
            requestSentTimestamp: elapsedTime,
            requestSentWalltime: walltime,
            initiatorCallFrames: this._initiatorCallFramesFromPayload(initiator),
            initiatorSourceCodeLocation: this._initiatorSourceCodeLocationFromPayload(initiator),
            initiatorNode: this._initiatorNodeFromPayload(initiator),
        });

        // Associate the resource with the requestIdentifier so it can be found in future loading events.
        this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
    }

    webSocketCreated(requestId, url)
    {
        this._webSocketIdentifierToURL.set(requestId, url);
    }

    webSocketWillSendHandshakeRequest(requestId, timestamp, walltime, request)
    {
        let url = this._webSocketIdentifierToURL.get(requestId);
        console.assert(url);
        if (!url)
            return;

        // COMPATIBILITY(iOS 10.3): `walltime` did not exist in 10.3 and earlier.
        if (!InspectorBackend.hasEvent("Network.webSocketWillSendHandshakeRequest", "walltime")) {
            request = arguments[2];
            walltime = NaN;
        }

        // FIXME: <webkit.org/b/168475> Web Inspector: Correctly display iframe's and worker's WebSockets

        let resource = new WI.WebSocketResource(url, {
            loaderIdentifier: WI.networkManager.mainFrame.id,
            requestIdentifier: requestId,
            requestHeaders: request.headers,
            timestamp,
            walltime,
            requestSentTimestamp: WI.timelineManager.computeElapsedTime(timestamp),
        });

        let frame = this.frameForIdentifier(WI.networkManager.mainFrame.id);
        frame.addResource(resource);

        this._resourceRequestIdentifierMap.set(requestId, resource);
    }

    webSocketHandshakeResponseReceived(requestId, timestamp, response)
    {
        let resource = this._resourceRequestIdentifierMap.get(requestId);
        console.assert(resource);
        if (!resource)
            return;

        resource.readyState = WI.WebSocketResource.ReadyState.Open;

        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);

        // FIXME: <webkit.org/b/169166> Web Inspector: WebSockets: Implement timing information
        let responseTiming = response.timing || null;

        resource.updateForResponse(resource.url, resource.mimeType, resource.type, response.headers, response.status, response.statusText, elapsedTime, responseTiming);

        resource.markAsFinished(elapsedTime);
    }

    webSocketFrameReceived(requestId, timestamp, response)
    {
        this._webSocketFrameReceivedOrSent(requestId, timestamp, response);
    }

    webSocketFrameSent(requestId, timestamp, response)
    {
        this._webSocketFrameReceivedOrSent(requestId, timestamp, response);
    }

    webSocketClosed(requestId, timestamp)
    {
        let resource = this._resourceRequestIdentifierMap.get(requestId);
        console.assert(resource);
        if (!resource)
            return;

        resource.readyState = WI.WebSocketResource.ReadyState.Closed;

        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        resource.markAsFinished(elapsedTime);

        this._webSocketIdentifierToURL.delete(requestId);
        this._resourceRequestIdentifierMap.delete(requestId);
    }

    _webSocketFrameReceivedOrSent(requestId, timestamp, response)
    {
        let resource = this._resourceRequestIdentifierMap.get(requestId);
        console.assert(resource);
        if (!resource)
            return;

        // Data going from the client to the server is always masked.
        let isOutgoing = !!response.mask;

        let {payloadData, payloadLength, opcode} = response;
        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);

        resource.addFrame(payloadData, payloadLength, isOutgoing, opcode, timestamp, elapsedTime);
    }

    markResourceRequestAsServedFromMemoryCache(requestIdentifier)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);

        // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
        // We don't want to assert in this case since we do likely have the resource, via Page.getResourceTree. The Resource
        // just doesn't have a requestIdentifier for us to look it up.
        if (!resource)
            return;

        resource.legacyMarkServedFromMemoryCache();
    }

    resourceRequestWasServedFromMemoryCache(requestIdentifier, frameIdentifier, loaderIdentifier, cachedResourcePayload, timestamp, initiator)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        console.assert(!this._resourceRequestIdentifierMap.has(requestIdentifier));

        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        let response = cachedResourcePayload.response;
        const responseSource = InspectorBackend.Enum.Network.ResponseSource.MemoryCache;

        let resource = this._addNewResourceToFrameOrTarget(cachedResourcePayload.url, frameIdentifier, {
            type: cachedResourcePayload.type,
            loaderIdentifier,
            requestIdentifier,
            requestMethod: "GET",
            requestSentTimestamp: elapsedTime,
            initiatorCallFrames: this._initiatorCallFramesFromPayload(initiator),
            initiatorSourceCodeLocation: this._initiatorSourceCodeLocationFromPayload(initiator),
            initiatorNode: this._initiatorNodeFromPayload(initiator),
        });
        resource.updateForResponse(cachedResourcePayload.url, response.mimeType, cachedResourcePayload.type, response.headers, response.status, response.statusText, elapsedTime, response.timing, responseSource, response.security);
        resource.increaseSize(cachedResourcePayload.bodySize, elapsedTime);
        resource.increaseTransferSize(cachedResourcePayload.bodySize);
        resource.setCachedResponseBodySize(cachedResourcePayload.bodySize);
        resource.markAsFinished(elapsedTime);

        console.assert(resource.cached, "This resource should be classified as cached since it was served from the MemoryCache", resource);

        if (cachedResourcePayload.sourceMapURL)
            this.downloadSourceMap(cachedResourcePayload.sourceMapURL, resource.url, resource);

        // No need to associate the resource with the requestIdentifier, since this is the only event
        // sent for memory cache resource loads.
    }

    resourceRequestDidReceiveResponse(requestIdentifier, frameIdentifier, loaderIdentifier, type, response, timestamp)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        var elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);

        // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
        // We don't want to assert in this case since we do likely have the resource, via Page.getResourceTree. The Resource
        // just doesn't have a requestIdentifier for us to look it up, but we can try to look it up by its URL.
        if (!resource) {
            var frame = this.frameForIdentifier(frameIdentifier);
            if (frame)
                resource = frame.resourcesForURL(response.url).firstValue;

            // If we find the resource this way we had marked it earlier as finished via Page.getResourceTree.
            // Associate the resource with the requestIdentifier so it can be found in future loading events.
            // and roll it back to an unfinished state, we know now it is still loading.
            if (resource) {
                this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
                resource.revertMarkAsFinished();
            }
        }

        // If we haven't found an existing Resource by now, then it is a resource that was loading when the inspector
        // opened and we just missed the resourceRequestWillBeSent for it. So make a new resource and add it.
        if (!resource) {
            resource = this._addNewResourceToFrameOrTarget(response.url, frameIdentifier, {
                type,
                loaderIdentifier,
                requestIdentifier,
                requestHeaders: response.requestHeaders,
                requestSentTimestamp: elapsedTime,
            });

            // Associate the resource with the requestIdentifier so it can be found in future loading events.
            this._resourceRequestIdentifierMap.set(requestIdentifier, resource);
        }

        // COMPATIBILITY (iOS 10.3): `fromDiskCache` is legacy, replaced by `source`.
        if (response.fromDiskCache)
            resource.legacyMarkServedFromDiskCache();

        resource.updateForResponse(response.url, response.mimeType, type, response.headers, response.status, response.statusText, elapsedTime, response.timing, response.source, response.security);
    }

    resourceRequestDidReceiveData(requestIdentifier, dataLength, encodedDataLength, timestamp)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
        var elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);

        // We might not have a resource if the inspector was opened during the page load (after resourceRequestWillBeSent is called).
        // We don't want to assert in this case since we do likely have the resource, via Page.getResourceTree. The Resource
        // just doesn't have a requestIdentifier for us to look it up.
        if (!resource)
            return;

        resource.increaseSize(dataLength, elapsedTime);

        if (encodedDataLength !== -1)
            resource.increaseTransferSize(encodedDataLength);
    }

    resourceRequestDidFinishLoading(requestIdentifier, timestamp, sourceMapURL, metrics)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        // By now we should always have the Resource. Either it was fetched when the inspector first opened with
        // Page.getResourceTree, or it was a currently loading resource that we learned about in resourceRequestDidReceiveResponse.
        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
        console.assert(resource);
        if (!resource)
            return;

        if (metrics)
            resource.updateWithMetrics(metrics);

        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        resource.markAsFinished(elapsedTime);

        if (sourceMapURL)
            this.downloadSourceMap(sourceMapURL, resource.url, resource);

        this._resourceRequestIdentifierMap.delete(requestIdentifier);
    }

    resourceRequestDidFailLoading(requestIdentifier, canceled, timestamp, errorText)
    {
        // Ignore this while waiting for the whole frame/resource tree.
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        // By now we should always have the Resource. Either it was fetched when the inspector first opened with
        // Page.getResourceTree, or it was a currently loading resource that we learned about in resourceRequestDidReceiveResponse.
        let resource = this._resourceRequestIdentifierMap.get(requestIdentifier);
        console.assert(resource);
        if (!resource)
            return;

        let elapsedTime = WI.timelineManager.computeElapsedTime(timestamp);
        resource.markAsFailed(canceled, elapsedTime, errorText);

        if (resource.parentFrame && resource === resource.parentFrame.provisionalMainResource)
            resource.parentFrame.clearProvisionalLoad();

        this._resourceRequestIdentifierMap.delete(requestIdentifier);
    }

    requestIntercepted(target, requestId, request)
    {
        let url = WI.urlWithoutFragment(request.url);
        for (let localResourceOverride of this.localResourceOverridesForURL(url)) {
            if (localResourceOverride.disabled)
                continue;

            let localResource = localResourceOverride.localResource;
            let revision = localResource.currentRevision;

            switch (localResourceOverride.type) {
            case WI.LocalResourceOverride.InterceptType.Request: {
                target.NetworkAgent.interceptWithRequest.invoke({
                    requestId,
                    url: localResource.url || undefined,
                    method: localResource.requestMethod ?? undefined,
                    headers: localResource.requestHeaders,
                    postData: (WI.HTTPUtilities.RequestMethodsWithBody.has(localResource.requestMethod) && localResource.requestData) ? btoa(localResource.requestData) : undefined,
                });
                return;
            }

            case WI.LocalResourceOverride.InterceptType.ResponseSkippingNetwork:
                console.assert(revision.mimeType === localResource.mimeType);
                target.NetworkAgent.interceptRequestWithResponse.invoke({
                    requestId,
                    content: revision.content,
                    base64Encoded: !!revision.base64Encoded,
                    mimeType: revision.mimeType ?? undefined,
                    status: !isNaN(localResource.statusCode) ? localResource.statusCode : 200,
                    statusText: !isNaN(localResource.statusCode) ? (localResource.statusText ?? "") : WI.HTTPUtilities.statusTextForStatusCode(200),
                    headers: localResource.responseHeaders,
                });
                return;
            }
        }

        // It's possible for a response regex override to overlap a request regex override, in
        // which case we should silently continue the request if the response regex override was
        // used instead (e.g. it was added first).
        target.NetworkAgent.interceptContinue.invoke({
            requestId,
            stage: InspectorBackend.Enum.Network.NetworkStage.Request,
        });
    }

    responseIntercepted(target, requestId, response)
    {
        let url = WI.urlWithoutFragment(response.url);
        for (let localResourceOverride of this.localResourceOverridesForURL(url)) {
            if (localResourceOverride.disabled)
                continue;

            let localResource = localResourceOverride.localResource;
            let revision = localResource.currentRevision;

            switch (localResourceOverride.type) {
            case WI.LocalResourceOverride.InterceptType.Response:
                console.assert(revision.mimeType === localResource.mimeType);
                target.NetworkAgent.interceptWithResponse.invoke({
                    requestId,
                    content: revision.content,
                    base64Encoded: !!revision.base64Encoded,
                    mimeType: revision.mimeType ?? undefined,
                    status: !isNaN(localResource.statusCode) ? localResource.statusCode : undefined,
                    statusText: !isNaN(localResource.statusCode) ? (localResource.statusText ?? "") : undefined,
                    headers: localResource.responseHeaders,
                });
                return;
            }
        }

        // It's possible for a request regex override to overlap a response regex override, in
        // which case we should silently continue the response if the request regex override was
        // used instead (e.g. it was added first).
        target.NetworkAgent.interceptContinue.invoke({
            requestId,
            stage: InspectorBackend.Enum.Network.NetworkStage.Response,
        });
    }

    // RuntimeObserver

    executionContextCreated(payload)
    {
        let frame = this.frameForIdentifier(payload.frameId);
        console.assert(frame);
        if (!frame)
            return;

        let type = WI.ExecutionContext.typeFromPayload(payload);
        let target = frame.mainResource.target;
        let executionContext = new WI.ExecutionContext(target, payload.id, type, payload.name, frame);
        frame.addExecutionContext(executionContext);
    }

    // Private

    _addNewResourceToFrameOrTarget(url, frameIdentifier, resourceOptions = {}, frameOptions = {})
    {
        console.assert(!this._waitingForMainFrameResourceTreePayload);

        let resource = null;

        if (!frameIdentifier && resourceOptions.targetId) {
            // This is a new resource for a ServiceWorker target.
            console.assert(WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker);
            console.assert(resourceOptions.targetId === WI.mainTarget.identifier);
            resource = new WI.Resource(url, resourceOptions);
            resource.target.addResource(resource);
            return resource;
        }

        let frame = this.frameForIdentifier(frameIdentifier);
        if (frame) {
            if (resourceOptions.type === InspectorBackend.Enum.Page.ResourceType.Document && frame.provisionalMainResource && frame.provisionalMainResource.url === url && frame.provisionalLoaderIdentifier === resourceOptions.loaderIdentifier)
                resource = frame.provisionalMainResource;
            else {
                resource = new WI.Resource(url, resourceOptions);
                if (resource.target === WI.pageTarget)
                    this._addResourceToFrame(frame, resource);
                else if (resource.target)
                    resource.target.addResource(resource);
                else
                    this._addOrphanedResource(resource, resourceOptions.targetId);
            }
        } else {
            // This is a new request for a new frame, which is always the main resource.
            console.assert(WI.sharedApp.debuggableType !== WI.DebuggableType.ServiceWorker);
            console.assert(!resourceOptions.targetId);
            resource = new WI.Resource(url, resourceOptions);
            frame = new WI.Frame(frameIdentifier, frameOptions.name, frameOptions.securityOrigin, resourceOptions.loaderIdentifier, resource);
            this._frameIdentifierMap.set(frame.id, frame);

            // If we don't have a main frame, assume this is it. This can change later in
            // frameDidNavigate when the parent frame is known.
            if (!this._mainFrame) {
                this._mainFrame = frame;
                this._mainFrameDidChange(null);
            }

            this._dispatchFrameWasAddedEvent(frame);
        }

        console.assert(resource);

        return resource;
    }

    _addResourceToFrame(frame, resource)
    {
        console.assert(!this._waitingForMainFrameResourceTreePayload);
        if (this._waitingForMainFrameResourceTreePayload)
            return;

        console.assert(frame);
        console.assert(resource);

        if (resource.loaderIdentifier !== frame.loaderIdentifier && !frame.provisionalLoaderIdentifier) {
            // This is the start of a provisional load which happens before frameDidNavigate is called.
            // This resource will be the new mainResource if frameDidNavigate is called.
            frame.startProvisionalLoad(resource);
            return;
        }

        // This is just another resource, either for the main loader or the provisional loader.
        console.assert(resource.loaderIdentifier === frame.loaderIdentifier || resource.loaderIdentifier === frame.provisionalLoaderIdentifier);
        frame.addResource(resource);
    }

    _addResourceToTarget(target, resource)
    {
        console.assert(target !== WI.pageTarget);
        console.assert(resource);

        target.addResource(resource);
    }

    _initiatorCallFramesFromPayload(initiatorPayload)
    {
        if (!initiatorPayload)
            return null;

        let callFrames = initiatorPayload.stackTrace;
        if (!callFrames)
            return null;

        return callFrames.map((payload) => WI.CallFrame.fromPayload(WI.assumingMainTarget(), payload));
    }

    _initiatorSourceCodeLocationFromPayload(initiatorPayload)
    {
        if (!initiatorPayload)
            return null;

        var url = null;
        var lineNumber = NaN;
        var columnNumber = 0;

        if (initiatorPayload.stackTrace && initiatorPayload.stackTrace.length) {
            var stackTracePayload = initiatorPayload.stackTrace;
            for (var i = 0; i < stackTracePayload.length; ++i) {
                var callFramePayload = stackTracePayload[i];
                if (!callFramePayload.url || callFramePayload.url === "[native code]")
                    continue;

                url = callFramePayload.url;

                // The lineNumber is 1-based, but we expect 0-based.
                lineNumber = callFramePayload.lineNumber - 1;

                columnNumber = callFramePayload.columnNumber;

                break;
            }
        } else if (initiatorPayload.url) {
            url = initiatorPayload.url;

            // The lineNumber is 1-based, but we expect 0-based.
            lineNumber = initiatorPayload.lineNumber - 1;
        }

        if (!url || isNaN(lineNumber) || lineNumber < 0)
            return null;

        let sourceCode = WI.networkManager.resourcesForURL(url).firstValue;
        if (!sourceCode)
            sourceCode = WI.debuggerManager.scriptsForURL(url, WI.mainTarget)[0];

        if (!sourceCode)
            return null;

        return sourceCode.createSourceCodeLocation(lineNumber, columnNumber);
    }

    _initiatorNodeFromPayload(initiatorPayload)
    {
        return WI.domManager.nodeForId(initiatorPayload.nodeId);
    }

    _processServiceWorkerConfiguration(error, initializationPayload)
    {
        console.assert(this._waitingForMainFrameResourceTreePayload);
        this._waitingForMainFrameResourceTreePayload = false;

        if (error) {
            console.error(JSON.stringify(error));
            return;
        }

        console.assert(initializationPayload.targetId.startsWith("serviceworker:"));

        WI.mainTarget.identifier = initializationPayload.targetId;
        WI.mainTarget.name = initializationPayload.url;

        // Create a main resource with this content in case the content never shows up as a WI.Script.
        const sourceURL = null;
        const sourceType = WI.Script.SourceType.Program;
        let script = new WI.LocalScript(WI.mainTarget, initializationPayload.url, sourceURL, sourceType, initializationPayload.content);
        WI.mainTarget.mainResource = script;

        InspectorBackend.runAfterPendingDispatches(() => {
            if (WI.mainTarget.mainResource === script) {
                // We've now received all the scripts, if we don't have a better main resource use this LocalScript.
                WI.debuggerManager.dataForTarget(WI.mainTarget).addScript(script);
                WI.debuggerManager.dispatchEventToListeners(WI.DebuggerManager.Event.ScriptAdded, {script});
            }
        });
    }

    _processMainFrameResourceTreePayload(error, mainFramePayload)
    {
        console.assert(this._waitingForMainFrameResourceTreePayload);
        this._waitingForMainFrameResourceTreePayload = false;

        if (error) {
            console.error(JSON.stringify(error));
            return;
        }

        console.assert(mainFramePayload);
        console.assert(mainFramePayload.frame);

        this._resourceRequestIdentifierMap = new Map;
        this._frameIdentifierMap = new Map;

        var oldMainFrame = this._mainFrame;

        this._mainFrame = this._addFrameTreeFromFrameResourceTreePayload(mainFramePayload, true);

        if (this._mainFrame !== oldMainFrame)
            this._mainFrameDidChange(oldMainFrame);

        // Emulate a main resource change within this page even though we are swapping out main frames.
        // This is because many managers listen only for main resource change events to perform work,
        // but they don't listen for main frame changes.
        if (this._transitioningPageTarget) {
            this._transitioningPageTarget = false;
            this._mainFrame._dispatchMainResourceDidChangeEvent(oldMainFrame.mainResource);
        }
    }

    _createFrame(payload)
    {
        // If payload.url is missing or empty then this page is likely the special empty page. In that case
        // we will just say it is "about:blank" so we have a URL, which is required for resources.
        let mainResource = new WI.Resource(payload.url || "about:blank", {
            mimeType: payload.mimeType,
            loaderIdentifier: payload.loaderId,
        });
        var frame = new WI.Frame(payload.id, payload.name, payload.securityOrigin, payload.loaderId, mainResource);

        this._frameIdentifierMap.set(frame.id, frame);

        mainResource.markAsFinished();

        return frame;
    }

    _createResource(payload, framePayload)
    {
        let resource = new WI.Resource(payload.url, {
            mimeType: payload.mimeType,
            type: payload.type,
            loaderIdentifier: framePayload.loaderId,
            targetId: payload.targetId,
        });

        if (payload.sourceMapURL)
            this.downloadSourceMap(payload.sourceMapURL, resource.url, resource);

        return resource;
    }

    _addFrameTreeFromFrameResourceTreePayload(payload, isMainFrame)
    {
        var frame = this._createFrame(payload.frame);
        if (isMainFrame)
            frame.markAsMainFrame();

        for (var i = 0; payload.childFrames && i < payload.childFrames.length; ++i)
            frame.addChildFrame(this._addFrameTreeFromFrameResourceTreePayload(payload.childFrames[i], false));

        for (var i = 0; payload.resources && i < payload.resources.length; ++i) {
            var resourcePayload = payload.resources[i];

            // The main resource is included as a resource. We can skip it since we already created
            // a main resource when we created the Frame. The resource payload does not include anything
            // didn't already get from the frame payload.
            if (resourcePayload.type === "Document" && resourcePayload.url === payload.frame.url)
                continue;

            var resource = this._createResource(resourcePayload, payload);
            if (resource.target === WI.pageTarget)
                frame.addResource(resource);
            else if (resource.target)
                resource.target.addResource(resource);
            else
                this._addOrphanedResource(resource, resourcePayload.targetId);

            if (resourcePayload.failed || resourcePayload.canceled)
                resource.markAsFailed(resourcePayload.canceled);
            else
                resource.markAsFinished();
        }

        this._dispatchFrameWasAddedEvent(frame);

        return frame;
    }

    _addOrphanedResource(resource, targetId)
    {
        let resources = this._orphanedResources.get(targetId);
        if (!resources) {
            resources = [];
            this._orphanedResources.set(targetId, resources);
        }

        resources.push(resource);
    }

    _commandArgumentsForInterception(localResourceOverride)
    {
        console.assert(localResourceOverride instanceof WI.LocalResourceOverride, localResourceOverride);

        return {
            url: localResourceOverride.url,
            stage: localResourceOverride.type === WI.LocalResourceOverride.InterceptType.Response ? InspectorBackend.Enum.Network.NetworkStage.Response : InspectorBackend.Enum.Network.NetworkStage.Request,
            caseSensitive: localResourceOverride.isCaseSensitive,
            isRegex: localResourceOverride.isRegex,
        };
    }

    _addInterception(localResourceOverride, specificTarget)
    {
        console.assert(localResourceOverride instanceof WI.LocalResourceOverride, localResourceOverride);
        console.assert(!localResourceOverride.disabled, localResourceOverride);

        let targets = specificTarget ? [specificTarget] : WI.targets;
        for (let target of targets) {
            // COMPATIBILITY (iOS 13.0): Network.addInterception did not exist yet.
            if (!target.hasCommand("Network.addInterception"))
                continue;

            target.NetworkAgent.addInterception.invoke(this._commandArgumentsForInterception(localResourceOverride));
        }
    }

    _removeInterception(localResourceOverride, specificTarget)
    {
        console.assert(localResourceOverride instanceof WI.LocalResourceOverride, localResourceOverride);

        let targets = specificTarget ? [specificTarget] : WI.targets;
        for (let target of targets) {
            // COMPATIBILITY (iOS 13.0): Network.removeInterception did not exist yet.
            if (!target.hasCommand("Network.removeInterception"))
                continue;

            target.NetworkAgent.removeInterception.invoke(this._commandArgumentsForInterception(localResourceOverride));
        }
    }

    _dispatchFrameWasAddedEvent(frame)
    {
        this.dispatchEventToListeners(WI.NetworkManager.Event.FrameWasAdded, {frame});
    }

    _mainFrameDidChange(oldMainFrame)
    {
        if (oldMainFrame)
            oldMainFrame.unmarkAsMainFrame();
        if (this._mainFrame)
            this._mainFrame.markAsMainFrame();

        this.dispatchEventToListeners(WI.NetworkManager.Event.MainFrameDidChange, {oldMainFrame});
    }

    _loadAndParseSourceMap(sourceMapURL, baseURL, originalSourceCode)
    {
        this._downloadingSourceMaps.add(sourceMapURL);

        let sourceMapLoaded = (error, content, mimeType, statusCode) => {
            if (error || statusCode >= 400) {
                this._sourceMapLoadAndParseFailed(sourceMapURL);
                return;
            }

            if (content.slice(0, 3) === ")]}") {
                let firstNewlineIndex = content.indexOf("\n");
                if (firstNewlineIndex === -1) {
                    this._sourceMapLoadAndParseFailed(sourceMapURL);
                    return;
                }

                content = content.substring(firstNewlineIndex);
            }

            try {
                let payload = JSON.parse(content);
                let baseURL = sourceMapURL.startsWith("data:") ? originalSourceCode.url : sourceMapURL;
                let sourceMap = new WI.SourceMap(baseURL, payload, originalSourceCode);
                this._sourceMapLoadAndParseSucceeded(sourceMapURL, sourceMap);
            } catch {
                this._sourceMapLoadAndParseFailed(sourceMapURL);
            }
        };

        if (sourceMapURL.startsWith("data:")) {
            let {mimeType, base64, data} = parseDataURL(sourceMapURL);
            let content = base64 ? atob(data) : data;
            sourceMapLoaded(null, content, mimeType, 0);
            return;
        }

        let target = WI.assumingMainTarget();
        if (!target.hasCommand("Network.loadResource")) {
            this._sourceMapLoadAndParseFailed(sourceMapURL);
            return;
        }

        let frameIdentifier = null;
        if (originalSourceCode instanceof WI.Resource && originalSourceCode.parentFrame)
            frameIdentifier = originalSourceCode.parentFrame.id;

        if (!frameIdentifier)
            frameIdentifier = WI.networkManager.mainFrame ? WI.networkManager.mainFrame.id : "";

        target.NetworkAgent.loadResource(frameIdentifier, sourceMapURL, sourceMapLoaded);
    }

    _sourceMapLoadAndParseFailed(sourceMapURL)
    {
        this._downloadingSourceMaps.delete(sourceMapURL);
    }

    _sourceMapLoadAndParseSucceeded(sourceMapURL, sourceMap)
    {
        if (!this._downloadingSourceMaps.has(sourceMapURL))
            return;

        this._downloadingSourceMaps.delete(sourceMapURL);

        this._sourceMapURLMap.set(sourceMapURL, sourceMap);

        for (let source of sourceMap.sources())
            sourceMap.addResource(new WI.SourceMapResource(source, sourceMap));

        // Associate the SourceMap with the originalSourceCode.
        sourceMap.originalSourceCode.addSourceMap(sourceMap);

        // If the originalSourceCode was not a Resource, be sure to also associate with the Resource if one exists.
        // FIXME: We should try to use the right frame instead of a global lookup by URL.
        if (!(sourceMap.originalSourceCode instanceof WI.Resource)) {
            console.assert(sourceMap.originalSourceCode instanceof WI.Script);
            let resource = sourceMap.originalSourceCode.resource;
            if (resource)
                resource.addSourceMap(sourceMap);
        }
    }

    _handleResourceContentChangedForLocalResourceOverride(event)
    {
        let localResourceOverride = event.target.localResourceOverride;
        if (!localResourceOverride)
            return;

        if (!this._saveLocalResourceOverridesDebouncer) {
            this._pendingLocalResourceOverrideSaves = new Set;
            this._saveLocalResourceOverridesDebouncer = new Debouncer(() => {
                for (let localResourceOverride of this._pendingLocalResourceOverrideSaves) {
                    console.assert(localResourceOverride instanceof WI.LocalResourceOverride);
                    WI.objectStores.localResourceOverrides.putObject(localResourceOverride);
                }
            });
        }

        this._pendingLocalResourceOverrideSaves.add(localResourceOverride);
        this._saveLocalResourceOverridesDebouncer.delayForTime(500);
    }

    _handleResourceOverrideDisabledChanged(event)
    {
        console.assert(WI.NetworkManager.supportsOverridingResponses());

        let localResourceOverride = event.target;
        WI.objectStores.localResourceOverrides.putObject(localResourceOverride);

        if (localResourceOverride.disabled)
            this._removeInterception(localResourceOverride);
        else
            this._addInterception(localResourceOverride);
    }

    _handleBootstrapScriptContentDidChange(event)
    {
        let source = this._bootstrapScript.content || "";

        WI.objectStores.general.put(source, NetworkManager.bootstrapScriptSourceObjectStoreKey);

        if (!this._bootstrapScriptEnabledSetting.value)
            return;

        // COMPATIBILITY (iOS 13.0): Page.setBootstrapScript did not exist yet.
        for (let target of WI.targets) {
            if (target.hasCommand("Page.setBootstrapScript"))
                target.PageAgent.setBootstrapScript(source);
        }
    }

    _extraDomainsActivated(event)
    {
        // COMPATIBILITY (iOS 14.0): Inspector.activateExtraDomains was removed in favor of a declared debuggable type

        let target = WI.assumingMainTarget();
        if (target.hasDomain("Page") && event.data.domains.includes("Page"))
            target.PageAgent.getResourceTree(this._processMainFrameResourceTreePayload.bind(this));
    }

    _handleFrameMainResourceDidChange(event)
    {
        if (!event.target.isMainFrame())
            return;

        this._sourceMapURLMap.clear();
        this._downloadingSourceMaps.clear();
    }
};

WI.NetworkManager.Event = {
    FrameWasAdded: "network-manager-frame-was-added",
    FrameWasRemoved: "network-manager-frame-was-removed",
    MainFrameDidChange: "network-manager-main-frame-did-change",
    BootstrapScriptCreated: "network-manager-bootstrap-script-created",
    BootstrapScriptEnabledChanged: "network-manager-bootstrap-script-enabled-changed",
    BootstrapScriptDestroyed: "network-manager-bootstrap-script-destroyed",
    LocalResourceOverrideAdded: "network-manager-local-resource-override-added",
    LocalResourceOverrideRemoved: "network-manager-local-resource-override-removed",
};
