/*
 * 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._localResourceOverrideMap = new Map;
        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 [url, localResourceOverride] of this._localResourceOverrideMap) {
                    if (!localResourceOverride.disabled)
                        target.NetworkAgent.addInterception(localResourceOverride.url, 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._localResourceOverrideMap.values());
    }

    get interceptionEnabled()
    {
        return this._interceptionEnabled;
    }

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

        this._interceptionEnabled = enabled;

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

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

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

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

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

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

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

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

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

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

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

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

        loadAndParseSourceMap();
    }

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

        return this._bootstrapScriptEnabledSetting.value;
    }

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

        this._bootstrapScriptEnabledSetting.value = !!enabled;

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

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

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

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

        if (this._bootstrapScript)
            return;

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

        if (!source) {
            source = `
/*
 * ${WI.UIString("The Inspector Bootstrap Script is guaranteed to be the first script evaluated in any page, as well as any sub-frames.")}
 * ${WI.UIString("It is evaluated immediately after the global object is created, before any other content has loaded.")}
 * 
 * ${WI.UIString("Modifications made here will take effect on the next load of any page or sub-frame.")}
 * ${WI.UIString("The contents and enabled state will be preserved across Web Inspector sessions.")}
 * 
 * ${WI.UIString("Some examples of ways to use this script include (but are not limited to):")}
 *  - ${WI.UIString("overriding built-in functions to log call traces or add `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._localResourceOverrideMap.get(localResourceOverride.url), "Already had an existing local resource override.");
        this._localResourceOverrideMap.set(localResourceOverride.url, localResourceOverride);

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

        if (!localResourceOverride.disabled) {
            // COMPATIBILITY (iOS 13.0): Network.addInterception did not exist.
            for (let target of WI.targets) {
                if (target.hasCommand("Network.addInterception"))
                    target.NetworkAgent.addInterception(localResourceOverride.url, InspectorBackend.Enum.Network.NetworkStage.Response);
            }
        }

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

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

        if (!this._localResourceOverrideMap.delete(localResourceOverride.url)) {
            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) {
            // COMPATIBILITY (iOS 13.0): Network.removeInterception did not exist.
            for (let target of WI.targets) {
                if (target.hasCommand("Network.removeInterception"))
                    target.NetworkAgent.removeInterception(localResourceOverride.url, InspectorBackend.Enum.Network.NetworkStage.Response);
            }
        }

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

    localResourceOverrideForURL(url)
    {
        return this._localResourceOverrideMap.get(url);
    }

    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._localResourceOverrideMap.get(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);

        // 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(localResourceOverride.url, InspectorBackend.Enum.Network.NetworkStage.Response);
                else
                    target.NetworkAgent.addInterception(localResourceOverride.url, InspectorBackend.Enum.Network.NetworkStage.Response);
            }
        }
    }

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