<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[243180] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/243180">243180</a></dd>
<dt>Author</dt> <dd>drousso@apple.com</dd>
<dt>Date</dt> <dd>2019-03-19 16:35:20 -0700 (Tue, 19 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Sources: provide option to group by path
https://bugs.webkit.org/show_bug.cgi?id=195203
<rdar://problem/27340680>

Reviewed by Timothy Hatcher.

Create top-level folders for each origin and nest all resources (in a folder chain) underneath.

* UserInterface/Views/SourcesNavigationSidebarPanel.js:
(WI.SourcesNavigationSidebarPanel):
(WI.SourcesNavigationSidebarPanel.prototype.closed):
(WI.SourcesNavigationSidebarPanel.prototype.treeElementForRepresentedObject.searchTreeOutline): Added.
(WI.SourcesNavigationSidebarPanel.prototype.treeElementForRepresentedObject):
(WI.SourcesNavigationSidebarPanel.prototype._compareTreeElements):
(WI.SourcesNavigationSidebarPanel.prototype._updateMainFrameTreeElement):
(WI.SourcesNavigationSidebarPanel.prototype._addResource):
(WI.SourcesNavigationSidebarPanel.prototype._addScript):
(WI.SourcesNavigationSidebarPanel.prototype._addWorkerTargetWithMainResource):
(WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeMouseDown.addOption): Added.
(WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeMouseDown): Added.
(WI.SourcesNavigationSidebarPanel.prototype._handleTreeSelectionDidChange):
(WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeChanged):
(WI.SourcesNavigationSidebarPanel.prototype._handleFrameMainResourceDidChange):
(WI.SourcesNavigationSidebarPanel.prototype._handleMainFrameDidChange):
* UserInterface/Views/SourcesNavigationSidebarPanel.css:
(.sidebar > .panel.navigation.sources > .content):
(.sidebar > .panel.navigation.sources > .content > .details-section.paused-reason.collapsed > .header > .options,):
(.sidebar > .panel.navigation.sources > .content > .details-section.breakpoints > .header > .options .create-breakpoint): Added.
(.sidebar > .panel.navigation.sources > .content > .resources): Added.
(.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread): Added.
(.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread > .item.thread): Added.
(.sidebar > .panel.navigation.sources > .content > .details-section.scripts:not(.collapsed)): Deleted.
(.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread): Deleted.
(.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread > .item.thread): Deleted.
Drive-by: fix "No Filter Results" message view to not overlap eachother.
Drive-by: try to be more smart about what tree we focus when selecting a represented object.

* UserInterface/Views/ResourceTreeElement.js:
(WI.ResourceTreeElement):
(WI.ResourceTreeElement.prototype.get mainTitleText):
(WI.ResourceTreeElement.prototype._updateTitles):
* UserInterface/Base/URLUtilities.js:
(WI.displayNameForURL):
Provide a way for the display name to use a directory "/" instead of the last path component.
This is needed in cases where the loaded resource is an implicit "index.*".

* UserInterface/Views/GeneralTreeElement.js:
(WI.GeneralTreeElement.prototype.createFoldersAsNeededForSubpath): Added.
* UserInterface/Views/SourceCodeTreeElement.js:
(WI.SourceCodeTreeElement.prototype.createFoldersAsNeededForSubpath): Deleted.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Models/Resource.js:

* UserInterface/Views/DetailsSection.css:
(.details-section > .header .go-to-arrow):
Drive-by: vertically center go-to-arrow.

* UserInterface/Protocol/InspectorFrontendAPI.js:
(InspectorFrontendAPI.contextMenuItemSelected):

* UserInterface/Base/Setting.js:
* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype.get filterNavigationItems):
(WI.NetworkTableContentView.prototype._populateNameCell):
(WI.NetworkTableContentView.prototype._generateSortComparator):
(WI.NetworkTableContentView.prototype._insertResourceAndReloadTable):
(WI.NetworkTableContentView.prototype._updateFilteredEntries):
(WI.NetworkTableContentView.prototype._handleGroupMediaRequestsByDOMNodeCheckedDidChange): Added.
(WI.NetworkTableContentView.prototype._handleGroupByDOMNodeCheckedDidChange): Deleted.
Rename the `groupByNode` setting to be more specific.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseSettingjs">trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseURLUtilitiesjs">trunk/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsResourcejs">trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolInspectorFrontendAPIjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendAPI.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDetailsSectioncss">trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSection.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsGeneralTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/GeneralTreeElement.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsResourceTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPanelcss">trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPaneljs">trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog    2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/ChangeLog       2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -1,5 +1,80 @@
</span><span class="cx"> 2019-03-19  Devin Rousso  <drousso@apple.com>
</span><span class="cx"> 
</span><ins>+        Web Inspector: Sources: provide option to group by path
+        https://bugs.webkit.org/show_bug.cgi?id=195203
+        <rdar://problem/27340680>
+
+        Reviewed by Timothy Hatcher.
+
+        Create top-level folders for each origin and nest all resources (in a folder chain) underneath.
+
+        * UserInterface/Views/SourcesNavigationSidebarPanel.js:
+        (WI.SourcesNavigationSidebarPanel):
+        (WI.SourcesNavigationSidebarPanel.prototype.closed):
+        (WI.SourcesNavigationSidebarPanel.prototype.treeElementForRepresentedObject.searchTreeOutline): Added.
+        (WI.SourcesNavigationSidebarPanel.prototype.treeElementForRepresentedObject):
+        (WI.SourcesNavigationSidebarPanel.prototype._compareTreeElements):
+        (WI.SourcesNavigationSidebarPanel.prototype._updateMainFrameTreeElement):
+        (WI.SourcesNavigationSidebarPanel.prototype._addResource):
+        (WI.SourcesNavigationSidebarPanel.prototype._addScript):
+        (WI.SourcesNavigationSidebarPanel.prototype._addWorkerTargetWithMainResource):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeMouseDown.addOption): Added.
+        (WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeMouseDown): Added.
+        (WI.SourcesNavigationSidebarPanel.prototype._handleTreeSelectionDidChange):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleResourceGroupingModeChanged):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleFrameMainResourceDidChange):
+        (WI.SourcesNavigationSidebarPanel.prototype._handleMainFrameDidChange):
+        * UserInterface/Views/SourcesNavigationSidebarPanel.css:
+        (.sidebar > .panel.navigation.sources > .content):
+        (.sidebar > .panel.navigation.sources > .content > .details-section.paused-reason.collapsed > .header > .options,):
+        (.sidebar > .panel.navigation.sources > .content > .details-section.breakpoints > .header > .options .create-breakpoint): Added.
+        (.sidebar > .panel.navigation.sources > .content > .resources): Added.
+        (.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread): Added.
+        (.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread > .item.thread): Added.
+        (.sidebar > .panel.navigation.sources > .content > .details-section.scripts:not(.collapsed)): Deleted.
+        (.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread): Deleted.
+        (.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread > .item.thread): Deleted.
+        Drive-by: fix "No Filter Results" message view to not overlap eachother.
+        Drive-by: try to be more smart about what tree we focus when selecting a represented object.
+
+        * UserInterface/Views/ResourceTreeElement.js:
+        (WI.ResourceTreeElement):
+        (WI.ResourceTreeElement.prototype.get mainTitleText):
+        (WI.ResourceTreeElement.prototype._updateTitles):
+        * UserInterface/Base/URLUtilities.js:
+        (WI.displayNameForURL):
+        Provide a way for the display name to use a directory "/" instead of the last path component.
+        This is needed in cases where the loaded resource is an implicit "index.*".
+
+        * UserInterface/Views/GeneralTreeElement.js:
+        (WI.GeneralTreeElement.prototype.createFoldersAsNeededForSubpath): Added.
+        * UserInterface/Views/SourceCodeTreeElement.js:
+        (WI.SourceCodeTreeElement.prototype.createFoldersAsNeededForSubpath): Deleted.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Models/Resource.js:
+
+        * UserInterface/Views/DetailsSection.css:
+        (.details-section > .header .go-to-arrow):
+        Drive-by: vertically center go-to-arrow.
+
+        * UserInterface/Protocol/InspectorFrontendAPI.js:
+        (InspectorFrontendAPI.contextMenuItemSelected):
+
+        * UserInterface/Base/Setting.js:
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView):
+        (WI.NetworkTableContentView.prototype.get filterNavigationItems):
+        (WI.NetworkTableContentView.prototype._populateNameCell):
+        (WI.NetworkTableContentView.prototype._generateSortComparator):
+        (WI.NetworkTableContentView.prototype._insertResourceAndReloadTable):
+        (WI.NetworkTableContentView.prototype._updateFilteredEntries):
+        (WI.NetworkTableContentView.prototype._handleGroupMediaRequestsByDOMNodeCheckedDidChange): Added.
+        (WI.NetworkTableContentView.prototype._handleGroupByDOMNodeCheckedDidChange): Deleted.
+        Rename the `groupByNode` setting to be more specific.
+
+2019-03-19  Devin Rousso  <drousso@apple.com>
+
</ins><span class="cx">         Web Inspector: CPU Usage Timeline - the right edge of each column should align with a CPU measurement
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=195789
</span><span class="cx">         <rdar://problem/48915271>
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js   2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js      2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -511,7 +511,10 @@
</span><span class="cx"> localizedStrings["Group Media Requests"] = "Group Media Requests";
</span><span class="cx"> localizedStrings["Group by Event"] = "Group by Event";
</span><span class="cx"> localizedStrings["Group by Node"] = "Group by Node";
</span><ins>+localizedStrings["Group by Path"] = "Group by Path";
+localizedStrings["Group by Type"] = "Group by Type";
</ins><span class="cx"> localizedStrings["Grouping Method"] = "Grouping Method";
</span><ins>+localizedStrings["Grouping Mode"] = "Grouping Mode";
</ins><span class="cx"> localizedStrings["HAR Export (%s)"] = "HAR Export (%s)";
</span><span class="cx"> localizedStrings["HAR Import"] = "HAR Import";
</span><span class="cx"> localizedStrings["HAR Import Error: %s"] = "HAR Import Error: %s";
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseSettingjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js        2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js   2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -134,7 +134,7 @@
</span><span class="cx">     emulateInUserGesture: new WI.Setting("emulate-in-user-gesture", false),
</span><span class="cx">     enableControlFlowProfiler: new WI.Setting("enable-control-flow-profiler", false),
</span><span class="cx">     enableLineWrapping: new WI.Setting("enable-line-wrapping", false),
</span><del>-    groupByDOMNode: new WI.Setting("group-by-dom-node", false),
</del><ins>+    groupMediaRequestsByDOMNode: new WI.Setting("group-media-requests-by-dom-node", WI.Setting.migrateValue("group-by-dom-node") || false),
</ins><span class="cx">     indentUnit: new WI.Setting("indent-unit", 4),
</span><span class="cx">     indentWithTabs: new WI.Setting("indent-with-tabs", false),
</span><span class="cx">     resourceCachingDisabled: new WI.Setting("disable-resource-caching", false),
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseURLUtilitiesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js   2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/URLUtilities.js      2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -214,7 +214,7 @@
</span><span class="cx">     return parameters;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-WI.displayNameForURL = function(url, urlComponents)
</del><ins>+WI.displayNameForURL = function(url, urlComponents, options = {})
</ins><span class="cx"> {
</span><span class="cx">     if (url.startsWith("data:"))
</span><span class="cx">         return WI.truncateURL(url);
</span><span class="lines">@@ -229,6 +229,9 @@
</span><span class="cx">         displayName = urlComponents.lastPathComponent;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (options.allowDirectoryAsName && (!displayName || urlComponents.path.endsWith(displayName + "/")))
+        displayName = "/";
+
</ins><span class="cx">     return displayName || WI.displayNameForHost(urlComponents.host) || url;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsResourcejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js     2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Resource.js        2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -1181,6 +1181,12 @@
</span><span class="cx">     High: Symbol("high"),
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+WI.Resource.GroupingMode = {
+    Path: "group-resource-by-path",
+    Type: "group-resource-by-type",
+};
+WI.settings.resourceGroupingMode = new WI.Setting("resource-grouping-mode", WI.Resource.GroupingMode.Type);
+
</ins><span class="cx"> // This MIME Type map is private, use WI.Resource.typeFromMIMEType().
</span><span class="cx"> WI.Resource._mimeTypeMap = {
</span><span class="cx">     "text/html": WI.Resource.Type.Document,
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolInspectorFrontendAPIjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendAPI.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendAPI.js       2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendAPI.js  2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -122,11 +122,7 @@
</span><span class="cx"> 
</span><span class="cx">     contextMenuItemSelected: function(id)
</span><span class="cx">     {
</span><del>-        try {
-            WI.ContextMenu.contextMenuItemSelected(id);
-        } catch (e) {
-            console.error("Uncaught exception in inspector page under contextMenuItemSelected", e);
-        }
</del><ins>+        WI.ContextMenu.contextMenuItemSelected(id);
</ins><span class="cx">     },
</span><span class="cx"> 
</span><span class="cx">     contextMenuCleared: function()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDetailsSectioncss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSection.css (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSection.css       2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DetailsSection.css  2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -140,7 +140,7 @@
</span><span class="cx"> 
</span><span class="cx"> .details-section > .header .go-to-arrow {
</span><span class="cx">     width: 10px;
</span><del>-    height: 12px;
</del><ins>+    height: 15px;
</ins><span class="cx">     -webkit-margin-start: 3px;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsGeneralTreeElementjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/GeneralTreeElement.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/GeneralTreeElement.js    2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/GeneralTreeElement.js       2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -191,6 +191,43 @@
</span><span class="cx">         this._tooltipHandledSeparately = !!x;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    createFoldersAsNeededForSubpath(subpath)
+    {
+        if (!subpath)
+            return this;
+
+        let components = subpath.split("/");
+        if (components.length === 1)
+            return this;
+
+        if (!this._subpathFolderTreeElementMap)
+            this._subpathFolderTreeElementMap = new Map;
+
+        let currentPath = "";
+        let currentFolderTreeElement = this;
+
+        for (let component of components) {
+            if (currentPath)
+                currentPath += "/";
+            currentPath += component;
+
+            let cachedFolder = this._subpathFolderTreeElementMap.get(currentPath);
+            if (cachedFolder) {
+                currentFolderTreeElement = cachedFolder;
+                continue;
+            }
+
+            let newFolder = new WI.FolderTreeElement(component);
+            this._subpathFolderTreeElementMap.set(currentPath, newFolder);
+
+            let index = insertionIndexForObjectInListSortedByFunction(newFolder, currentFolderTreeElement.children, WI.ResourceTreeElement.compareFolderAndResourceTreeElements);
+            currentFolderTreeElement.insertChild(newFolder, index);
+            currentFolderTreeElement = newFolder;
+        }
+
+        return currentFolderTreeElement;
+    }
+
</ins><span class="cx">     // Overrides from TreeElement (Private)
</span><span class="cx"> 
</span><span class="cx">     isEventWithinDisclosureTriangle(event)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsNetworkTableContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js       2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js  2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -88,10 +88,10 @@
</span><span class="cx">         this._typeFilterScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._typeFilterScopeBarSelectionChanged, this);
</span><span class="cx"> 
</span><span class="cx">         if (WI.MediaInstrument.supported()) {
</span><del>-            this._groupByDOMNodeNavigationItem = new WI.CheckboxNavigationItem("group-by-node", WI.UIString("Group Media Requests"), WI.settings.groupByDOMNode.value);
-            this._groupByDOMNodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupByDOMNodeCheckedDidChange, this);
</del><ins>+            this._groupMediaRequestsByDOMNodeNavigationItem = new WI.CheckboxNavigationItem("group-media-requests", WI.UIString("Group Media Requests"), WI.settings.groupMediaRequestsByDOMNode.value);
+            this._groupMediaRequestsByDOMNodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupMediaRequestsByDOMNodeCheckedDidChange, this);
</ins><span class="cx">         } else
</span><del>-            WI.settings.groupByDOMNode.value = false;
</del><ins>+            WI.settings.groupMediaRequestsByDOMNode.value = false;
</ins><span class="cx"> 
</span><span class="cx">         this._urlFilterSearchText = null;
</span><span class="cx">         this._urlFilterSearchRegex = null;
</span><span class="lines">@@ -246,7 +246,7 @@
</span><span class="cx">     {
</span><span class="cx">         let navigationItems = [this._urlFilterNavigationItem, this._typeFilterScopeBar];
</span><span class="cx">         if (WI.MediaInstrument.supported())
</span><del>-            navigationItems.push(this._groupByDOMNodeNavigationItem);
</del><ins>+            navigationItems.push(this._groupMediaRequestsByDOMNodeNavigationItem);
</ins><span class="cx">         return navigationItems;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -643,7 +643,7 @@
</span><span class="cx"> 
</span><span class="cx">         cell.classList.add(WI.ResourceTreeElement.ResourceIconStyleClassName);
</span><span class="cx"> 
</span><del>-        if (WI.settings.groupByDOMNode.value && resource.initiatorNode) {
</del><ins>+        if (WI.settings.groupMediaRequestsByDOMNode.value && resource.initiatorNode) {
</ins><span class="cx">             let nodeEntry = this._domNodeEntries.get(resource.initiatorNode);
</span><span class="cx">             if (nodeEntry.initiatedResourceEntries.length > 1 || nodeEntry.domNode.domEvents.length)
</span><span class="cx">                 cell.classList.add("child");
</span><span class="lines">@@ -1063,7 +1063,7 @@
</span><span class="cx">         // This will ensure that all resource entries for a given `initiatorNode` will appear right
</span><span class="cx">         // next to each other, as they will all effectively be sorted by the first resource.
</span><span class="cx">         let substitute = (entry, other) => {
</span><del>-            if (WI.settings.groupByDOMNode.value && entry.resource.initiatorNode) {
</del><ins>+            if (WI.settings.groupMediaRequestsByDOMNode.value && entry.resource.initiatorNode) {
</ins><span class="cx">                 let nodeEntry = this._domNodeEntries.get(entry.resource.initiatorNode);
</span><span class="cx">                 if (!nodeEntry.initiatedResourceEntries.includes(other))
</span><span class="cx">                     return nodeEntry.initiatedResourceEntries[0];
</span><span class="lines">@@ -1710,7 +1710,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._tryLinkResourceToDOMNode(resourceEntry);
</span><span class="cx"> 
</span><del>-        if (WI.settings.groupByDOMNode.value && resource.initiatorNode) {
</del><ins>+        if (WI.settings.groupMediaRequestsByDOMNode.value && resource.initiatorNode) {
</ins><span class="cx">             if (!this._entriesSortComparator)
</span><span class="cx">                 this._generateSortComparator();
</span><span class="cx">         } else if (this._isDefaultSort() || !this._entriesSortComparator) {
</span><span class="lines">@@ -1726,7 +1726,7 @@
</span><span class="cx">         insertObjectIntoSortedArray(resourceEntry, collection.entries, this._entriesSortComparator);
</span><span class="cx"> 
</span><span class="cx">         if (this._passFilter(resourceEntry)) {
</span><del>-            if (WI.settings.groupByDOMNode.value)
</del><ins>+            if (WI.settings.groupMediaRequestsByDOMNode.value)
</ins><span class="cx">                 this._updateFilteredEntries();
</span><span class="cx">             else
</span><span class="cx">                 insertObjectIntoSortedArray(resourceEntry, collection.filteredEntries, this._entriesSortComparator);
</span><span class="lines">@@ -1897,7 +1897,7 @@
</span><span class="cx">         else
</span><span class="cx">             collection.filteredEntries = collection.entries.slice();
</span><span class="cx"> 
</span><del>-        if (WI.settings.groupByDOMNode.value) {
</del><ins>+        if (WI.settings.groupMediaRequestsByDOMNode.value) {
</ins><span class="cx">             for (let nodeEntry of this._domNodeEntries.values()) {
</span><span class="cx">                 if (nodeEntry.initiatedResourceEntries.length < 2 && !nodeEntry.domNode.domEvents.length)
</span><span class="cx">                     continue;
</span><span class="lines">@@ -2003,11 +2003,11 @@
</span><span class="cx">         this._reloadTable();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _handleGroupByDOMNodeCheckedDidChange(event)
</del><ins>+    _handleGroupMediaRequestsByDOMNodeCheckedDidChange(event)
</ins><span class="cx">     {
</span><del>-        WI.settings.groupByDOMNode.value = this._groupByDOMNodeNavigationItem.checked;
</del><ins>+        WI.settings.groupMediaRequestsByDOMNode.value = this._groupMediaRequestsByDOMNodeNavigationItem.checked;
</ins><span class="cx"> 
</span><del>-        if (!WI.settings.groupByDOMNode.value) {
</del><ins>+        if (!WI.settings.groupMediaRequestsByDOMNode.value) {
</ins><span class="cx">             this._table.element.classList.remove("grouped");
</span><span class="cx"> 
</span><span class="cx">             if (this._selectedObject && this._selectedObject instanceof WI.DOMNode) {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsResourceTreeElementjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js   2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.js      2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> WI.ResourceTreeElement = class ResourceTreeElement extends WI.SourceCodeTreeElement
</span><span class="cx"> {
</span><del>-    constructor(resource, representedObject)
</del><ins>+    constructor(resource, representedObject, {allowDirectoryAsName, hideOrigin} = {})
</ins><span class="cx">     {
</span><span class="cx">         console.assert(resource instanceof WI.Resource);
</span><span class="cx"> 
</span><span class="lines">@@ -33,6 +33,11 @@
</span><span class="cx">         const subtitle = null;
</span><span class="cx">         super(resource, ["resource", WI.ResourceTreeElement.ResourceIconStyleClassName, WI.Resource.classNameForResource(resource)], title, subtitle, representedObject || resource);
</span><span class="cx"> 
</span><ins>+        if (allowDirectoryAsName)
+            this._allowDirectoryAsName = allowDirectoryAsName;
+        if (hideOrigin)
+            this._hideOrigin = hideOrigin;
+
</ins><span class="cx">         this._updateResource(resource);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -135,7 +140,9 @@
</span><span class="cx"> 
</span><span class="cx">     get mainTitleText()
</span><span class="cx">     {
</span><del>-        return WI.displayNameForURL(this._resource.url, this._resource.urlComponents);
</del><ins>+        return WI.displayNameForURL(this._resource.url, this._resource.urlComponents, {
+            allowDirectoryAsName: this._allowDirectoryAsName,
+        });
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _updateTitles()
</span><span class="lines">@@ -158,9 +165,11 @@
</span><span class="cx">         var oldMainTitle = this.mainTitle;
</span><span class="cx">         this.mainTitle = this.mainTitleText;
</span><span class="cx"> 
</span><del>-        // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource.
-        var subtitle = parentResourceHost !== urlComponents.host || frame && frame.isMainFrame() && isMainResource ? WI.displayNameForHost(urlComponents.host) : null;
-        this.subtitle = this.mainTitle !== subtitle ? subtitle : null;
</del><ins>+        if (!this._hideOrigin) {
+            // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource.
+            var subtitle = parentResourceHost !== urlComponents.host || frame && frame.isMainFrame() && isMainResource ? WI.displayNameForHost(urlComponents.host) : null;
+            this.subtitle = this.mainTitle !== subtitle ? subtitle : null;
+        }
</ins><span class="cx"> 
</span><span class="cx">         if (oldMainTitle !== this.mainTitle)
</span><span class="cx">             this.callFirstAncestorFunction("descendantResourceTreeElementMainTitleDidChange", [this, oldMainTitle]);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourceCodeTreeElementjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js 2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourceCodeTreeElement.js    2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -130,43 +130,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Protected
</span><span class="cx"> 
</span><del>-    createFoldersAsNeededForSubpath(subpath)
-    {
-        if (!subpath)
-            return this;
-
-        var components = subpath.split("/");
-        if (components.length === 1)
-            return this;
-
-        if (!this._subpathFolderTreeElementMap)
-            this._subpathFolderTreeElementMap = {};
-
-        var currentPath = "";
-        var currentFolderTreeElement = this;
-
-        for (var i = 0; i < components.length - 1; ++i) {
-            var componentName = components[i];
-            currentPath += (i ? "/" : "") + componentName;
-
-            var cachedFolder = this._subpathFolderTreeElementMap[currentPath];
-            if (cachedFolder) {
-                currentFolderTreeElement = cachedFolder;
-                continue;
-            }
-
-            var newFolder = new WI.FolderTreeElement(componentName);
-            newFolder.__path = currentPath;
-            this._subpathFolderTreeElementMap[currentPath] = newFolder;
-
-            var index = insertionIndexForObjectInListSortedByFunction(newFolder, currentFolderTreeElement.children, WI.ResourceTreeElement.compareFolderAndResourceTreeElements);
-            currentFolderTreeElement.insertChild(newFolder, index);
-            currentFolderTreeElement = newFolder;
-        }
-
-        return currentFolderTreeElement;
-    }
-
</del><span class="cx">     descendantResourceTreeElementTypeDidChange(childTreeElement, oldType)
</span><span class="cx">     {
</span><span class="cx">         // Called by descendant SourceMapResourceTreeElements.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPanelcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css        2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.css   2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -24,6 +24,8 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> .sidebar > .panel.navigation.sources > .content {
</span><ins>+    display: flex;
+    flex-direction: column;
</ins><span class="cx">     top: var(--navigation-bar-height);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -73,6 +75,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .sidebar > .panel.navigation.sources > .content > .details-section.paused-reason.collapsed > .header > .options,
</span><ins>+.sidebar > .panel.navigation.sources > .content > .details-section.breakpoints.collapsed > .header > .options,
</ins><span class="cx"> .sidebar > .panel.navigation.sources > .content > .details-section > .content,
</span><span class="cx"> .sidebar > .panel.navigation.sources > .content > .details-section > .content > .group {
</span><span class="cx">     display: block;
</span><span class="lines">@@ -82,8 +85,8 @@
</span><span class="cx">     display: none;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.sidebar > .panel.navigation.sources > .content > .details-section.scripts:not(.collapsed) {
-    border-bottom: none;
</del><ins>+.sidebar > .panel.navigation.sources > .content > .details-section.breakpoints > .header > .options .create-breakpoint {
+    width: 15px;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .sidebar > .panel.navigation.sources > .content > .navigation-bar {
</span><span class="lines">@@ -90,11 +93,16 @@
</span><span class="cx">     margin-bottom: 1px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread {
</del><ins>+.sidebar > .panel.navigation.sources > .content > .resources {
+    position: relative;
+    height: 100%;
+}
+
+.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread {
</ins><span class="cx">     -webkit-margin-start: -10px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.sidebar > .panel.navigation.sources > .content > .tree-outline.single-thread > .item.thread {
</del><ins>+.sidebar > .panel.navigation.sources > .content .tree-outline.single-thread > .item.thread {
</ins><span class="cx">     display: none;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSourcesNavigationSidebarPaneljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js (243179 => 243180)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js 2019-03-19 23:34:03 UTC (rev 243179)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SourcesNavigationSidebarPanel.js    2019-03-19 23:35:20 UTC (rev 243180)
</span><span class="lines">@@ -30,6 +30,16 @@
</span><span class="cx">         const shouldAutoPruneStaleTopLevelResourceTreeElements = true;
</span><span class="cx">         super("sources", WI.UIString("Sources"), shouldAutoPruneStaleTopLevelResourceTreeElements);
</span><span class="cx"> 
</span><ins>+        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);
+
</ins><span class="cx">         this._debuggerNavigationBar = new WI.NavigationBar;
</span><span class="cx">         this.addSubview(this._debuggerNavigationBar);
</span><span class="cx"> 
</span><span class="lines">@@ -175,18 +185,11 @@
</span><span class="cx">         let breakpointsSection = new WI.DetailsSection("breakpoints", WI.UIString("Breakpoints"), [breakpointsGroup], breakpointNavigationBarWrapper);
</span><span class="cx">         this.contentView.element.insertBefore(breakpointsSection.element, this.contentView.element.firstChild);
</span><span class="cx"> 
</span><del>-        this._resourcesTreeOutline = this.contentTreeOutline;
-        this._resourcesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
-        this._resourcesTreeOutline.includeSourceMapResourceChildren = true;
-
</del><span class="cx">         this._resourcesNavigationBar = new WI.NavigationBar;
</span><span class="cx">         this.contentView.addSubview(this._resourcesNavigationBar);
</span><del>-        this.contentView.element.insertBefore(this._resourcesNavigationBar.element, this._resourcesTreeOutline.element);
</del><ins>+        this.contentView.element.insertBefore(this._resourcesNavigationBar.element, breakpointsSection.nextSibling);
</ins><span class="cx"> 
</span><del>-        this._workerTargetTreeElementMap = new Map;
-        this._extensionScriptsFolderTreeElement = null;
-        this._extraScriptsFolderTreeElement = null;
-        this._anonymousScriptsFolderTreeElement = null;
</del><ins>+        this._resourcesNavigationBar.addNavigationItem(new WI.FlexibleSpaceNavigationItem);
</ins><span class="cx"> 
</span><span class="cx">         const resourceTypeScopeItemPrefix = "sources-resource-type-";
</span><span class="cx">         let resourceTypeScopeBarItems = [];
</span><span class="lines">@@ -202,6 +205,21 @@
</span><span class="cx">         this._resourceTypeScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._handleResourceTypeScopeBarSelectionChanged, this);
</span><span class="cx">         this._resourcesNavigationBar.addNavigationItem(this._resourceTypeScopeBar);
</span><span class="cx"> 
</span><ins>+        this._resourcesNavigationBar.addNavigationItem(new WI.FlexibleSpaceNavigationItem);
+
+        let resourceGroupingModeNavigationItem = new WI.ButtonNavigationItem("grouping-mode", WI.UIString("Grouping Mode"), "Images/Gear.svg", 15, 15);
+        resourceGroupingModeNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
+        resourceGroupingModeNavigationItem.element.addEventListener("mousedown", this._handleResourceGroupingModeMouseDown.bind(this));
+        this._resourcesNavigationBar.addNavigationItem(resourceGroupingModeNavigationItem);
+
+        let resourcesContainer = this.contentView.element.insertBefore(document.createElement("div"), this._resourcesNavigationBar.element.nextSibling);
+        resourcesContainer.classList.add("resources");
+
+        this._resourcesTreeOutline = this.contentTreeOutline;
+        this._resourcesTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._handleTreeSelectionDidChange, this);
+        this._resourcesTreeOutline.includeSourceMapResourceChildren = true;
+        resourcesContainer.appendChild(this._resourcesTreeOutline.element);
+
</ins><span class="cx">         let onlyShowResourcesWithIssuesFilterFunction = (treeElement) => {
</span><span class="cx">             if (treeElement.treeOutline !== this._resourcesTreeOutline)
</span><span class="cx">                 return true;
</span><span class="lines">@@ -220,6 +238,8 @@
</span><span class="cx">         const activatedByDefault = false;
</span><span class="cx">         this.filterBar.addFilterBarButton("sources-only-show-resources-with-issues", onlyShowResourcesWithIssuesFilterFunction, activatedByDefault, WI.UIString("Only show resources with issues"), WI.UIString("Show all resources"), "Images/Errors.svg", 15, 15);
</span><span class="cx"> 
</span><ins>+        WI.settings.resourceGroupingMode.addEventListener(WI.Setting.Event.Changed, this._handleResourceGroupingModeChanged, this);
+
</ins><span class="cx">         WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._handleFrameMainResourceDidChange, this);
</span><span class="cx">         WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._handleResourceAdded, this);
</span><span class="cx">         WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._handleResourceAdded, this);
</span><span class="lines">@@ -281,24 +301,13 @@
</span><span class="cx">         if (InspectorBackend.domains.Debugger.setPauseOnAssertions && WI.settings.showAssertionFailuresBreakpoint.value)
</span><span class="cx">             WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
</span><span class="cx"> 
</span><del>-        let mainFrame = WI.networkManager.mainFrame;
-        if (mainFrame) {
-            this._updateMainFrameTreeElement(mainFrame);
-            this._addResourcesRecursivelyForFrame(mainFrame);
-        }
-
</del><span class="cx">         for (let target of WI.targets)
</span><span class="cx">             this._addTarget(target);
</span><span class="cx"> 
</span><span class="cx">         this._updateCallStackTreeOutline();
</span><span class="cx"> 
</span><del>-        for (let script of WI.debuggerManager.knownNonResourceScripts) {
-            this._addScript(script);
</del><ins>+        this._handleResourceGroupingModeChanged();
</ins><span class="cx"> 
</span><del>-            if (script.sourceMaps.length && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
-                this._resourcesTreeOutline.disclosureButtons = true;
-        }
-
</del><span class="cx">         if (WI.domDebuggerManager.supported) {
</span><span class="cx">             if (WI.settings.showAllRequestsBreakpoint.value)
</span><span class="cx">                 WI.domDebuggerManager.addURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
</span><span class="lines">@@ -347,6 +356,7 @@
</span><span class="cx"> 
</span><span class="cx">     closed()
</span><span class="cx">     {
</span><ins>+        WI.settings.resourceGroupingMode.removeEventListener(null, null, this);
</ins><span class="cx">         WI.Frame.removeEventListener(null, null, this);
</span><span class="cx">         WI.Target.removeEventListener(null, null, this);
</span><span class="cx">         WI.networkManager.removeEventListener(null, null, this);
</span><span class="lines">@@ -387,7 +397,6 @@
</span><span class="cx">             return null;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // The Frame is used as the representedObject instead of the main resource in our tree.
</del><span class="cx">         if (representedObject instanceof WI.Resource && representedObject.parentFrame && representedObject.parentFrame.mainResource === representedObject)
</span><span class="cx">             representedObject = representedObject.parentFrame;
</span><span class="cx"> 
</span><span class="lines">@@ -417,7 +426,12 @@
</span><span class="cx">             return resourceOrFrame.parentFrame;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        let treeElement = this._resourcesTreeOutline.findTreeElement(representedObject, isAncestor, getParent);
</del><ins>+        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);
</ins><span class="cx">         if (treeElement)
</span><span class="cx">             return treeElement;
</span><span class="cx"> 
</span><span class="lines">@@ -441,7 +455,7 @@
</span><span class="cx">             this._anonymousScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Anonymous Scripts"), new WI.ScriptCollection);
</span><span class="cx"> 
</span><span class="cx">         if (!this._anonymousScriptsFolderTreeElement.parent) {
</span><del>-            let index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this._resourcesTreeOutline.children, this._compareTreeElements);
</del><ins>+            let index = insertionIndexForObjectInListSortedByFunction(this._anonymousScriptsFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
</ins><span class="cx">             this._resourcesTreeOutline.insertChild(this._anonymousScriptsFolderTreeElement, index);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -485,6 +499,9 @@
</span><span class="cx">         if (treeElement instanceof WI.FolderTreeElement)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><ins>+        if (treeElement instanceof WI.IssueTreeElement)
+            treeElement = treeElement.parent;
+
</ins><span class="cx">         function match()
</span><span class="cx">         {
</span><span class="cx">             if (treeElement instanceof WI.FrameTreeElement)
</span><span class="lines">@@ -527,16 +544,30 @@
</span><span class="cx"> 
</span><span class="cx">     _compareTreeElements(a, b)
</span><span class="cx">     {
</span><del>-        // Always sort the main frame element first.
-        if (a instanceof WI.FrameTreeElement)
-            return -1;
-        if (b instanceof WI.FrameTreeElement)
-            return 1;
</del><ins>+        const rankFunctions = [
+            (treeElement) => treeElement === this._mainFrameTreeElement,
+            (treeElement) => treeElement instanceof WI.FrameTreeElement,
+            (treeElement) => {
+                return treeElement instanceof WI.FolderTreeElement
+                    && treeElement !== this._extensionScriptsFolderTreeElement
+                    && treeElement !== this._extraScriptsFolderTreeElement
+                    && treeElement !== this._anonymousScriptsFolderTreeElement;
+            },
+            (treeElement) => treeElement === this._extensionScriptsFolderTreeElement,
+            (treeElement) => treeElement === this._extraScriptsFolderTreeElement,
+            (treeElement) => treeElement === this._anonymousScriptsFolderTreeElement,
+        ];
</ins><span class="cx"> 
</span><del>-        console.assert(a.mainTitle);
-        console.assert(b.mainTitle);
</del><ins>+        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;
+        }
</ins><span class="cx"> 
</span><del>-        return (a.mainTitle || "").extendedLocaleCompare(b.mainTitle || "");
</del><ins>+        return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _updateMainFrameTreeElement(mainFrame)
</span><span class="lines">@@ -544,6 +575,7 @@
</span><span class="cx">         if (this.didInitialLayout)
</span><span class="cx">             this.contentBrowser.contentViewContainer.closeAllContentViews();
</span><span class="cx"> 
</span><ins>+        let oldMainFrameTreeElement = this._mainFrameTreeElement;
</ins><span class="cx">         if (this._mainFrameTreeElement) {
</span><span class="cx">             this._resourcesTreeOutline.removeChild(this._mainFrameTreeElement);
</span><span class="cx">             this._mainFrameTreeElement = null;
</span><span class="lines">@@ -552,7 +584,28 @@
</span><span class="cx">         if (!mainFrame)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        this._mainFrameTreeElement = new WI.FrameTreeElement(mainFrame);
</del><ins>+        let resourceGroupingMode = WI.settings.resourceGroupingMode.value;
+        switch (resourceGroupingMode) {
+        case WI.Resource.GroupingMode.Path:
+            for (let treeElement of this._originTreeElementMap.values()) {
+                if (treeElement !== oldMainFrameTreeElement)
+                    this._resourcesTreeOutline.removeChild(treeElement);
+            }
+            this._originTreeElementMap.clear();
+
+            this._mainFrameTreeElement = new WI.FolderTreeElement(mainFrame.securityOrigin, mainFrame);
+            this._originTreeElementMap.set(mainFrame.securityOrigin, 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;
+        }
+
</ins><span class="cx">         this._resourcesTreeOutline.insertChild(this._mainFrameTreeElement, 0);
</span><span class="cx"> 
</span><span class="cx">         // Cookie restoration will attempt to re-select the resource we were showing.
</span><span class="lines">@@ -564,7 +617,7 @@
</span><span class="cx">             let currentContentView = this.contentBrowser.currentContentView;
</span><span class="cx">             let treeElement = currentContentView ? this.treeElementForRepresentedObject(currentContentView.representedObject) : null;
</span><span class="cx">             if (!treeElement)
</span><del>-                treeElement = this._mainFrameTreeElement;
</del><ins>+                treeElement = this.treeElementForRepresentedObject(WI.networkManager.mainFrame);
</ins><span class="cx">             this.showDefaultContentViewForTreeElement(treeElement);
</span><span class="cx">         });
</span><span class="cx">     }
</span><span class="lines">@@ -600,11 +653,42 @@
</span><span class="cx"> 
</span><span class="cx">     _addResource(resource)
</span><span class="cx">     {
</span><del>-        if (resource.type !== WI.Resource.Type.Document && resource.type !== WI.Resource.Type.Script)
-            return;
</del><ins>+        if (WI.settings.resourceGroupingMode.value === WI.Resource.GroupingMode.Path) {
+            if (!this._mainFrameTreeElement || this._resourcesTreeOutline.findTreeElement(resource))
+                return;
</ins><span class="cx"> 
</span><del>-        this._addBreakpointsForSourceCode(resource);
-        this._addIssuesForSourceCode(resource);
</del><ins>+            let origin = null;
+            if (resource.urlComponents.scheme && resource.urlComponents.host) {
+                origin = resource.urlComponents.scheme + "://" + resource.urlComponents.host;
+                if (resource.urlComponents.port)
+                    origin += ":" + resource.urlComponents.port;
+            } else
+                origin = resource.parentFrame.securityOrigin;
+
+            let frameTreeElement = this._originTreeElementMap.get(origin);
+            if (!frameTreeElement) {
+                frameTreeElement = new WI.FolderTreeElement(origin, origin === resource.parentFrame.securityOrigin ? resource.parentFrame : null);
+                this._originTreeElementMap.set(origin, frameTreeElement);
+
+                let index = insertionIndexForObjectInListSortedByFunction(frameTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
+                this._resourcesTreeOutline.insertChild(frameTreeElement, index);
+            }
+
+            let subpath = resource.urlComponents.path;
+            if (subpath && subpath[0] === "/")
+                subpath = subpath.substring(1);
+
+            let parent = frameTreeElement.createFoldersAsNeededForSubpath(subpath);
+            if (resource instanceof WI.CSSStyleSheet)
+                parent.appendChild(new WI.CSSStyleSheetTreeElement(resource));
+            else
+                parent.appendChild(new WI.ResourceTreeElement(resource, resource, {allowDirectoryAsName: true, hideOrigin: true}));
+        }
+
+        if (resource.type === WI.Resource.Type.Document || resource.type === WI.Resource.Type.Script) {
+            this._addBreakpointsForSourceCode(resource);
+            this._addIssuesForSourceCode(resource);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _addResourcesRecursivelyForFrame(frame)
</span><span class="lines">@@ -642,20 +726,22 @@
</span><span class="cx">         if (script.resource || script.dynamicallyAddedScriptElement)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        let insertIntoTopLevel = false;
-        let parentFolderTreeElement = null;
</del><ins>+        let scriptTreeElement = new WI.ScriptTreeElement(script);
</ins><span class="cx"> 
</span><del>-        if (script.injected) {
-            if (!this._extensionScriptsFolderTreeElement) {
-                let collection = new WI.ScriptCollection;
-                this._extensionScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extension Scripts"), collection);
-            }
</del><ins>+        if (!script.injected && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel()) {
+            let index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
+            this._resourcesTreeOutline.insertChild(scriptTreeElement, index);
+        } else {
+            let parentFolderTreeElement = null;
</ins><span class="cx"> 
</span><del>-            parentFolderTreeElement = this._extensionScriptsFolderTreeElement;
-        } else {
-            if (WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
-                insertIntoTopLevel = true;
-            else {
</del><ins>+            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 {
</ins><span class="cx">                 if (!this._extraScriptsFolderTreeElement) {
</span><span class="cx">                     let collection = new WI.ScriptCollection;
</span><span class="cx">                     this._extraScriptsFolderTreeElement = new WI.FolderTreeElement(WI.UIString("Extra Scripts"), collection);
</span><span class="lines">@@ -663,19 +749,12 @@
</span><span class="cx"> 
</span><span class="cx">                 parentFolderTreeElement = this._extraScriptsFolderTreeElement;
</span><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if (parentFolderTreeElement)
-            parentFolderTreeElement.representedObject.add(script);
</del><ins>+            if (parentFolderTreeElement)
+                parentFolderTreeElement.representedObject.add(script);
</ins><span class="cx"> 
</span><del>-        let scriptTreeElement = new WI.ScriptTreeElement(script);
-
-        if (insertIntoTopLevel) {
-            let index = insertionIndexForObjectInListSortedByFunction(scriptTreeElement, this._resourcesTreeOutline.children, this._compareTreeElements);
-            this._resourcesTreeOutline.insertChild(scriptTreeElement, index);
-        } else {
</del><span class="cx">             if (!parentFolderTreeElement.parent) {
</span><del>-                let index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this._resourcesTreeOutline.children, this._compareTreeElements);
</del><ins>+                let index = insertionIndexForObjectInListSortedByFunction(parentFolderTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
</ins><span class="cx">                 this._resourcesTreeOutline.insertChild(parentFolderTreeElement, index);
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -693,7 +772,7 @@
</span><span class="cx">         let targetTreeElement = new WI.WorkerTreeElement(target);
</span><span class="cx">         this._workerTargetTreeElementMap.set(target, targetTreeElement);
</span><span class="cx"> 
</span><del>-        let index = insertionIndexForObjectInListSortedByFunction(targetTreeElement, this._resourcesTreeOutline.children, this._compareTreeElements);
</del><ins>+        let index = insertionIndexForObjectInListSortedByFunction(targetTreeElement, this._resourcesTreeOutline.children, this._boundCompareTreeElements);
</ins><span class="cx">         this._resourcesTreeOutline.insertChild(targetTreeElement, index);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1258,6 +1337,29 @@
</span><span class="cx">         this.updateFilter();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _handleResourceGroupingModeMouseDown(event)
+    {
+        if (this._ignoreResourceGroupingModeMouseDown)
+            return;
+
+        this._ignoreResourceGroupingModeMouseDown = true;
+
+        let contextMenu = WI.ContextMenu.createFromEvent(event);
+        contextMenu.addBeforeShowCallback(() => {
+            this._ignoreResourceGroupingModeMouseDown = false;
+        });
+
+        function addOption(mode, label) {
+            contextMenu.appendCheckboxItem(label, () => {
+                WI.settings.resourceGroupingMode.value = mode;
+            }, WI.settings.resourceGroupingMode.value === mode);
+        }
+        addOption(WI.Resource.GroupingMode.Path, WI.UIString("Group by Path"));
+        addOption(WI.Resource.GroupingMode.Type, WI.UIString("Group by Type"));
+
+        contextMenu.show();
+    }
+
</ins><span class="cx">     _handleTreeSelectionDidChange(event)
</span><span class="cx">     {
</span><span class="cx">         if (!this.selected)
</span><span class="lines">@@ -1277,7 +1379,9 @@
</span><span class="cx">             || treeElement instanceof WI.ResourceTreeElement
</span><span class="cx">             || treeElement instanceof WI.ScriptTreeElement
</span><span class="cx">             || treeElement instanceof WI.CSSStyleSheetTreeElement) {
</span><del>-            WI.showRepresentedObject(treeElement.representedObject);
</del><ins>+            let representedObject = treeElement.representedObject;
+            if (representedObject instanceof WI.Collection || representedObject instanceof WI.SourceCode)
+                WI.showRepresentedObject(representedObject);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1387,10 +1491,38 @@
</span><span class="cx">         contextMenu.show();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _handleResourceGroupingModeChanged(event)
+    {
+        this._workerTargetTreeElementMap.clear();
+        this._mainFrameTreeElement = null;
+        this._extensionScriptsFolderTreeElement = null;
+        this._extraScriptsFolderTreeElement = null;
+        this._anonymousScriptsFolderTreeElement = null;
+
+        this._originTreeElementMap.clear();
+
+        this._resourcesTreeOutline.removeChildren();
+
+        let mainFrame = WI.networkManager.mainFrame;
+        if (mainFrame) {
+            this._updateMainFrameTreeElement(mainFrame);
+            this._addResourcesRecursivelyForFrame(mainFrame);
+        }
+
+        for (let script of WI.debuggerManager.knownNonResourceScripts) {
+            this._addScript(script);
+
+            if (script.sourceMaps.length && WI.SourcesNavigationSidebarPanel.shouldPlaceResourcesAtTopLevel())
+                this._resourcesTreeOutline.disclosureButtons = true;
+        }
+    }
+
</ins><span class="cx">     _handleFrameMainResourceDidChange(event)
</span><span class="cx">     {
</span><del>-        if (event.target.isMainFrame()) {
-            this._updateMainFrameTreeElement(event.target);
</del><ins>+        let frame = event.target;
+        if (frame.isMainFrame()) {
+            this._updateMainFrameTreeElement(frame);
+            this._addResourcesRecursivelyForFrame(frame);
</ins><span class="cx"> 
</span><span class="cx">             for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
</span><span class="cx">                 this._removeBreakpoint(domBreakpoint);
</span><span class="lines">@@ -1410,7 +1542,9 @@
</span><span class="cx"> 
</span><span class="cx">     _handleMainFrameDidChange(event)
</span><span class="cx">     {
</span><del>-        this._updateMainFrameTreeElement(WI.networkManager.mainFrame);
</del><ins>+        let mainFrame = WI.networkManager.mainFrame;
+        this._updateMainFrameTreeElement(mainFrame);
+        this._addResourcesRecursivelyForFrame(mainFrame);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     _handleDebuggerBreakpointAdded(event)
</span></span></pre>
</div>
</div>

</body>
</html>