/*
 * 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 = new Set;
        this._harImportLocalResourceMap = new Set;

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

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

        WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._extraDomainsActivated, this);
        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);

        if (NetworkManager.supportsLocalResourceOverrides()) {
            WI.Resource.addEventListener(WI.SourceCode.Event.ContentDidChange, this._handleResourceContentDidChange, 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);

                    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 supportsLocalResourceOverrides()
    {
        return InspectorBackend.hasCommand("Network.setInterceptionEnabled");
    }

    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) {
                        target.NetworkAgent.addInterception.invoke({
                            url: localResourceOverride.url,
                            caseSensitive: localResourceOverride.isCaseSensitive,
                            isRegex: localResourceOverride.isRegex,
                            networkStage: InspectorBackend.Enum.Network.NetworkStage.Response,
                        });
                    }
                }
            }
        }

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

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

    // Public

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

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

    get localResourceOverrides()
    {
        return Array.from(this._localResourceOverrides);
    }

    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 `debugger` statements")}
 *  - ${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.has(localResourceOverride), "Already had an existing local resource override.");
        this._localResourceOverrides.add(localResourceOverride);

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

        if (!localResourceOverride.disabled) {
            let commandArguments = {
                url: localResourceOverride.url,
                caseSensitive: localResourceOverride.isCaseSensitive,
                isRegex: localResourceOverride.isRegex,
                networkStage: InspectorBackend.Enum.Network.NetworkStage.Response,
            };

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

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

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

        if (!this._localResourceOverrides.delete(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) {
            let commandArguments = {
                url: localResourceOverride.url,
                caseSensitive: localResourceOverride.isCaseSensitive,
                isRegex: localResourceOverride.isRegex,
                networkStage: InspectorBackend.Enum.Network.NetworkStage.Response,
            };

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

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

    localResourceOverrideForURL(url)
    {
        for (let localResourceOverride of this._localResourceOverrides) {
            if (localResourceOverride.matches(url))
                return localResourceOverride;
        }
        return null;
    }

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

        if (resource instanceof WI.SourceMapResource)
            return false;

        if (resource.isLocalResourceOverride)
            return false;

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

        let existingOverride = this.localResourceOverrideForURL(resource.url);
        if (existingOverride)
            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;
    }

    resourceForURL(url)
    {
        if (!this._mainFrame)
            return null;

        if (this._mainFrame.mainResource.url === url)
            return this._mainFrame.mainResource;

        return this._mainFrame.resourceForURL(url, true);
    }

    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;

        // COMPATIBILITY (iOS 8): Timeline timestamps for legacy backends are computed
        // dynamically from the first backend timestamp received. For navigations we
        // need to reset that base timestamp, and an appropriate timestamp to use is
        // the new main resource's will be sent timestamp. So save this value on the
        // resource in case it becomes a main resource.
        var originalRequestWillBeSentTimestamp = timestamp;

        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),
            originalRequestWillBeSentTimestamp,
        });

        // 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.resourceForURL(response.url);

            // 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);
    }

    responseIntercepted(target, requestId, response)
    {
        let url = WI.urlWithoutFragment(response.url);
        let localResourceOverride = this.localResourceOverrideForURL(url);
        if (!localResourceOverride || localResourceOverride.disabled) {
            target.NetworkAgent.interceptContinue(requestId);
            return;
        }

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

        let content = revision.content;
        let base64Encoded = revision.base64Encoded;
        let mimeType = revision.mimeType;
        let statusCode = localResource.statusCode;
        let statusText = localResource.statusText;
        let responseHeaders = localResource.responseHeaders;
        console.assert(revision.mimeType === localResource.mimeType);

        if (isNaN(statusCode))
            statusCode = undefined;
        if (!statusText)
            statusText = undefined;
        if (!responseHeaders)
            responseHeaders = undefined;

        target.NetworkAgent.interceptWithResponse(requestId, content, base64Encoded, mimeType, statusCode, statusText, responseHeaders);
    }

    // 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) {
            // This is a new request for an existing frame, which might be the main resource or a new resource.
            if (resourceOptions.type === "Document" && frame.mainResource.url === url && frame.loaderIdentifier === resourceOptions.loaderIdentifier)
                resource = frame.mainResource;
            else if (resourceOptions.type === "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;

        var sourceCode = WI.networkManager.resourceForURL(url);
        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);
    }

    _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;
        }

        if (!InspectorBackend.hasDomain("Network")) {
            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 : "";

        let target = WI.assumingMainTarget();
        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);
        }
    }

    _handleResourceContentDidChange(event)
    {
        let resource = event.target;
        if (!(resource instanceof WI.Resource))
            return;

        if (!resource.isLocalResourceOverride)
            return;

        let localResourceOverride = this.localResourceOverrideForURL(resource.url);
        console.assert(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.supportsLocalResourceOverrides());

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

        let commandArguments = {
            url: localResourceOverride.url,
            caseSensitive: localResourceOverride.isCaseSensitive,
            isRegex: localResourceOverride.isRegex,
            networkStage: InspectorBackend.Enum.Network.NetworkStage.Response,
        };

        // COMPATIBILITY (iOS 13.0): Network.addInterception / Network.removeInterception did not exist.
        for (let target of WI.targets) {
            if (target.hasDomain("Network")) {
                if (localResourceOverride.disabled)
                    target.NetworkAgent.removeInterception.invoke(commandArguments);
                else
                    target.NetworkAgent.addInterception.invoke(commandArguments);
            }
        }
    }

    _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)
    {
        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",
};
