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

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

        if (!this._bootstrapScript.content)
            WI.objectStores.general.put("", NetworkManager.bootstrapScriptSourceObjectStoreKey);

        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(contextPayload)
    {
        let frame = this.frameForIdentifier(contextPayload.frameId);
        console.assert(frame);
        if (!frame)
            return;

        let displayName = contextPayload.name || frame.mainResource.displayName;
        let target = frame.mainResource.target;
        let executionContext = new WI.ExecutionContext(target, contextPayload.id, displayName, contextPayload.isPageContext, 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",
};
