/*
 * Copyright (C) 2018 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.
 */

WI.SourcesNavigationSidebarPanel = class SourcesNavigationSidebarPanel extends WI.NavigationSidebarPanel
{
    constructor()
    {
        const shouldAutoPruneStaleTopLevelResourceTreeElements = true;
        super("sources", WI.UIString("Sources"), shouldAutoPruneStaleTopLevelResourceTreeElements);

        this._workerTargetTreeElementMap = new Map;
        this._mainFrameTreeElement = null;
        this._extensionScriptsFolderTreeElement = null;
        this._extraScriptsFolderTreeElement = null;
        this._anonymousScriptsFolderTreeElement = null;

        this._originTreeElementMap = new Map;

        this._boundCompareTreeElements = this._compareTreeElements.bind(this);

        this._debuggerNavigationBar = new WI.NavigationBar;
        this.addSubview(this._debuggerNavigationBar);

        let createActivateNavigationItem = ({identifier, defaultToolTip, activatedToolTip, image}) => {
            let navigationItem = new WI.ActivateButtonNavigationItem(identifier, defaultToolTip, activatedToolTip, image, 15, 15);
            this._debuggerNavigationBar.addNavigationItem(navigationItem);
            return navigationItem;
        };

        let createToggleNavigationItem = ({identifier, defaultToolTip, alternateToolTip, defaultImage, alternateImage}) => {
            let navigationItem = new WI.ToggleButtonNavigationItem(identifier, defaultToolTip, alternateToolTip, defaultImage, alternateImage, 15, 15);
            this._debuggerNavigationBar.addNavigationItem(navigationItem);
            return navigationItem;
        };

        let createButtonNavigationitem = ({identifier, toolTipOrLabel, image}) => {
            let navigationItem = new WI.ButtonNavigationItem(identifier, toolTipOrLabel, image, 15, 15);
            this._debuggerNavigationBar.addNavigationItem(navigationItem);
            return navigationItem;
        };

        this._debuggerBreakpointsButtonItem = createActivateNavigationItem({
            identifier: "debugger-breakpoints",
            defaultToolTip: WI.UIString("Enable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName),
            activatedToolTip: WI.UIString("Disable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName),
            image: "Images/Breakpoints.svg",
        });
        this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;
        this._debuggerBreakpointsButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerToggleBreakpoints, this);

        this._debuggerPauseResumeButtonItem = createToggleNavigationItem({
            identifier: "debugger-pause-resume",
            defaultToolTip: WI.UIString("Pause script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName),
            alternateToolTip: WI.UIString("Continue script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName),
            defaultImage: "Images/Pause.svg",
            alternateImage: "Images/Resume.svg",
        });
        this._debuggerPauseResumeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerPauseResumeToggle, this);

        this._debuggerStepOverButtonItem = createButtonNavigationitem({
            identifier: "debugger-step-over",
            toolTipOrLabel: WI.UIString("Step over (%s or %s)").format(WI.stepOverKeyboardShortcut.displayName, WI.stepOverAlternateKeyboardShortcut.displayName),
            image: "Images/StepOver.svg",
        });
        this._debuggerStepOverButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOver, this);
        this._debuggerStepOverButtonItem.enabled = false;

        this._debuggerStepIntoButtonItem = createButtonNavigationitem({
            identifier: "debugger-step-into",
            toolTipOrLabel: WI.UIString("Step into (%s or %s)").format(WI.stepIntoKeyboardShortcut.displayName, WI.stepIntoAlternateKeyboardShortcut.displayName),
            image: "Images/StepInto.svg",
        });
        this._debuggerStepIntoButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepInto, this);
        this._debuggerStepIntoButtonItem.enabled = false;

        this._debuggerStepOutButtonItem = createButtonNavigationitem({
            identifier: "debugger-step-out",
            toolTipOrLabel: WI.UIString("Step out (%s or %s)").format(WI.stepOutKeyboardShortcut.displayName, WI.stepOutAlternateKeyboardShortcut.displayName),
            image: "Images/StepOut.svg",
        });
        this._debuggerStepOutButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOut, this);
        this._debuggerStepOutButtonItem.enabled = false;

        this._timelineRecordingWarningElement = null;
        this._auditTestWarningElement = null;
        this._breakpointsDisabledWarningElement = null;

        this._pauseReasonTreeOutline = null;
        this._pauseReasonLinkContainerElement = document.createElement("span");
        this._pauseReasonTextRow = new WI.DetailsSectionTextRow;
        this._pauseReasonGroup = new WI.DetailsSectionGroup([this._pauseReasonTextRow]);
        this._pauseReasonSection = new WI.DetailsSection("paused-reason", WI.UIString("Pause Reason"), [this._pauseReasonGroup], this._pauseReasonLinkContainerElement);

        this._pauseReasonContainer = document.createElement("div");
        this._pauseReasonContainer.classList.add("pause-reason-container");
        this._pauseReasonContainer.appendChild(this._pauseReasonSection.element);

        this._callStackTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
        this._callStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);

        let callStackRow = new WI.DetailsSectionRow;
        callStackRow.element.appendChild(this._callStackTreeOutline.element);

        let callStackGroup = new WI.DetailsSectionGroup([callStackRow]);
        this._callStackSection = new WI.DetailsSection("call-stack", WI.UIString("Call Stack"), [callStackGroup]);

        this._callStackContainer = document.createElement("div");
        this._callStackContainer.classList.add("call-stack-container");
        this._callStackContainer.appendChild(this._callStackSection.element);

        this._localResourceOverridesTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
        this._localResourceOverridesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);

        let localResourceOverridesRow = new WI.DetailsSectionRow;
        localResourceOverridesRow.element.appendChild(this._localResourceOverridesTreeOutline.element);

        let localResourceOverridesGroup = new WI.DetailsSectionGroup([localResourceOverridesRow]);
        this._localResourceOverridesSection = new WI.DetailsSection("local-overrides", WI.UIString("Local Overrides"), [localResourceOverridesGroup]);

        this._localResourceOverridesContainer = document.createElement("div");
        this._localResourceOverridesContainer.classList.add("local-overrides-container");
        this._localResourceOverridesContainer.appendChild(this._localResourceOverridesSection.element);

        this._mainTargetTreeElement = null;
        this._activeCallFrameTreeElement = null;

        // Prevent the breakpoints list from being used as the source of selection restoration (e.g. on reload or navigation).
        this._breakpointsTreeOutline = this.createContentTreeOutline({ignoreCookieRestoration: true});
        this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._handleBreakpointElementAddedOrRemoved, this);
        this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._handleBreakpointElementAddedOrRemoved, this);
        this._breakpointsTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
        this._breakpointsTreeOutline.ondelete = (selectedTreeElement) => {
            console.assert(selectedTreeElement.selected);

            if (!WI.debuggerManager.isBreakpointRemovable(selectedTreeElement.representedObject)) {
                let treeElementToSelect = selectedTreeElement.nextSelectableSibling;
                if (treeElementToSelect) {
                    const omitFocus = true;
                    const selectedByUser = true;
                    treeElementToSelect.select(omitFocus, selectedByUser);
                }
            } else if (selectedTreeElement instanceof WI.ResourceTreeElement || selectedTreeElement instanceof WI.ScriptTreeElement) {
                let breakpoints = this._breakpointsBeneathTreeElement(selectedTreeElement);
                this._removeAllBreakpoints(breakpoints);
            } else if (selectedTreeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject) {
                let eventBreakpointsOnWindow = WI.domManager.eventListenerBreakpoints.filter((eventBreakpoint) => eventBreakpoint.eventListener.onWindow);
                for (let eventBreakpoint of eventBreakpointsOnWindow)
                    WI.domManager.removeBreakpointForEventListener(eventBreakpoint.eventListener);
            }

            return true;
        };
        this._breakpointsTreeOutline.populateContextMenu = (contextMenu, event, treeElement) => {
            // This check is necessary since the context menu is created by the TreeOutline, meaning
            // that any child could be the target of the context menu event.
            if (treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement) {
                let breakpoints = this._breakpointsBeneathTreeElement(treeElement);

                let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
                contextMenu.appendItem(shouldDisable ? WI.UIString("Disable Breakpoints") : WI.UIString("Enable Breakpoints"), () => {
                    this._toggleAllBreakpoints(breakpoints, shouldDisable);
                });

                contextMenu.appendItem(WI.UIString("Delete Breakpoints"), () => {
                    this._removeAllBreakpoints(breakpoints);
                });
            }

            WI.TreeOutline.prototype.populateContextMenu(contextMenu, event, treeElement);
        };

        let breakpointsRow = new WI.DetailsSectionRow;
        breakpointsRow.element.appendChild(this._breakpointsTreeOutline.element);

        let breakpointNavigationBarWrapper = document.createElement("div");

        let breakpointNavigationBar = new WI.NavigationBar;
        breakpointNavigationBarWrapper.appendChild(breakpointNavigationBar.element);

        this._createBreakpointButton = new WI.ButtonNavigationItem("create-breakpoint", WI.UIString("Create Breakpoint"), "Images/Plus13.svg", 13, 13);
        WI.addMouseDownContextMenuHandlers(this._createBreakpointButton.element, this._populateCreateBreakpointContextMenu.bind(this));
        breakpointNavigationBar.addNavigationItem(this._createBreakpointButton);

        let breakpointsGroup = new WI.DetailsSectionGroup([breakpointsRow]);
        this._breakpointsSection = new WI.DetailsSection("breakpoints", WI.UIString("Breakpoints"), [breakpointsGroup], breakpointNavigationBarWrapper);

        this._breakpointsContainer = document.createElement("div");
        this._breakpointsContainer.classList.add("breakpoints-container");
        this._breakpointsContainer.appendChild(this._breakpointsSection.element);

        this.contentView.element.insertBefore(this._breakpointsContainer, this.contentView.element.firstChild);

        this._resourcesNavigationBar = new WI.NavigationBar;
        this.contentView.addSubview(this._resourcesNavigationBar);
        this.contentView.element.insertBefore(this._resourcesNavigationBar.element, this._breakpointsContainer.nextSibling);

        this._resourceGroupingModeScopeBarItems = {};
        let createResourceGroupingModeScopeBarItem = (mode, label) => {
            this._resourceGroupingModeScopeBarItems[mode] = new WI.ScopeBarItem("sources-resource-grouping-mode-" + mode, label, {exclusive: true});
            this._resourceGroupingModeScopeBarItems[mode][SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol] = mode;
        };
        createResourceGroupingModeScopeBarItem(WI.Resource.GroupingMode.Type, WI.UIString("By Type"));
        createResourceGroupingModeScopeBarItem(WI.Resource.GroupingMode.Path, WI.UIString("By Path"));

        this._resourceGroupingModeScopeBar = new WI.ScopeBar("sources-resource-grouping-mode-scope-bar", Object.values(this._resourceGroupingModeScopeBarItems), this._resourceGroupingModeScopeBarItems[WI.settings.resourceGroupingMode.value]);
        this._resourceGroupingModeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleResourceGroupingModeScopeBarSelectionChanged, this);
        this._resourcesNavigationBar.addNavigationItem(this._resourceGroupingModeScopeBar);

        let resourcesContainer = document.createElement("div");
        resourcesContainer.classList.add("resources-container");
        this.contentView.element.insertBefore(resourcesContainer, this._resourcesNavigationBar.element.nextSibling);

        this._resourcesTreeOutline = this.contentTreeOutline;
        this._resourcesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
        this._resourcesTreeOutline.includeSourceMapResourceChildren = true;
        resourcesContainer.appendChild(this._resourcesTreeOutline.element);

        if (InspectorBackend.domains.CSS) {
            let createResourceNavigationBar = new WI.NavigationBar;

            let createResourceButtonNavigationItem = new WI.ButtonNavigationItem("create-resource", WI.UIString("Create Resource"), "Images/Plus15.svg", 15, 15);
            WI.addMouseDownContextMenuHandlers(createResourceButtonNavigationItem.element, this._populateCreateResourceContextMenu.bind(this));
            createResourceNavigationBar.addNavigationItem(createResourceButtonNavigationItem);

            this.filterBar.element.insertBefore(createResourceNavigationBar.element, this.filterBar.element.firstChild);
        }

        const activatedByDefault = false;
        this.filterBar.addFilterBarButton("sources-only-show-resources-with-issues", this._filterByResourcesWithIssues.bind(this), activatedByDefault, WI.UIString("Only show resources with issues"), WI.UIString("Show all resources"), "Images/Errors.svg", 15, 15);

        const resourceTypeScopeItemPrefix = "sources-resource-type-";
        let resourceTypeScopeBarItems = [];
        resourceTypeScopeBarItems.push(new WI.ScopeBarItem(resourceTypeScopeItemPrefix + "all", WI.UIString("All")));
        for (let value of Object.values(WI.Resource.Type)) {
            let scopeBarItem = new WI.ScopeBarItem(resourceTypeScopeItemPrefix + value, WI.Resource.displayNameForType(value, true));
            scopeBarItem[SourcesNavigationSidebarPanel.ResourceTypeSymbol] = value;
            resourceTypeScopeBarItems.push(scopeBarItem);
        }

        const shouldGroupNonExclusiveItems = true;
        this._resourceTypeScopeBar = new WI.ScopeBar("sources-resource-type-scope-bar", resourceTypeScopeBarItems, resourceTypeScopeBarItems[0], shouldGroupNonExclusiveItems);
        this._resourceTypeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleResourceTypeScopeBarSelectionChanged, this);
        this.filterBar.addFilterNavigationItem(this._resourceTypeScopeBar);

        WI.settings.resourceGroupingMode.addEventListener(WI.Setting.Event.Changed, this._handleResourceGroupingModeChanged, this);

        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
        WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._handleResourceAdded, this);
        WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._handleResourceAdded, this);

        WI.networkManager.addEventListener(WI.NetworkManager.Event.FrameWasAdded, this._handleFrameWasAdded, this);

        if (WI.NetworkManager.supportsLocalResourceOverrides()) {
            WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideAdded, this._handleLocalResourceOverrideAdded, this);
            WI.networkManager.addEventListener(WI.NetworkManager.Event.LocalResourceOverrideRemoved, this._handleLocalResourceOverrideRemoved, this);
        }

        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointAdded, this._handleDebuggerBreakpointAdded, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._handleDebuggerBreakpointAdded, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointAdded, this._handleDebuggerBreakpointAdded, this);

        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);
        WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointRemoved, this._handleDebuggerBreakpointRemoved, this);

        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._handleDebuggerBreakpointsEnabledDidChange, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptAdded, this._handleDebuggerScriptAdded, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptRemoved, this._handleDebuggerScriptRemoved, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptsCleared, this._handleDebuggerScriptsCleared, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, this._handleDebuggerPaused, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, this._handleDebuggerResumed, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, this._handleDebuggerCallFramesDidChange, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._handleDebuggerActiveCallFrameDidChange, this);
        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.WaitingToPause, this._handleDebuggerWaitingToPause, this);

        WI.Breakpoint.addEventListener(WI.Breakpoint.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
        WI.IssueMessage.addEventListener(WI.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);

        WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeChanged, this._handleDOMBreakpointDOMNodeChanged, this);

        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._handleConsoleIssueAdded, this);
        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._handleConsoleCleared, this);

        WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);

        WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
        WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);

        WI.cssManager.addEventListener(WI.CSSManager.Event.StyleSheetAdded, this._handleCSSStyleSheetAdded, this);

        WI.targetManager.addEventListener(WI.TargetManager.Event.TargetAdded, this._handleTargetAdded, this);
        WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._handleTargetRemoved, this);

        WI.notifications.addEventListener(WI.Notification.ExtraDomainsActivated, this._handleExtraDomainsActivated, this);

        if (WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
            this._resourcesTreeOutline.disclosureButtons = false;
            WI.SourceCode.addEventListener(WI.SourceCode.Event.SourceMapAdded, () => {
                this._resourcesTreeOutline.disclosureButtons = true;
            }, this);
        }

        WI.debuggerManager.addBreakpoint(WI.debuggerManager.allExceptionsBreakpoint);
        WI.debuggerManager.addBreakpoint(WI.debuggerManager.uncaughtExceptionsBreakpoint);

        // COMPATIBILITY (iOS 10): DebuggerAgent.setPauseOnAssertions did not exist yet.
        if (InspectorBackend.domains.Debugger.setPauseOnAssertions && WI.settings.showAssertionFailuresBreakpoint.value)
            WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);

        // COMPATIBILITY (iOS 13): DebuggerAgent.setPauseOnMicrotasks did not exist yet.
        if (InspectorBackend.domains.Debugger.setPauseOnMicrotasks && WI.settings.showAllMicrotasksBreakpoint.value)
            WI.debuggerManager.addBreakpoint(WI.debuggerManager.allMicrotasksBreakpoint);

        for (let target of WI.targets)
            this._addTarget(target);

        this._updateCallStackTreeOutline();

        this._handleResourceGroupingModeChanged();

        if (WI.NetworkManager.supportsLocalResourceOverrides()) {
            for (let localResourceOverride of WI.networkManager.localResourceOverrides)
                this._addLocalResourceOverride(localResourceOverride);
        }

        if (WI.domDebuggerManager.supported) {
            if (WI.settings.showAllAnimationFramesBreakpoint.value)
                WI.domDebuggerManager.addEventBreakpoint(WI.domDebuggerManager.allAnimationFramesBreakpoint);

            if (WI.settings.showAllTimeoutsBreakpoint.value)
                WI.domDebuggerManager.addEventBreakpoint(WI.domDebuggerManager.allTimeoutsBreakpoint);

            if (WI.settings.showAllIntervalsBreakpoint.value)
                WI.domDebuggerManager.addEventBreakpoint(WI.domDebuggerManager.allIntervalsBreakpoint);

            if (WI.settings.showAllListenersBreakpoint.value)
                WI.domDebuggerManager.addEventBreakpoint(WI.domDebuggerManager.allListenersBreakpoint);

            for (let eventBreakpoint of WI.domDebuggerManager.listenerBreakpoints)
                this._addBreakpoint(eventBreakpoint);

            for (let eventListenerBreakpoint of WI.domManager.eventListenerBreakpoints)
                this._addBreakpoint(eventListenerBreakpoint);

            for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
                this._addBreakpoint(domBreakpoint);

            if (WI.settings.showAllRequestsBreakpoint.value)
                WI.domDebuggerManager.addURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);

            for (let urlBreakpoints of WI.domDebuggerManager.urlBreakpoints)
                this._addBreakpoint(urlBreakpoints);
        }

        if (WI.debuggerManager.paused)
            this._handleDebuggerPaused();

        if (WI.debuggerManager.breakpointsDisabledTemporarily) {
            this._handleTimelineCapturingStateChanged();

            if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping)
                this._handleAuditManagerTestScheduled();
        }

        this._updateBreakpointsDisabledBanner();
    }

    // Static

    static shouldPlaceResourcesAtTopLevel()
    {
        return (WI.sharedApp.debuggableType === WI.DebuggableType.JavaScript && !WI.sharedApp.hasExtraDomains)
            || WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker;
    }

    // Public

    get minimumWidth()
    {
        return Math.max(this._debuggerNavigationBar.minimumWidth, this._resourcesNavigationBar.minimumWidth);
    }

    closed()
    {
        WI.settings.resourceGroupingMode.removeEventListener(null, null, this);
        WI.Frame.removeEventListener(null, null, this);
        WI.Target.removeEventListener(null, null, this);
        WI.networkManager.removeEventListener(null, null, this);
        WI.debuggerManager.removeEventListener(null, null, this);
        WI.domDebuggerManager.removeEventListener(null, null, this);
        WI.Breakpoint.removeEventListener(null, null, this);
        WI.IssueMessage.removeEventListener(null, null, this);
        WI.DOMBreakpoint.removeEventListener(null, null, this);
        WI.consoleManager.removeEventListener(null, null, this);
        WI.timelineManager.removeEventListener(null, null, this);
        WI.auditManager.removeEventListener(null, null, this);
        WI.cssManager.removeEventListener(null, null, this);
        WI.targetManager.removeEventListener(null, null, this);
        WI.notifications.removeEventListener(null, null, this);
        WI.SourceCode.removeEventListener(null, null, this);

        super.closed();
    }

    showDefaultContentView()
    {
        if (WI.networkManager.mainFrame) {
            this.contentBrowser.showContentViewForRepresentedObject(WI.networkManager.mainFrame);
            return;
        }

        let firstTreeElement = this._resourcesTreeOutline.children[0];
        if (firstTreeElement)
            this.showDefaultContentViewForTreeElement(firstTreeElement);
    }

    treeElementForRepresentedObject(representedObject)
    {
        // A custom implementation is needed for this since the frames are populated lazily.

        if (representedObject instanceof WI.LocalResourceOverride)
            return this._localResourceOverridesTreeOutline.findTreeElement(representedObject);

        if (representedObject instanceof WI.LocalResource) {
            let localResourceOverride = WI.networkManager.localResourceOverrideForURL(representedObject.url);
            return this._localResourceOverridesTreeOutline.findTreeElement(localResourceOverride);
        }

        if (!this._mainFrameTreeElement && (representedObject instanceof WI.Resource || representedObject instanceof WI.Frame || representedObject instanceof WI.Collection)) {
            // All resources are under the main frame, so we need to return early if we don't have the main frame yet.
            return null;
        }

        switch (WI.settings.resourceGroupingMode.value) {
        case WI.Resource.GroupingMode.Path:
            if (representedObject instanceof WI.Frame)
                representedObject = representedObject.mainResource;
            break;

        default:
            WI.reportInternalError("Unknown resource grouping mode", {"Resource Grouping Mode": WI.settings.resourceGroupingMode.value});
            // Fallthrough for default value.

        case WI.Resource.GroupingMode.Type:
            if (representedObject instanceof WI.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
                representedObject = representedObject.parentFrame;
            break;
        }

        function isAncestor(ancestor, resourceOrFrame) {
            // SourceMapResources are descendants of another SourceCode object.
            if (resourceOrFrame instanceof WI.SourceMapResource) {
                if (resourceOrFrame.sourceMap.originalSourceCode === ancestor)
                    return true;

                // Not a direct ancestor, so check the ancestors of the parent SourceCode object.
                resourceOrFrame = resourceOrFrame.sourceMap.originalSourceCode;
            }

            let currentFrame = resourceOrFrame.parentFrame;
            while (currentFrame) {
                if (currentFrame === ancestor)
                    return true;
                currentFrame = currentFrame.parentFrame;
            }
            return false;
        }

        function getParent(resourceOrFrame) {
            // SourceMapResources are descendants of another SourceCode object.
            if (resourceOrFrame instanceof WI.SourceMapResource)
                return resourceOrFrame.sourceMap.originalSourceCode;
            return resourceOrFrame.parentFrame;
        }

        function searchTreeOutline(treeOutline, forceSearch) {
            if (!treeOutline || (!treeOutline.selectedTreeElement && !forceSearch))
                return null;
            return treeOutline.findTreeElement(representedObject, isAncestor, getParent);
        }
        let treeElement = searchTreeOutline(this._pauseReasonTreeOutline) || searchTreeOutline(this._callStackTreeOutline) || searchTreeOutline(this._breakpointsTreeOutline) || searchTreeOutline(this._resourcesTreeOutline, true);
        if (treeElement)
            return treeElement;

        // Only special case Script objects.
        if (!(representedObject instanceof WI.Script)) {
            console.error("Didn't find a TreeElement for representedObject", representedObject);
            return null;
        }

        // If the Script has a URL we should have found it earlier.
        if (representedObject.url) {
            console.error("Didn't find a ScriptTreeElement for a Script with a URL.");
            return null;
        }

        // Since the Script does not have a URL we consider it an 'anonymous' script. These scripts happen from calls to
        // window.eval() or browser features like Auto Fill and Reader. They are not normally added to the sidebar, but since
        // we have a ScriptContentView asking for the tree element we will make a ScriptTreeElement on demand and add it.

        if (!this._anonymousScriptsFolderTreeElement)
            this._anonymousScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Anonymous Scripts"), new WI.ScriptCollection);

        if (!this._anonymousScriptsFolderTreeElement.parent) {
            let index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
            this._resourcesTreeOutline.insertChild(this._anonymousScriptsFolderTreeElement, index);
        }

        this._anonymousScriptsFolderTreeElement.representedObject.add(representedObject);

        let scriptTreeElement = new WI.ScriptTreeElement(representedObject);
        this._anonymousScriptsFolderTreeElement.appendChild(scriptTreeElement);
        return scriptTreeElement;
    }

    // Protected

    createContentTreeOutline(options = {})
    {
        let treeOutline = super.createContentTreeOutline(options);

        treeOutline.addEventListener(WI.TreeOutline.Event.ElementRevealed, (event) => {
            let treeElement = event.data.element;
            let detailsSections = [this._pauseReasonSection, this._callStackSection, this._breakpointsSection, this._localResourceOverridesSection];
            let detailsSection = detailsSections.find((detailsSection) => detailsSection.element.contains(treeElement.listItemElement));
            if (!detailsSection)
                return;

            // Revealing a TreeElement at the scroll container's topmost edge with
            // scrollIntoViewIfNeeded may result in the element being covered by the
            // DetailsSection header, which uses sticky positioning. Detect this case,
            // and adjust the sidebar content's scroll position to compensate.
            let offset = detailsSection.headerElement.totalOffsetBottom - treeElement.listItemElement.totalOffsetTop;
            if (offset > 0)
                this.scrollElement.scrollBy(0, -offset);
        });

        return treeOutline;
    }

    resetFilter()
    {
        this._resourceTypeScopeBar.resetToDefault();

        super.resetFilter();
    }

    hasCustomFilters()
    {
        console.assert(this._resourceTypeScopeBar.selectedItems.length === 1);
        let selectedScopeBarItem = this._resourceTypeScopeBar.selectedItems[0];
        return selectedScopeBarItem && selectedScopeBarItem !== this._resourceTypeScopeBar.defaultItem;
    }

    matchTreeElementAgainstCustomFilters(treeElement, flags)
    {
        // Only apply the resource type filter to the resources list.
        if (treeElement.treeOutline !== this._resourcesTreeOutline)
            return true;

        console.assert(this._resourceTypeScopeBar.selectedItems.length === 1);
        let selectedScopeBarItem = this._resourceTypeScopeBar.selectedItems[0];

        // Show everything if there is no selection or "All Resources" is selected (the default item).
        if (!selectedScopeBarItem || selectedScopeBarItem === this._resourceTypeScopeBar.defaultItem)
            return true;

        // Folders are hidden on the first pass, but visible childen under the folder will force the folder visible again.
        if (treeElement instanceof WI.FolderTreeElement || treeElement instanceof WI.OriginTreeElement)
            return false;

        if (treeElement instanceof WI.IssueTreeElement)
            treeElement = treeElement.parent;

        function match()
        {
            if (treeElement instanceof WI.FrameTreeElement)
                return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Document;

            if (treeElement instanceof WI.ScriptTreeElement)
                return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.Script;

            if (treeElement instanceof WI.CSSStyleSheetTreeElement)
                return selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol] === WI.Resource.Type.StyleSheet;

            console.assert(treeElement instanceof WI.ResourceTreeElement, "Unknown treeElement", treeElement);
            if (!(treeElement instanceof WI.ResourceTreeElement))
                return false;

            return treeElement.resource.type === selectedScopeBarItem[WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol];
        }

        let matched = match();
        if (matched)
            flags.expandTreeElement = true;
        return matched;
    }

    // Popover delegate

    willDismissPopover(popover)
    {
        if (popover instanceof WI.LocalResourceOverridePopover) {
            this._willDismissLocalOverridePopover(popover);
            return;
        }

        if (popover instanceof WI.EventBreakpointPopover) {
            this._willDismissEventBreakpointPopover(popover);
            return;
        }

        if (popover instanceof WI.URLBreakpointPopover) {
            this._willDismissURLBreakpointPopover(popover);
            return;
        }

        console.assert();
    }

    // Private

    _willDismissLocalOverridePopover(popover)
    {
        let serializedData = popover.serializedData;
        if (!serializedData) {
            InspectorFrontendHost.beep();
            return;
        }

        let {url, mimeType, statusCode, statusText, headers} = serializedData;

        // Do not conflict with an existing override.
        let existingOverride = WI.networkManager.localResourceOverrideForURL(url);
        if (existingOverride) {
            InspectorFrontendHost.beep();
            return;
        }

        let localResourceOverride = WI.LocalResourceOverride.create({
            url,
            mimeType,
            statusCode,
            statusText,
            headers,
            content: "",
            base64Encoded: false,
        });

        WI.networkManager.addLocalResourceOverride(localResourceOverride);
        WI.showLocalResourceOverride(localResourceOverride);
    }

    _willDismissEventBreakpointPopover(popover)
    {
        let breakpoint = popover.breakpoint;
        if (!breakpoint)
            return;

        WI.domDebuggerManager.addEventBreakpoint(breakpoint);
    }

    _willDismissURLBreakpointPopover(popover)
    {
        let breakpoint = popover.breakpoint;
        if (!breakpoint)
            return;

        WI.domDebuggerManager.addURLBreakpoint(breakpoint);
    }

    _filterByResourcesWithIssues(treeElement)
    {
        if (treeElement.treeOutline !== this._resourcesTreeOutline)
            return true;

        if (treeElement instanceof WI.IssueTreeElement)
            return true;

        if (treeElement.hasChildren) {
            for (let child of treeElement.children) {
                if (child instanceof WI.IssueTreeElement)
                    return true;
            }
        }
        return false;
    }

    _compareTreeElements(a, b)
    {
        const rankFunctions = [
            (treeElement) => treeElement instanceof WI.CSSStyleSheetTreeElement && treeElement.representedObject.isInspectorStyleSheet(),
            (treeElement) => treeElement === this._mainFrameTreeElement,
            (treeElement) => treeElement instanceof WI.FrameTreeElement,
            (treeElement) => treeElement instanceof WI.OriginTreeElement,
            (treeElement) => {
                return treeElement !== this._extensionScriptsFolderTreeElement
                    && treeElement !== this._extraScriptsFolderTreeElement
                    && treeElement !== this._anonymousScriptsFolderTreeElement;
            },
            (treeElement) => treeElement === this._extensionScriptsFolderTreeElement,
            (treeElement) => treeElement === this._extraScriptsFolderTreeElement,
            (treeElement) => treeElement === this._anonymousScriptsFolderTreeElement,
        ];

        let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
        let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
        if ((aRank >= 0 && bRank < 0) || aRank < bRank)
            return -1;
        if ((bRank >= 0 && aRank < 0) || bRank < aRank)
            return 1;

        return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
    }

    _closeContentViewsFilter(contentView)
    {
        // Local Resource Override content views do not need to be closed across page navigations.
        if (contentView.representedObject instanceof WI.LocalResource && contentView.representedObject.isLocalResourceOverride)
            return false;

        return true;
    }

    _updateMainFrameTreeElement(mainFrame)
    {
        if (this.didInitialLayout)
            this.contentBrowser.contentViewContainer.closeAllContentViews(this._closeContentViewsFilter);

        let oldMainFrameTreeElement = this._mainFrameTreeElement;
        if (this._mainFrameTreeElement) {
            this._resourcesTreeOutline.removeChild(this._mainFrameTreeElement);
            this._mainFrameTreeElement = null;
        }

        if (!mainFrame)
            return;

        switch (WI.settings.resourceGroupingMode.value) {
        case WI.Resource.GroupingMode.Path: {
            for (let treeElement of this._originTreeElementMap.values()) {
                if (treeElement !== oldMainFrameTreeElement)
                    this._resourcesTreeOutline.removeChild(treeElement);
            }
            this._originTreeElementMap.clear();

            let origin = mainFrame.urlComponents.origin;
            this._mainFrameTreeElement = new WI.OriginTreeElement(origin, mainFrame, {hasChildren: true});
            this._originTreeElementMap.set(origin, this._mainFrameTreeElement);
            break;
        }

        default:
            WI.reportInternalError("Unknown resource grouping mode", {"Resource Grouping Mode": WI.settings.resourceGroupingMode.value});
            // Fallthrough for default value.

        case WI.Resource.GroupingMode.Type:
            this._mainFrameTreeElement = new WI.FrameTreeElement(mainFrame);
            break;
        }

        this._resourcesTreeOutline.insertChild(this._mainFrameTreeElement, 0);

        // Cookie restoration will attempt to re-select the resource we were showing.
        // Give it time to do that before selecting the main frame resource.
        setTimeout(() => {
            if (this._resourcesTreeOutline.selectedTreeElement)
                return;

            let currentContentView = this.contentBrowser.currentContentView;
            let treeElement = currentContentView ? this.treeElementForRepresentedObject(currentContentView.representedObject) : null;
            if (!treeElement)
                treeElement = this.treeElementForRepresentedObject(WI.networkManager.mainFrame);
            this.showDefaultContentViewForTreeElement(treeElement);
        });
    }

    _addTarget(target)
    {
        let treeElement = new WI.ThreadTreeElement(target);
        this._callStackTreeOutline.appendChild(treeElement);

        // FIXME: When WI.mainTarget changes?
        if (target === WI.mainTarget)
            this._mainTargetTreeElement = treeElement;

        this._updateCallStackTreeOutline();
    }

    _findCallStackTargetTreeElement(target)
    {
        for (let child of this._callStackTreeOutline.children) {
            if (child.target === target)
                return child;
        }
        return null;
    }

    _updateCallStackTreeOutline()
    {
        let singleThreadShowing = WI.targets.length <= 1;
        this._callStackTreeOutline.element.classList.toggle("single-thread", singleThreadShowing);
        if (this._mainTargetTreeElement)
            this._mainTargetTreeElement.selectable = !singleThreadShowing;
    }

    _addResource(resource)
    {
        if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
            if (!this._mainFrameTreeElement || this._resourcesTreeOutline.findTreeElement(resource))
                return;

            let parentTreeElement = null;

            if (resource instanceof WI.CSSStyleSheet && resource.isInspectorStyleSheet())
                parentTreeElement = this._resourcesTreeOutline.findTreeElement(resource.parentFrame.mainResource);

            if (!parentTreeElement) {
                let origin = resource.urlComponents.origin;
                if (origin) {
                    let originTreeElement = this._originTreeElementMap.get(origin);
                    if (!originTreeElement) {
                        originTreeElement = new WI.OriginTreeElement(origin, resource.parentFrame, {hasChildren: true});
                        this._originTreeElementMap.set(origin, originTreeElement);

                        let index = insertionIndexForObjectInListSortedByFunction(originTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
                        this._resourcesTreeOutline.insertChild(originTreeElement, index);
                    }

                    let subpath = resource.urlComponents.path;
                    if (subpath && subpath[0] === "/")
                        subpath = subpath.substring(1);

                    parentTreeElement = originTreeElement.createFoldersAsNeededForSubpath(subpath, this._boundCompareTreeElements);
                } else
                    parentTreeElement = this._resourcesTreeOutline;
            }

            let resourceTreeElement = null;
            if (resource instanceof WI.CSSStyleSheet)
                resourceTreeElement = new WI.CSSStyleSheetTreeElement(resource);
            else
                resourceTreeElement = new WI.ResourceTreeElement(resource, resource, {allowDirectoryAsName: true, hideOrigin: true});

            let index = insertionIndexForObjectInListSortedByFunction(resourceTreeElement, parentTreeElement.children, this._boundCompareTreeElements);
            parentTreeElement.insertChild(resourceTreeElement, index);
        }

        if (resource.type === WI.Resource.Type.Document || resource.type === WI.Resource.Type.Script) {
            this._addBreakpointsForSourceCode(resource);
            this._addIssuesForSourceCode(resource);
        }
    }

    _addResourcesRecursivelyForFrame(frame)
    {
        this._addResource(frame.mainResource);

        for (let resource of frame.resourceCollection)
            this._addResource(resource);

        for (let childFrame of frame.childFrameCollection)
            this._addResourcesRecursivelyForFrame(childFrame);

        if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
            for (let styleSheet of WI.cssManager.inspectorStyleSheetsForFrame(frame))
                this._addResource(styleSheet);
        }
    }

    _addScript(script)
    {
        // We don't add scripts without URLs here. Those scripts can quickly clutter the interface and
        // are usually more transient. They will get added if/when they need to be shown in a content view.
        if (!script.url && !script.sourceURL)
            return;

        // Target main resource.
        if (WI.sharedApp.debuggableType !== WI.DebuggableType.JavaScript) {
            if (script.target !== WI.pageTarget) {
                if (script.isMainResource()) {
                    this._addWorkerTargetWithMainResource(script.target);
                    this._addBreakpointsForSourceCode(script);
                    this._addIssuesForSourceCode(script);
                }
                this._resourcesTreeOutline.disclosureButtons = true;
                return;
            }
        }

        // If the script URL matches a resource we can assume it is part of that resource and does not need added.
        if (script.resource || script.dynamicallyAddedScriptElement)
            return;

        let scriptTreeElement = new WI.ScriptTreeElement(script);

        if (!script.injected && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
            let index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
            this._resourcesTreeOutline.insertChild(scriptTreeElement, index);
        } else {
            let parentFolderTreeElement = null;

            if (script.injected) {
                if (!this._extensionScriptsFolderTreeElement) {
                    let collection = new WI.ScriptCollection;
                    this._extensionScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extension Scripts"), collection);
                }

                parentFolderTreeElement = this._extensionScriptsFolderTreeElement;
            } else {
                if (!this._extraScriptsFolderTreeElement) {
                    let collection = new WI.ScriptCollection;
                    this._extraScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extra Scripts"), collection);
                }

                parentFolderTreeElement = this._extraScriptsFolderTreeElement;
            }

            if (parentFolderTreeElement)
                parentFolderTreeElement.representedObject.add(script);

            if (!parentFolderTreeElement.parent) {
                let index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
                this._resourcesTreeOutline.insertChild(parentFolderTreeElement, index);
            }

            parentFolderTreeElement.appendChild(scriptTreeElement);
        }

        this._addBreakpointsForSourceCode(script);
        this._addIssuesForSourceCode(script);
    }

    _addWorkerTargetWithMainResource(target)
    {
        console.assert(target.type === WI.Target.Type.Worker || target.type === WI.Target.Type.ServiceWorker);

        let targetTreeElement = new WI.WorkerTreeElement(target);
        this._workerTargetTreeElementMap.set(target, targetTreeElement);

        let index = insertionIndexForObjectInListSortedByFunction(targetTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
        this._resourcesTreeOutline.insertChild(targetTreeElement, index);
    }

    _addDebuggerTreeElementForSourceCode(sourceCode)
    {
        let treeElement = this._breakpointsTreeOutline.findTreeElement(sourceCode);
        if (!treeElement) {
            if (sourceCode instanceof WI.SourceMapResource)
                treeElement = new WI.SourceMapResourceTreeElement(sourceCode);
            else if (sourceCode instanceof WI.Resource)
                treeElement = new WI.ResourceTreeElement(sourceCode);
            else if (sourceCode instanceof WI.Script)
                treeElement = new WI.ScriptTreeElement(sourceCode);
        }

        if (!treeElement) {
            console.error("Unknown sourceCode instance", sourceCode);
            return null;
        }

        if (!treeElement.parent) {
            treeElement.hasChildren = false;
            treeElement.expand();

            this._insertDebuggerTreeElement(treeElement, this._breakpointsTreeOutline);
        }

        return treeElement;
    }

    _insertDebuggerTreeElement(treeElement, parentTreeElement)
    {
        let comparator = (a, b) => {
            const rankFunctions = [
                (treeElement) => treeElement.representedObject === WI.debuggerManager.allExceptionsBreakpoint,
                (treeElement) => treeElement.representedObject === WI.debuggerManager.uncaughtExceptionsBreakpoint,
                (treeElement) => treeElement.representedObject === WI.debuggerManager.assertionFailuresBreakpoint,
                (treeElement) => treeElement instanceof WI.BreakpointTreeElement || treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement,
                (treeElement) => treeElement.representedObject === WI.debuggerManager.allMicrotasksBreakpoint,
                (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allAnimationFramesBreakpoint,
                (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allTimeoutsBreakpoint,
                (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allIntervalsBreakpoint,
                (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allListenersBreakpoint,
                (treeElement) => treeElement instanceof WI.EventBreakpointTreeElement,
                (treeElement) => treeElement instanceof WI.DOMNodeTreeElement,
                (treeElement) => treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject,
                (treeElement) => treeElement instanceof WI.DOMBreakpointTreeElement,
                (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allRequestsBreakpoint,
                (treeElement) => treeElement instanceof WI.URLBreakpointTreeElement,
            ];

            let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
            let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
            if (aRank >= 0 && bRank >= 0) {
                if (aRank < bRank)
                    return -1;
                if (bRank < aRank)
                    return 1;
            }

            if (a instanceof WI.BreakpointTreeElement && b instanceof WI.BreakpointTreeElement)
                return this._compareBreakpointTreeElements(a, b);

            return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
        };

        parentTreeElement.insertChild(treeElement, insertionIndexForObjectInListSortedByFunction(treeElement, parentTreeElement.children, comparator));
    }

    _compareBreakpointTreeElements(a, b)
    {
        if (!a.representedObject || !b.representedObject)
            return 0;

        let aLocation = a.representedObject.sourceCodeLocation;
        let bLocation = b.representedObject.sourceCodeLocation;
        if (!aLocation || !bLocation)
            return 0;

        return aLocation.displayLineNumber - bLocation.displayLineNumber || aLocation.displayColumnNumber - bLocation.displayColumnNumber;
    }

    _addBreakpoint(breakpoint)
    {
        if (this._breakpointsTreeOutline.findTreeElement(breakpoint))
            return null;

        let constructor = WI.BreakpointTreeElement;
        let options = {};
        let parentTreeElement = this._breakpointsTreeOutline;

        let getDOMNodeTreeElement = (domNode) => {
            console.assert(domNode, "Missing DOMNode for identifier", breakpoint.domNodeIdentifier);
            if (!domNode)
                return null;

            let domNodeTreeElement = this._breakpointsTreeOutline.findTreeElement(domNode);
            if (!domNodeTreeElement) {
                domNodeTreeElement = new WI.DOMNodeTreeElement(domNode);
                this._insertDebuggerTreeElement(domNodeTreeElement, this._breakpointsTreeOutline);
            }
            return domNodeTreeElement;
        };

        if (breakpoint === WI.debuggerManager.allExceptionsBreakpoint) {
            options.className = "breakpoint-exception-icon";
            options.title = WI.repeatedUIString.allExceptions();
        } else if (breakpoint === WI.debuggerManager.uncaughtExceptionsBreakpoint) {
            options.className = "breakpoint-exception-icon";
            options.title = WI.repeatedUIString.uncaughtExceptions();
        } else if (breakpoint === WI.debuggerManager.assertionFailuresBreakpoint) {
            options.className = "breakpoint-assertion-icon";
            options.title = WI.repeatedUIString.assertionFailures();
        } else if (breakpoint === WI.debuggerManager.allMicrotasksBreakpoint) {
            options.className = "breakpoint-microtask-icon";
            options.title = WI.UIString("All Microtasks");
        } else if (breakpoint instanceof WI.DOMBreakpoint) {
            if (!breakpoint.domNodeIdentifier)
                return null;

            constructor = WI.DOMBreakpointTreeElement;

            let domNode = WI.domManager.nodeForId(breakpoint.domNodeIdentifier);
            parentTreeElement = getDOMNodeTreeElement(domNode);
        } else if (breakpoint instanceof WI.EventBreakpoint) {
            constructor = WI.EventBreakpointTreeElement;

            if (breakpoint === WI.domDebuggerManager.allAnimationFramesBreakpoint)
                options.title = WI.UIString("All Animation Frames");
            else if (breakpoint === WI.domDebuggerManager.allIntervalsBreakpoint)
                options.title = WI.UIString("All Intervals");
            else if (breakpoint === WI.domDebuggerManager.allListenersBreakpoint)
                options.title = WI.UIString("All Events");
            else if (breakpoint === WI.domDebuggerManager.allTimeoutsBreakpoint)
                options.title = WI.UIString("All Timeouts");
            else if (breakpoint.eventListener) {
                let eventTargetTreeElement = null;
                if (breakpoint.eventListener.onWindow) {
                    if (!SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
                        SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject = {__window: true};

                    eventTargetTreeElement = this._breakpointsTreeOutline.findTreeElement(SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
                    if (!eventTargetTreeElement) {
                        const subtitle = null;
                        eventTargetTreeElement = new WI.GeneralTreeElement(["event-target-window"], WI.unlocalizedString("window"), subtitle, SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject);
                        this._insertDebuggerTreeElement(eventTargetTreeElement, this._breakpointsTreeOutline);
                    }
                } else if (breakpoint.eventListener.node)
                    eventTargetTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
                if (eventTargetTreeElement)
                    parentTreeElement = eventTargetTreeElement;
            }
        } else if (breakpoint instanceof WI.URLBreakpoint) {
            constructor = WI.URLBreakpointTreeElement;

            if (breakpoint === WI.domDebuggerManager.allRequestsBreakpoint)
                options.title = WI.repeatedUIString.allRequests();
        } else {
            let sourceCode = breakpoint.sourceCodeLocation && breakpoint.sourceCodeLocation.displaySourceCode;
            if (!sourceCode)
                return null;

            parentTreeElement = this._addDebuggerTreeElementForSourceCode(sourceCode);

            // Mark disabled breakpoints as resolved if there is source code loaded with that URL.
            // This gives the illusion the breakpoint was resolved, but since we don't send disabled
            // breakpoints to the backend we don't know for sure. If the user enables the breakpoint
            // it will be resolved properly.
            if (breakpoint.disabled)
                breakpoint.resolved = true;
        }

        let breakpointTreeElement = new constructor(breakpoint, options);
        this._insertDebuggerTreeElement(breakpointTreeElement, parentTreeElement);
        if (parentTreeElement.children.length === 1)
            parentTreeElement.expand();
        return breakpointTreeElement;
    }

    _removeBreakpoint(breakpoint)
    {
        if (this._pauseReasonTreeOutline) {
            let pauseReasonBreakpointTreeElement = this._pauseReasonTreeOutline.findTreeElement(breakpoint);
            if (pauseReasonBreakpointTreeElement)
                pauseReasonBreakpointTreeElement.status = null;
        }

        let breakpointTreeElement = this._breakpointsTreeOutline.findTreeElement(breakpoint);
        if (!breakpointTreeElement)
            return;

        this._removeDebuggerTreeElement(breakpointTreeElement);
    }

    _removeAllBreakpoints(breakpoints)
    {
        for (let breakpoint of breakpoints) {
            if (WI.debuggerManager.isBreakpointRemovable(breakpoint))
                WI.debuggerManager.removeBreakpoint(breakpoint);
        }
    }

    _toggleAllBreakpoints(breakpoints, disabled)
    {
        for (let breakpoint of breakpoints)
            breakpoint.disabled = disabled;
    }

    _breakpointsBeneathTreeElement(treeElement)
    {
        console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
        if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
            return [];

        let breakpoints = [];
        for (let child of treeElement.children) {
            console.assert(child instanceof WI.BreakpointTreeElement);
            let breakpoint = child.breakpoint;
            console.assert(breakpoint);
            if (breakpoint)
                breakpoints.push(breakpoint);
        }
        return breakpoints;
    }

    _addIssue(issueMessage, sourceCode)
    {
        let issueTreeElement = this._resourcesTreeOutline.findTreeElement(issueMessage);
        if (!issueTreeElement) {
            console.assert(sourceCode || (issueMessage.sourceCodeLocation && issueMessage.sourceCodeLocation.sourceCode));
            let parentTreeElement = this._resourcesTreeOutline.findTreeElement(sourceCode || issueMessage.sourceCodeLocation.sourceCode);
            if (!parentTreeElement)
                return null;

            issueTreeElement = new WI.IssueTreeElement(issueMessage);

            parentTreeElement.insertChild(issueTreeElement, insertionIndexForObjectInListSortedByFunction(issueTreeElement, parentTreeElement.children, this._compareBreakpointTreeElements));
            if (parentTreeElement.children.length === 1)
                parentTreeElement.expand();
        }
        return issueTreeElement;
    }

    _removeDebuggerTreeElement(debuggerTreeElement)
    {
        // If this is a BreakpointTreeElement being deleted because of a cause
        // outside of the TreeOutline then deselect if it is selected to avoid
        // TreeOutline selection changes causing unexpected ContentView changes.
        if (!debuggerTreeElement.__deletedViaDeleteKeyboardShortcut)
            debuggerTreeElement.deselect();

        let parentTreeElement = debuggerTreeElement.parent;
        parentTreeElement.removeChild(debuggerTreeElement);

        if (parentTreeElement.children.length || parentTreeElement === this._breakpointsTreeOutline)
            return;

        parentTreeElement.treeOutline.removeChild(parentTreeElement);
    }

    _addBreakpointsForSourceCode(sourceCode)
    {
        for (let breakpoint of WI.debuggerManager.breakpointsForSourceCode(sourceCode))
            this._addBreakpoint(breakpoint);
    }

    _addIssuesForSourceCode(sourceCode)
    {
        for (let issue of WI.consoleManager.issuesForSourceCode(sourceCode))
            this._addIssue(issue, sourceCode);
    }

    _addLocalResourceOverride(localResourceOverride)
    {
        console.assert(WI.NetworkManager.supportsLocalResourceOverrides());

        if (this._localResourceOverridesTreeOutline.findTreeElement(localResourceOverride))
            return;

        let parentTreeElement = this._localResourceOverridesTreeOutline;
        let resourceTreeElement = new WI.LocalResourceOverrideTreeElement(localResourceOverride.localResource, localResourceOverride);
        let index = insertionIndexForObjectInListSortedByFunction(resourceTreeElement, parentTreeElement.children, this._boundCompareTreeElements);
        parentTreeElement.insertChild(resourceTreeElement, index);

        if (!this._localResourceOverridesContainer.parentNode)
            this.contentView.element.insertBefore(this._localResourceOverridesContainer, this._resourcesNavigationBar.element);
    }

    _removeLocalResourceOverride(localResourceOverride)
    {
        console.assert(WI.NetworkManager.supportsLocalResourceOverrides());

        let resourceTreeElement = this._localResourceOverridesTreeOutline.findTreeElement(localResourceOverride);
        if (!resourceTreeElement)
            return;

        let wasSelected = resourceTreeElement.selected;

        let parentTreeElement = this._localResourceOverridesTreeOutline;
        parentTreeElement.removeChild(resourceTreeElement);

        if (!parentTreeElement.children.length) {
            this._localResourceOverridesContainer.remove();

            if (wasSelected && WI.networkManager.mainFrame && WI.networkManager.mainFrame.mainResource)
                WI.showRepresentedObject(WI.networkManager.mainFrame.mainResource);
        }
    }

    _updateTemporarilyDisabledBreakpointsButtons()
    {
        let breakpointsDisabledTemporarily = WI.debuggerManager.breakpointsDisabledTemporarily;
        this._debuggerBreakpointsButtonItem.enabled = !breakpointsDisabledTemporarily;
        this._debuggerPauseResumeButtonItem.enabled = !breakpointsDisabledTemporarily;
    }

    _updateBreakpointsDisabledBanner()
    {
        if (!WI.debuggerManager.breakpointsEnabled && !this._timelineRecordingWarningElement && !this._auditTestWarningElement) {
            if (!this._breakpointsDisabledWarningElement) {
                let enableBreakpointsButton = document.createElement("button");
                enableBreakpointsButton.textContent = WI.UIString("Enable Breakpoints");
                enableBreakpointsButton.addEventListener("click", () => {
                    WI.debuggerToggleBreakpoints();
                });

                this._breakpointsDisabledWarningElement = document.createElement("div");
                this._breakpointsDisabledWarningElement.classList.add("warning-banner");
                this._breakpointsDisabledWarningElement.append(WI.UIString("Breakpoints disabled"), document.createElement("br"), enableBreakpointsButton);
            }

            this.contentView.element.insertBefore(this._breakpointsDisabledWarningElement, this.contentView.element.firstChild);
        } else if (this._breakpointsDisabledWarningElement) {
            this._breakpointsDisabledWarningElement.remove();
            this._breakpointsDisabledWarningElement = null;
        }
    }

    _updatePauseReason()
    {
        this._pauseReasonTreeOutline = null;

        this._updatePauseReasonGotoArrow();

        let target = WI.debuggerManager.activeCallFrame.target;
        let targetData = WI.debuggerManager.dataForTarget(target);
        return this._updatePauseReasonSection(target, targetData.pauseReason, targetData.pauseData);
    }

    _updatePauseReasonGotoArrow()
    {
        this._pauseReasonLinkContainerElement.removeChildren();

        let activeCallFrame = WI.debuggerManager.activeCallFrame;
        if (!activeCallFrame)
            return;

        let sourceCodeLocation = activeCallFrame.sourceCodeLocation;
        if (!sourceCodeLocation)
            return;

        const options = {
            useGoToArrowButton: true,
        };
        let linkElement = WI.createSourceCodeLocationLink(sourceCodeLocation, options);
        this._pauseReasonLinkContainerElement.appendChild(linkElement);
    }

    _updatePauseReasonSection(target, pauseReason, pauseData)
    {
        switch (pauseReason) {
        case WI.DebuggerManager.PauseReason.AnimationFrame: {
            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(WI.domDebuggerManager.allAnimationFramesBreakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("requestAnimationFrame Fired"),
            });
            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);

            let eventBreakpointRow = new WI.DetailsSectionRow;
            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            this._pauseReasonGroup.rows = [eventBreakpointRow];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Assertion:
            // FIXME: We should include the assertion condition string.
            console.assert(pauseData, "Expected data with an assertion, but found none.");
            if (pauseData && pauseData.message)
                this._pauseReasonTextRow.text = WI.UIString("Assertion with message: %s").format(pauseData.message);
            else
                this._pauseReasonTextRow.text = WI.UIString("Assertion Failed");
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;

        case WI.DebuggerManager.PauseReason.BlackboxedScript: {
            console.assert(pauseData);
            if (pauseData)
                this._updatePauseReasonSection(target, WI.DebuggerManager.pauseReasonFromPayload(pauseData.originalReason), pauseData.originalData);

            // Don't use `_pauseReasonTextRow` as it may have already been set.
            let blackboxReasonTextRow = new WI.DetailsSectionTextRow(WI.UIString("Deferred pause from blackboxed script"));
            blackboxReasonTextRow.__blackboxReason = true;

            let existingRows = this._pauseReasonGroup.rows.filter((row) => !row.__blackboxReason);
            this._pauseReasonGroup.rows = [blackboxReasonTextRow, ...existingRows];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Breakpoint: {
            console.assert(pauseData, "Expected breakpoint identifier, but found none.");
            if (!pauseData || !pauseData.breakpointId)
                break;

            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
            this._pauseReasonTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);

            let breakpoint = WI.debuggerManager.breakpointForIdentifier(pauseData.breakpointId);
            let breakpointTreeElement = new WI.BreakpointTreeElement(breakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("Triggered Breakpoint"),
            });
            let breakpointDetailsSection = new WI.DetailsSectionRow;
            this._pauseReasonTreeOutline.appendChild(breakpointTreeElement);
            breakpointDetailsSection.element.appendChild(this._pauseReasonTreeOutline.element);

            this._pauseReasonGroup.rows = [breakpointDetailsSection];
            return true;
        }

        case WI.DebuggerManager.PauseReason.CSPViolation:
            console.assert(pauseData, "Expected data with a CSP Violation, but found none.");
            if (!pauseData)
                break;

            // COMPATIBILITY (iOS 8): 'directive' was 'directiveText'.
            this._pauseReasonTextRow.text = WI.UIString("Content Security Policy violation of directive: %s").format(pauseData.directive || pauseData.directiveText);
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;

        case WI.DebuggerManager.PauseReason.DebuggerStatement:
            this._pauseReasonTextRow.text = WI.UIString("Debugger Statement");
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;

        case WI.DebuggerManager.PauseReason.DOM: {
            console.assert(WI.domDebuggerManager.supported);
            console.assert(pauseData, "Expected DOM breakpoint data, but found none.");
            if (!pauseData || !pauseData.nodeId)
                break;

            let domNode = WI.domManager.nodeForId(pauseData.nodeId);
            let domBreakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode);
            let domBreakpoint;
            for (let breakpoint of domBreakpoints) {
                if (breakpoint.type === pauseData.type) {
                    domBreakpoint = breakpoint;
                    break;
                }
            }

            console.assert(domBreakpoint, "Missing DOM breakpoint of type for node", pauseData.type, domNode);
            if (!domBreakpoint)
                break;

            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let type = WI.DOMBreakpointTreeElement.displayNameForType(domBreakpoint.type);
            let domBreakpointTreeElement = new WI.DOMBreakpointTreeElement(domBreakpoint, {
                className: "breakpoint-paused-icon",
                title: type,
            });
            let domBreakpointRow = new WI.DetailsSectionRow;
            this._pauseReasonTreeOutline.appendChild(domBreakpointTreeElement);
            domBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(domNode));
            this._pauseReasonGroup.rows = [domBreakpointRow, ownerElementRow];

            if (domBreakpoint.type !== WI.DOMBreakpoint.Type.SubtreeModified)
                return true;

            console.assert(pauseData.targetNode);

            let remoteObject = WI.RemoteObject.fromPayload(pauseData.targetNode, target);
            remoteObject.pushNodeToFrontend((nodeId) => {
                if (!nodeId)
                    return;

                let node = WI.domManager.nodeForId(nodeId);
                console.assert(node, "Missing node for id.", nodeId);
                if (!node)
                    return;

                let fragment = document.createDocumentFragment();
                let description = pauseData.insertion ? WI.UIString("Child added to ") : WI.UIString("Removed descendant ");
                fragment.append(description, WI.linkifyNodeReference(node));

                let targetDescriptionRow = new WI.DetailsSectionSimpleRow(WI.UIString("Details"), fragment);
                targetDescriptionRow.element.classList.add("target-description");

                this._pauseReasonGroup.rows = this._pauseReasonGroup.rows.concat(targetDescriptionRow);
            });

            return true;
        }

        case WI.DebuggerManager.PauseReason.Listener:
        case WI.DebuggerManager.PauseReason.EventListener: {
            console.assert(pauseData, "Expected data with an event listener, but found none.");
            if (!pauseData)
                break;

            let eventBreakpoint = null;
            if (pauseData.eventListenerId)
                eventBreakpoint = WI.domManager.breakpointForEventListenerId(pauseData.eventListenerId);
            if (!eventBreakpoint)
                eventBreakpoint = WI.domDebuggerManager.listenerBreakpointForEventName(pauseData.eventName);

            console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
            if (!eventBreakpoint)
                break;

            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("\u201C%s\u201D Event Fired").format(pauseData.eventName),
            });
            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);

            let eventBreakpointRow = new WI.DetailsSectionRow;
            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            let rows = [eventBreakpointRow];

            let eventListener = eventBreakpoint.eventListener;
            if (eventListener) {
                console.assert(eventListener.eventListenerId === pauseData.eventListenerId);

                let value = null;
                if (eventListener.onWindow)
                    value = WI.unlocalizedString("window");
                else if (eventListener.node)
                    value = WI.linkifyNodeReference(eventListener.node);
                if (value)
                    rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), value));
            }

            this._pauseReasonGroup.rows = rows;
            return true;
        }

        case WI.DebuggerManager.PauseReason.Exception: {
            console.assert(pauseData, "Expected data with an exception, but found none.");
            if (!pauseData)
                break;

            // FIXME: We should improve the appearance of thrown objects. This works well for exception strings.
            let data = WI.RemoteObject.fromPayload(pauseData, target);
            this._pauseReasonTextRow.text = WI.UIString("Exception with thrown value: %s").format(data.description);
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Interval: {
            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(WI.domDebuggerManager.allIntervalsBreakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("setInterval Fired"),
            });
            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);

            let eventBreakpointRow = new WI.DetailsSectionRow;
            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            this._pauseReasonGroup.rows = [eventBreakpointRow];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Microtask:
            this._pauseReasonTextRow.text = WI.UIString("Microtask Fired");
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;

        case WI.DebuggerManager.PauseReason.PauseOnNextStatement:
            this._pauseReasonTextRow.text = WI.UIString("Immediate Pause Requested");
            this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            return true;

        case WI.DebuggerManager.PauseReason.Timer: {
            console.assert(pauseData, "Expected data with a timer, but found none.");
            if (!pauseData)
                break;

            let eventBreakpoint = null;
            switch (pauseData.eventName) {
            case "setTimeout":
                eventBreakpoint = WI.domDebuggerManager.allTimeoutsBreakpoint;
                break;

            case "setInterval":
                eventBreakpoint = WI.domDebuggerManager.allIntervalsBreakpoint;
                break;
            }
            console.assert(eventBreakpoint, "Expected Timer breakpoint for event name.", pauseData.eventName);
            if (!eventBreakpoint)
                break;

            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("%s Fired").format(pauseData.eventName),
            });
            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);

            let eventBreakpointRow = new WI.DetailsSectionRow;
            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            this._pauseReasonGroup.rows = [eventBreakpointRow];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Timeout: {
            this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

            let eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(WI.domDebuggerManager.allTimeoutsBreakpoint, {
                className: "breakpoint-paused-icon",
                title: WI.UIString("setTimeout Fired"),
            });
            this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);

            let eventBreakpointRow = new WI.DetailsSectionRow;
            eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

            this._pauseReasonGroup.rows = [eventBreakpointRow];
            return true;
        }

        case WI.DebuggerManager.PauseReason.Fetch:
        case WI.DebuggerManager.PauseReason.XHR: {
            console.assert(WI.domDebuggerManager.supported);
            console.assert(pauseData, "Expected URL breakpoint data, but found none.");
            if (!pauseData)
                break;

            if (pauseData.breakpointURL) {
                let urlBreakpoint = WI.domDebuggerManager.urlBreakpointForURL(pauseData.breakpointURL);
                console.assert(urlBreakpoint, "Expected URL breakpoint for URL.", pauseData.breakpointURL);

                this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});

                let urlBreakpointTreeElement = new WI.URLBreakpointTreeElement(urlBreakpoint, {
                    className: "breakpoint-paused-icon",
                    title: WI.UIString("Triggered URL Breakpoint"),
                });
                let urlBreakpointRow = new WI.DetailsSectionRow;
                this._pauseReasonTreeOutline.appendChild(urlBreakpointTreeElement);
                urlBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);

                this._pauseReasonTextRow.text = pauseData.url;
                this._pauseReasonGroup.rows = [urlBreakpointRow, this._pauseReasonTextRow];
            } else {
                console.assert(pauseData.breakpointURL === "", "Should be the All Requests breakpoint which has an empty URL");
                this._pauseReasonTextRow.text = WI.UIString("Requesting: %s").format(pauseData.url);
                this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
            }
            this._pauseReasonTextRow.element.title = pauseData.url;
            return true;
        }

        case WI.DebuggerManager.PauseReason.Other:
            console.error("Paused for unknown reason. We should always have a reason.");
            break;
        }

        return false;
    }

    _handleResourceGroupingModeScopeBarSelectionChanged(event)
    {
        console.assert(this._resourceGroupingModeScopeBar.selectedItems.length === 1);
        let selectedScopeBarItem = this._resourceGroupingModeScopeBar.selectedItems[0];
        WI.settings.resourceGroupingMode.value = selectedScopeBarItem[SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol] || WI.Resource.GroupingMode.Type;
    }

    _handleResourceTypeScopeBarSelectionChanged(event)
    {
        this.updateFilter();
    }

    _handleTreeSelectionDidChange(event)
    {
        if (!this.selected)
            return;

        let treeElement = event.target.selectedTreeElement;
        if (!treeElement)
            return;

        if (treeElement instanceof WI.DOMNodeTreeElement
            || treeElement instanceof WI.DOMBreakpointTreeElement
            || treeElement instanceof WI.EventBreakpointTreeElement
            || treeElement instanceof WI.URLBreakpointTreeElement)
            return;

        if (treeElement.representedObject === SourcesNavigationSidebarPanel.__windowEventTargetRepresentedObject)
            return;

        if (treeElement instanceof WI.LocalResourceOverrideTreeElement) {
            WI.showRepresentedObject(treeElement.representedObject.localResource);
            return;
        }

        // Silently select the corresponding tree element in the resources tree outline to update
        // the hierarchical path components to show the right ancestor(s).
        let selectTreeElementInResourcesTreeOutline = (sourceCode) => {
            let resourceTreeElement = this._resourcesTreeOutline.findTreeElement(sourceCode);
            if (!resourceTreeElement)
                return;

            const omitFocus = true;
            const selectedByUser = false;
            const suppressNotification = true;
            resourceTreeElement.select(omitFocus, selectedByUser, suppressNotification);
        };

        if (treeElement instanceof WI.FolderTreeElement
            || treeElement instanceof WI.OriginTreeElement
            || treeElement instanceof WI.ResourceTreeElement
            || treeElement instanceof WI.ScriptTreeElement
            || treeElement instanceof WI.CSSStyleSheetTreeElement) {
            let representedObject = treeElement.representedObject;

            if (representedObject instanceof WI.Script && representedObject.resource)
                representedObject = representedObject.resource;

            if (treeElement.treeOutline !== this._resourcesTreeOutline)
                selectTreeElementInResourcesTreeOutline(representedObject);

            if (representedObject instanceof WI.Collection || representedObject instanceof WI.SourceCode || representedObject instanceof WI.Frame)
                WI.showRepresentedObject(representedObject);
            return;
        }

        if (treeElement instanceof WI.CallFrameTreeElement) {
            let callFrame = treeElement.callFrame;
            if (callFrame.id)
                WI.debuggerManager.activeCallFrame = callFrame;
            if (callFrame.sourceCodeLocation)
                WI.showSourceCodeLocation(callFrame.sourceCodeLocation);
            return;
        }

        if (treeElement instanceof WI.IssueTreeElement) {
            WI.showSourceCodeLocation(treeElement.issueMessage.sourceCodeLocation);
            return;
        }

        if (treeElement instanceof WI.BreakpointTreeElement) {
            let breakpoint = treeElement.breakpoint;
            if (WI.debuggerManager.isBreakpointSpecial(breakpoint))
                return;

            let sourceCode = breakpoint.sourceCodeLocation.displaySourceCode;
            if (sourceCode instanceof WI.Script && sourceCode.resource)
                sourceCode = sourceCode.resource;
            selectTreeElementInResourcesTreeOutline(sourceCode);

            WI.showSourceCodeLocation(breakpoint.sourceCodeLocation);
            return;
        }

        console.error("Unknown tree element", treeElement);
    }

    _handleBreakpointElementAddedOrRemoved(event)
    {
        let treeElement = event.data.element;

        let setting = null;
        switch (treeElement.representedObject) {
        case WI.debuggerManager.assertionFailuresBreakpoint:
            setting = WI.settings.showAssertionFailuresBreakpoint;
            break;

        case WI.debuggerManager.allMicrotasksBreakpoint:
            setting = WI.settings.showAllMicrotasksBreakpoint;
            break;

        case WI.domDebuggerManager.allAnimationFramesBreakpoint:
            setting = WI.settings.showAllAnimationFramesBreakpoint;
            break;

        case WI.domDebuggerManager.allIntervalsBreakpoint:
            setting = WI.settings.showAllIntervalsBreakpoint;
            break;

        case WI.domDebuggerManager.allListenersBreakpoint:
            setting = WI.settings.showAllListenersBreakpoint;
            break;

        case WI.domDebuggerManager.allRequestsBreakpoint:
            setting = WI.settings.showAllRequestsBreakpoint;
            break;

        case WI.domDebuggerManager.allTimeoutsBreakpoint:
            setting = WI.settings.showAllTimeoutsBreakpoint;
            break;
        }

        if (setting)
            setting.value = !!treeElement.parent;

        if (event.type === WI.TreeOutline.Event.ElementRemoved) {
            let selectedTreeElement = this._breakpointsTreeOutline.selectedTreeElement;
            if (selectedTreeElement) {
                if (selectedTreeElement.representedObject === WI.debuggerManager.assertionFailuresBreakpoint || !WI.debuggerManager.isBreakpointRemovable(selectedTreeElement.representedObject)) {
                    const skipUnrevealed = true;
                    const dontPopulate = true;
                    let treeElementToSelect = selectedTreeElement.traverseNextTreeElement(skipUnrevealed, dontPopulate);
                    if (treeElementToSelect) {
                        const omitFocus = true;
                        const selectedByUser = true;
                        treeElementToSelect.select(omitFocus, selectedByUser);
                    }
                }
            }
        }
    }

    _populateCreateBreakpointContextMenu(contextMenu)
    {
        // COMPATIBILITY (iOS 10): DebuggerAgent.setPauseOnAssertions did not exist yet.
        if (InspectorBackend.domains.Debugger.setPauseOnAssertions) {
            let assertionFailuresBreakpointShown = WI.settings.showAssertionFailuresBreakpoint.value;

            contextMenu.appendCheckboxItem(WI.repeatedUIString.assertionFailures(), () => {
                if (assertionFailuresBreakpointShown)
                    WI.debuggerManager.removeBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
                else {
                    WI.debuggerManager.assertionFailuresBreakpoint.disabled = false;
                    WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
                }
            }, assertionFailuresBreakpointShown);
        }

        contextMenu.appendSeparator();

        // COMPATIBILITY (iOS 13): DebuggerAgent.setPauseOnMicrotasks did not exist yet.
        if (InspectorBackend.domains.Debugger.setPauseOnMicrotasks) {
            let allMicrotasksBreakpointShown = WI.settings.showAllMicrotasksBreakpoint.value;

            contextMenu.appendCheckboxItem(WI.UIString("All Microtasks"), () => {
                if (allMicrotasksBreakpointShown)
                    WI.debuggerManager.removeBreakpoint(WI.debuggerManager.allMicrotasksBreakpoint);
                else {
                    WI.debuggerManager.allMicrotasksBreakpoint.disabled = false;
                    WI.debuggerManager.addBreakpoint(WI.debuggerManager.allMicrotasksBreakpoint);
                }
            }, allMicrotasksBreakpointShown);
        }

        if (WI.DOMDebuggerManager.supportsEventBreakpoints() || WI.DOMDebuggerManager.supportsEventListenerBreakpoints()) {
            function addToggleForSpecialEventBreakpoint(breakpoint, label, checked) {
                contextMenu.appendCheckboxItem(label, () => {
                    if (checked)
                        WI.domDebuggerManager.removeEventBreakpoint(breakpoint);
                    else {
                        breakpoint.disabled = false;
                        WI.domDebuggerManager.addEventBreakpoint(breakpoint);
                    }
                }, checked);
            }

            addToggleForSpecialEventBreakpoint(WI.domDebuggerManager.allAnimationFramesBreakpoint, WI.UIString("All Animation Frames"), WI.settings.showAllAnimationFramesBreakpoint.value);
            addToggleForSpecialEventBreakpoint(WI.domDebuggerManager.allTimeoutsBreakpoint, WI.UIString("All Timeouts"), WI.settings.showAllTimeoutsBreakpoint.value);
            addToggleForSpecialEventBreakpoint(WI.domDebuggerManager.allIntervalsBreakpoint, WI.UIString("All Intervals"), WI.settings.showAllIntervalsBreakpoint.value);

            contextMenu.appendSeparator();

            if (WI.DOMDebuggerManager.supportsAllListenersBreakpoint())
                addToggleForSpecialEventBreakpoint(WI.domDebuggerManager.allListenersBreakpoint, WI.UIString("All Events"), WI.settings.showAllListenersBreakpoint.value);

            contextMenu.appendItem(WI.UIString("Event Breakpoint\u2026"), () => {
                let popover = new WI.EventBreakpointPopover(this);
                popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
            });
        }

        if (WI.DOMDebuggerManager.supportsURLBreakpoints() || WI.DOMDebuggerManager.supportsXHRBreakpoints()) {
            contextMenu.appendSeparator();

            let allRequestsBreakpointShown = WI.settings.showAllRequestsBreakpoint.value;
            contextMenu.appendCheckboxItem(WI.repeatedUIString.allRequests(), () => {
                if (allRequestsBreakpointShown)
                    WI.domDebuggerManager.removeURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
                else {
                    WI.domDebuggerManager.allRequestsBreakpoint.disabled = false;
                    WI.domDebuggerManager.addURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
                }
            }, allRequestsBreakpointShown);

            contextMenu.appendItem(WI.DOMDebuggerManager.supportsURLBreakpoints() ? WI.UIString("URL Breakpoint\u2026") : WI.UIString("XHR Breakpoint\u2026"), () => {
                let popover = new WI.URLBreakpointPopover(this);
                popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
            });
        }

        if (WI.NetworkManager.supportsLocalResourceOverrides()) {
            contextMenu.appendSeparator();
            contextMenu.appendItem(WI.UIString("Local Override\u2026"), () => {
                let popover = new WI.LocalResourceOverridePopover(this);
                popover.show(null, this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
            });
        }
    }

    _populateCreateResourceContextMenu(contextMenu)
    {
        if (InspectorBackend.domains.CSS) {
            let addInspectorStyleSheetItem = (menu, frame) => {
                menu.appendItem(WI.UIString("Inspector Style Sheet"), () => {
                    if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
                        // Force the parent to populate.
                        let parentFrameTreeElement = this._resourcesTreeOutline.findTreeElement(frame.mainResource);
                        parentFrameTreeElement.reveal();
                        parentFrameTreeElement.expand();
                    }

                    WI.cssManager.preferredInspectorStyleSheetForFrame(frame, (styleSheet) => {
                        WI.showRepresentedObject(styleSheet);
                    });
                });
            };

            addInspectorStyleSheetItem(contextMenu, WI.networkManager.mainFrame);

            let frames = WI.networkManager.frames;
            if (frames.length > 2) {
                let framesSubMenu = contextMenu.appendSubMenuItem(WI.UIString("Frames"));

                for (let frame of frames) {
                    if (frame === WI.networkManager.mainFrame || frame.mainResource.type !== WI.Resource.Type.Document)
                        continue;

                    let frameSubMenuItem = framesSubMenu.appendSubMenuItem(frame.name ? WI.UIString("%s (%s)").format(frame.name, frame.mainResource.displayName) : frame.mainResource.displayName);

                    addInspectorStyleSheetItem(frameSubMenuItem, frame);
                }
            }
        }
    }

    _handleResourceGroupingModeChanged(event)
    {
        this._workerTargetTreeElementMap.clear();
        this._mainFrameTreeElement = null;
        this._extensionScriptsFolderTreeElement = null;
        this._extraScriptsFolderTreeElement = null;
        this._anonymousScriptsFolderTreeElement = null;

        this._originTreeElementMap.clear();

        let resourceGroupingModeScopeBarItem = this._resourceGroupingModeScopeBarItems[WI.settings.resourceGroupingMode.value];
        console.assert(resourceGroupingModeScopeBarItem);
        if (resourceGroupingModeScopeBarItem)
            resourceGroupingModeScopeBarItem.selected = true;

        this._resourcesTreeOutline.removeChildren();

        let mainFrame = WI.networkManager.mainFrame;
        if (mainFrame) {
            this._updateMainFrameTreeElement(mainFrame);
            this._addResourcesRecursivelyForFrame(mainFrame);

            for (let frame of WI.networkManager.frames) {
                if (frame !== mainFrame)
                    this._addResourcesRecursivelyForFrame(frame);
            }
        }

        for (let script of WI.debuggerManager.knownNonResourceScripts) {
            this._addScript(script);

            if (script.sourceMaps.length && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
                this._resourcesTreeOutline.disclosureButtons = true;
        }
    }

    _handleFrameMainResourceDidChange(event)
    {
        let frame = event.target;
        if (frame.isMainFrame()) {
            this._updateMainFrameTreeElement(frame);
            this._addResourcesRecursivelyForFrame(frame);

            for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
                this._removeBreakpoint(domBreakpoint);
        }

        if (!event.data.oldMainResource) {
            let resource = event.target.mainResource;
            this._addBreakpointsForSourceCode(resource);
            this._addIssuesForSourceCode(resource);
        }
    }

    _handleResourceAdded(event)
    {
        this._addResource(event.data.resource);
    }

    _handleFrameWasAdded(event)
    {
        let {frame} = event.data;

        if (frame.isMainFrame())
            this._updateMainFrameTreeElement(frame);

        this._addResourcesRecursivelyForFrame(frame);
    }

    _handleLocalResourceOverrideAdded(event)
    {
        this._addLocalResourceOverride(event.data.localResourceOverride);
    }

    _handleLocalResourceOverrideRemoved(event)
    {
        this._removeLocalResourceOverride(event.data.localResourceOverride);
    }

    _handleDebuggerBreakpointAdded(event)
    {
        this._addBreakpoint(event.data.breakpoint);
    }

    _handleDebuggerBreakpointRemoved(event)
    {
        this._removeBreakpoint(event.data.breakpoint);
    }

    _handleDebuggerBreakpointsEnabledDidChange(event)
    {
        this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;

        this._updateBreakpointsDisabledBanner();
    }

    _handleDebuggerScriptAdded(event)
    {
        this._addScript(event.data.script);
    }

    _handleDebuggerScriptRemoved(event)
    {
        let script = event.data.script;
        let scriptTreeElement = this._resourcesTreeOutline.findTreeElement(script);
        if (!scriptTreeElement)
            return;

        let parentTreeElement = scriptTreeElement.parent;
        parentTreeElement.removeChild(scriptTreeElement);

        if (parentTreeElement instanceof WI.FolderTreeElement || parentTreeElement instanceof WI.OriginTreeElement) {
            parentTreeElement.representedObject.remove(script);

            if (!parentTreeElement.children.length)
                parentTreeElement.parent.removeChild(parentTreeElement);
        }
    }

    _handleDebuggerScriptsCleared(event)
    {
        const suppressOnDeselect = true;
        const suppressSelectSibling = true;

        for (let i = this._breakpointsTreeOutline.children.length - 1; i >= 0; --i) {
            let treeElement = this._breakpointsTreeOutline.children[i];
            if (!(treeElement instanceof WI.ScriptTreeElement))
                continue;

            this._breakpointsTreeOutline.removeChild(treeElement, suppressOnDeselect, suppressSelectSibling);
        }

        if (this._extensionScriptsFolderTreeElement) {
            if (this._extensionScriptsFolderTreeElement.parent)
                this._extensionScriptsFolderTreeElement.parent.removeChild(this._extensionScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);

            this._extensionScriptsFolderTreeElement.representedObject.clear();
            this._extensionScriptsFolderTreeElement = null;
        }

        if (this._extraScriptsFolderTreeElement) {
            if (this._extraScriptsFolderTreeElement.parent)
                this._extraScriptsFolderTreeElement.parent.removeChild(this._extraScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);

            this._extraScriptsFolderTreeElement.representedObject.clear();
            this._extraScriptsFolderTreeElement = null;
        }

        if (this._anonymousScriptsFolderTreeElement) {
            if (this._anonymousScriptsFolderTreeElement.parent)
                this._anonymousScriptsFolderTreeElement.parent.removeChild(this._anonymousScriptsFolderTreeElement, suppressOnDeselect, suppressSelectSibling);

            this._anonymousScriptsFolderTreeElement.representedObject.clear();
            this._anonymousScriptsFolderTreeElement = null;
        }

        if (this._workerTargetTreeElementMap.size) {
            for (let treeElement of this._workerTargetTreeElementMap.values())
                treeElement.parent.removeChild(treeElement, suppressOnDeselect, suppressSelectSibling);
            this._workerTargetTreeElementMap.clear();
        }

        this._addResourcesRecursivelyForFrame(WI.networkManager.mainFrame);
    }

    _handleDebuggerPaused(event)
    {
        this.contentView.element.insertBefore(this._callStackContainer, this.contentView.element.firstChild);

        if (this._updatePauseReason())
            this.contentView.element.insertBefore(this._pauseReasonContainer, this.contentView.element.firstChild);

        this._debuggerPauseResumeButtonItem.enabled = true;
        this._debuggerPauseResumeButtonItem.toggled = true;
        this._debuggerStepOverButtonItem.enabled = true;
        this._debuggerStepIntoButtonItem.enabled = true;
        this._debuggerStepOutButtonItem.enabled = true;

        this.element.classList.add("paused");
    }

    _handleDebuggerResumed(event)
    {
        this._callStackContainer.remove();

        this._pauseReasonContainer.remove();

        this._debuggerPauseResumeButtonItem.enabled = true;
        this._debuggerPauseResumeButtonItem.toggled = false;
        this._debuggerStepOverButtonItem.enabled = false;
        this._debuggerStepIntoButtonItem.enabled = false;
        this._debuggerStepOutButtonItem.enabled = false;

        this.element.classList.remove("paused");
    }

    _handleDebuggerCallFramesDidChange(event)
    {
        let {target} = event.data;
        let treeElement = this._findCallStackTargetTreeElement(target);
        console.assert(treeElement);
        if (treeElement)
            treeElement.refresh();

        let activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WI.debuggerManager.activeCallFrame);
        if (activeCallFrameTreeElement)
            activeCallFrameTreeElement.reveal();
    }

    _handleDebuggerActiveCallFrameDidChange(event)
    {
        if (this._activeCallFrameTreeElement) {
            this._activeCallFrameTreeElement.isActiveCallFrame = false;
            this._activeCallFrameTreeElement = null;
        }

        if (!WI.debuggerManager.activeCallFrame)
            return;

        this._activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WI.debuggerManager.activeCallFrame);
        if (this._activeCallFrameTreeElement)
            this._activeCallFrameTreeElement.isActiveCallFrame = true;
    }

    _handleDebuggerWaitingToPause(event)
    {
        this._debuggerPauseResumeButtonItem.enabled = false;
    }

    _handleDebuggerObjectDisplayLocationDidChange(event)
    {
        let debuggerObject = event.target;

        if (event.data.oldDisplaySourceCode === debuggerObject.sourceCodeLocation.displaySourceCode)
            return;

        // A known debugger object (breakpoint, issueMessage, etc.) moved between resources. Remove
        // the old tree element and create a new tree element with the updated file.

        let wasSelected = false;
        let oldDebuggerTreeElement = null;
        let newDebuggerTreeElement = null;
        if (debuggerObject instanceof WI.Breakpoint) {
            oldDebuggerTreeElement = this._breakpointsTreeOutline.findTreeElement(debuggerObject);
            if (oldDebuggerTreeElement)
                wasSelected = oldDebuggerTreeElement.selected;

            newDebuggerTreeElement = this._addBreakpoint(debuggerObject);
        } else if (debuggerObject instanceof WI.IssueMessage) {
            oldDebuggerTreeElement = this._resourcesTreeOutline.findTreeElement(debuggerObject);
            if (oldDebuggerTreeElement)
                wasSelected = oldDebuggerTreeElement.selected;

            newDebuggerTreeElement = this._addIssue(debuggerObject);
        }

        if (!newDebuggerTreeElement)
            return;

        if (oldDebuggerTreeElement)
            this._removeDebuggerTreeElement(oldDebuggerTreeElement);

        if (wasSelected)
            newDebuggerTreeElement.revealAndSelect(true, false, true);
    }

    _handleDOMBreakpointDOMNodeChanged(event)
    {
        let breakpoint = event.target;
        if (breakpoint.domNodeIdentifier)
            this._addBreakpoint(breakpoint);
        else
            this._removeBreakpoint(breakpoint);
    }

    _handleConsoleIssueAdded(event)
    {
        let {issue} = event.data;

        // We only want to show issues originating from JavaScript source code.
        if (!issue.sourceCodeLocation || !issue.sourceCodeLocation.sourceCode || (issue.source !== "javascript" && issue.source !== "console-api"))
            return;

        this._addIssue(issue);
    }

    _handleConsoleCleared(event)
    {
        let issueTreeElements = [];
        let currentTreeElement = this._resourcesTreeOutline.children[0];
        while (currentTreeElement && !currentTreeElement.root) {
            if (currentTreeElement instanceof WI.IssueTreeElement)
                issueTreeElements.push(currentTreeElement);

            const skipUnrevealed = false;
            const stayWithin = null;
            const dontPopulate = true;
            currentTreeElement = currentTreeElement.traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate);
        }

        issueTreeElements.forEach((treeElement) => treeElement.parent.removeChild(treeElement));
    }

    _handleTimelineCapturingStateChanged(event)
    {
        this._updateTemporarilyDisabledBreakpointsButtons();

        switch (WI.timelineManager.capturingState) {
        case WI.TimelineManager.CapturingState.Starting:
            if (!this._timelineRecordingWarningElement) {
                let stopRecordingButton = document.createElement("button");
                stopRecordingButton.textContent = WI.UIString("Stop recording");
                stopRecordingButton.addEventListener("click", () => {
                    WI.timelineManager.stopCapturing();
                });

                this._timelineRecordingWarningElement = document.createElement("div");
                this._timelineRecordingWarningElement.classList.add("warning-banner");
                this._timelineRecordingWarningElement.append(WI.UIString("Debugger disabled during Timeline recording"), document.createElement("br"), stopRecordingButton);
            }

            this.contentView.element.insertBefore(this._timelineRecordingWarningElement, this.contentView.element.firstChild);
            break;

        case WI.TimelineManager.CapturingState.Inactive:
            if (this._timelineRecordingWarningElement) {
                this._timelineRecordingWarningElement.remove();
                this._timelineRecordingWarningElement = null;
            }
            break;
        }

        this._updateBreakpointsDisabledBanner();
    }

    _handleAuditManagerTestScheduled(event)
    {
        this._updateTemporarilyDisabledBreakpointsButtons();

        if (!this._auditTestWarningElement) {
            let stopAuditButton = document.createElement("button");
            stopAuditButton.textContent = WI.UIString("Stop Audit");
            stopAuditButton.addEventListener("click", (event) => {
                WI.auditManager.stop();
            });

            this._auditTestWarningElement = document.createElement("div");
            this._auditTestWarningElement.classList.add("warning-banner");
            this._auditTestWarningElement.append(WI.UIString("Debugger disabled during Audit"), document.createElement("br"), stopAuditButton);
        }

        this.contentView.element.insertBefore(this._auditTestWarningElement, this.contentView.element.firstChild);

        this._updateBreakpointsDisabledBanner();
    }

    _handleAuditManagerTestCompleted(event)
    {
        this._updateTemporarilyDisabledBreakpointsButtons();

        if (this._auditTestWarningElement) {
            this._auditTestWarningElement.remove();
            this._auditTestWarningElement = null;
        }

        this._updateBreakpointsDisabledBanner();
    }

    _handleCSSStyleSheetAdded(event)
    {
        let styleSheet = event.data.styleSheet;
        if (!styleSheet.isInspectorStyleSheet())
            return;

        if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Type) {
            let frameTreeElement = this.treeElementForRepresentedObject(styleSheet.parentFrame);
            if (frameTreeElement) {
                frameTreeElement.addRepresentedObjectToNewChildQueue(styleSheet);
                return;
            }
        }

        this._addResource(styleSheet);
    }

    _handleTargetAdded(event)
    {
        this._addTarget(event.data.target);
    }

    _handleTargetRemoved(event)
    {
        let {target} = event.data;

        let workerTreeElement = this._workerTargetTreeElementMap.take(target);
        if (workerTreeElement)
            workerTreeElement.parent.removeChild(workerTreeElement);

        let callStackTreeElement = this._findCallStackTargetTreeElement(target);
        console.assert(callStackTreeElement);
        if (callStackTreeElement)
            this._callStackTreeOutline.removeChild(callStackTreeElement);

        this._updateCallStackTreeOutline();
    }

    _handleExtraDomainsActivated()
    {
        if (WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
            this._resourcesTreeOutline.disclosureButtons = true;
    }
};

WI.SourcesNavigationSidebarPanel.ResourceTypeSymbol = Symbol("resource-type");
WI.SourcesNavigationSidebarPanel.ResourceGroupingModeSymbol = Symbol("resource-grouping-mode");
