<!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>[199143] trunk</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/199143">199143</a></dd>
<dt>Author</dt> <dd>mattbaker@apple.com</dd>
<dt>Date</dt> <dd>2016-04-06 19:09:07 -0700 (Wed, 06 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Improve filtering in OpenResourceDialog
https://bugs.webkit.org/show_bug.cgi?id=155324
&lt;rdar://problem/25094504&gt;

Source/WebInspectorUI:

Reviewed by Joseph Pecoraro and Timothy Hatcher.

* UserInterface/Base/Utilities.js:
(value):
Added String methods isLowerCase, isUpperCase, removeWhitespace.

* UserInterface/Controllers/ResourceQueryController.js: Added.
(WebInspector.ResourceQueryController):
(WebInspector.ResourceQueryController.prototype.addResource):
(WebInspector.ResourceQueryController.prototype.removeResource):
Add and remove the resources to be queried.

(WebInspector.ResourceQueryController.prototype.reset):
Reset controller state. Current just clears resources.

(WebInspector.ResourceQueryController.prototype.executeQuery):
Executes a query against the list of resources and returns a list of
QueryResult objects, with at most one result per resource, ordered by
descending rank.

The query string is stripped of whitespace characters and lowercased
before use. Prior to running the query, resources undergo a one-time
pre-processing step to locate special characters.

(WebInspector.ResourceQueryController.prototype._findQueryMatches.pushMatch):
(WebInspector.ResourceQueryController.prototype._findQueryMatches.matchNextSpecialCharacter):
(WebInspector.ResourceQueryController.prototype._findQueryMatches.backtrack):
(WebInspector.ResourceQueryController.prototype._findQueryMatches):
Returns a list of query matches for a single resource, along with metadata
which is used to rank the matches. The algorithm attempts to match the
entire query, first comparing each query character against &quot;special&quot; characters
in the resource (commonly used filename separators, the first character,
and camel-case word boundaries).

If there are remaining query characters after exhausting special characters,
regular characters are matched starting from the last matched special
character. Failing that, the algorithm attempts to find a match by backtracking.
To backtrack, the last match is discarded and the query position decremented.
If a special match is now the last match, matching starts again from the
next character in the filename after the match. If a normal match is now
the last match, keep discarding until a special match is found or no matches
remain. The query fails if no matches remain. For example, consider:

   Query: &quot;abcd&quot;
   Filename: &quot;AxBcdCx&quot;

The capital A, B, and C are all special characters, and are successfully
matched with the first three query characters. Having exhausted the special
characters the &quot;d&quot; at the end of the query is compared with the &quot;x&quot; at
the end of the filename, and fails to match. Backtracking then kicks in.
The last match, &quot;C&quot;, is discarded and the search position in the query
decremented. The search resumes after the next to last match, &quot;B&quot;, and now
matches the non-special characters &quot;cd&quot;, yielding the following: &quot;A Bcd  &quot;.

(WebInspector.ResourceQueryController.prototype._findSpecialCharacterIndices):
Pre-processing step for resources. Locates the positions of special
characters in the resource filename. Special characters are defined as:

   1. The first character
   2. Common filename separators, and the character immediately following.
   3. A capital letter that follows a lowercase character.

* UserInterface/Models/ResourceQueryMatch.js: Added.
Helper class used internally by the controller and QueryResult classes.
(WebInspector.ResourceQueryMatch):
(WebInspector.ResourceQueryMatch.prototype.get type):
(WebInspector.ResourceQueryMatch.prototype.get index):
(WebInspector.ResourceQueryMatch.prototype.get queryIndex):

* UserInterface/Models/ResourceQueryResult.js: Added.
Holds a resource that matched the executed query.
(WebInspector.ResourceQueryResult):
(WebInspector.ResourceQueryResult.prototype.get resource):
(WebInspector.ResourceQueryResult.prototype.get rank):
Ranking relative to other results returned by the query. Used by
the ResourceQueryController to sort results.

(WebInspector.ResourceQueryResult.prototype.get matchingTextRanges):
Get TextRanges for matching substrings in the resource display name.

(WebInspector.ResourceQueryResult.prototype._calculateRank):
Calculate the rank of the result. Matches are scored based on the type
of match (Special vs. Normal), the location of the match within the filename
(matches closer to the beginning are scored higher), and whether the match
is adjacent to the previous match.

Values assigned to each ranking criteria are somewhat arbitrary, and may
be fine-tuned over time to produce better results.

(WebInspector.ResourceQueryResult.prototype._createMatchingTextRanges):
(WebInspector.ResourceQueryResult.prototype.__test_createMatchesMask):
Test API for visualizing matches. For a result returned from the query
&quot;abce&quot;, run against a filename &quot;abcde&quot;, the mask is &quot;a c e&quot;.

* UserInterface/Main.html:
* UserInterface/Test.html:
New files.

* UserInterface/Views/Dialog.js:
(WebInspector.Dialog.prototype.dismiss):
(WebInspector.Dialog.prototype.didDismissDialog):
Add hook for subclasses to perform actions after on dialog dismissal.

* UserInterface/Views/OpenResourceDialog.js:
(WebInspector.OpenResourceDialog):
(WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline.createHighlightedTitleFragment):
(WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline):
Add tree elements for each QueryResult returned by the last query, creating
titles with contiguous matching query characters wrapped in highlight spans.

(WebInspector.OpenResourceDialog.prototype.didDismissDialog):
Clear resources from the ResourceQueryController.
(WebInspector.OpenResourceDialog.prototype.didPresentDialog):
Add resources to the ResourceQueryController.
(WebInspector.OpenResourceDialog.prototype._updateFilter):
Execute the filter text as a resource query.

* UserInterface/Views/TreeOutline.css:
(.tree-outline.large .item .titles): Deleted.
Line height too small, hid the bottom border of highlighted matches in
tree element title spans. Removing the style had no negative visual impact
on the Quick Open or Timelines tree outlines (the only &quot;large&quot; trees).

LayoutTests:

Reviewed by Joseph Pecoraro.

Add test coverage for ResourceQueryController.

* inspector/unit-tests/resource-query-controller-expected.txt: Added.
* inspector/unit-tests/resource-query-controller.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceBaseUtilitiesjs">trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceTesthtml">trunk/Source/WebInspectorUI/UserInterface/Test.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDialogjs">trunk/Source/WebInspectorUI/UserInterface/Views/Dialog.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsOpenResourceDialogjs">trunk/Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinecss">trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectorunittestsresourcequerycontrollerexpectedtxt">trunk/LayoutTests/inspector/unit-tests/resource-query-controller-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorunittestsresourcequerycontrollerhtml">trunk/LayoutTests/inspector/unit-tests/resource-query-controller.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceControllersResourceQueryControllerjs">trunk/Source/WebInspectorUI/UserInterface/Controllers/ResourceQueryController.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsResourceQueryMatchjs">trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryMatch.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsResourceQueryResultjs">trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryResult.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/LayoutTests/ChangeLog        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-04-06  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: Improve filtering in OpenResourceDialog
+        https://bugs.webkit.org/show_bug.cgi?id=155324
+        &lt;rdar://problem/25094504&gt;
+
+        Reviewed by Joseph Pecoraro.
+
+        Add test coverage for ResourceQueryController.
+
+        * inspector/unit-tests/resource-query-controller-expected.txt: Added.
+        * inspector/unit-tests/resource-query-controller.html: Added.
+
</ins><span class="cx"> 2016-04-06  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         jsc-layout-tests.yaml/js/script-tests/regress-141098.js failing on Yosemite Debug after r198989
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestsresourcequerycontrollerexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/unit-tests/resource-query-controller-expected.txt (0 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/resource-query-controller-expected.txt                                (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/resource-query-controller-expected.txt        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -0,0 +1,214 @@
</span><ins>+Testing WebInspector.ResourceQueryController.
+
+
+== Running test suite: ResourceQueryController
+-- Running test case: FindSpecialCharacterIndices
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+PASS: Result should match expected special indices.
+
+-- Running test case: ExecuteQueryAgainstNoResources
+PASS: Should return no results.
+
+-- Running test case: ExecuteWhitespaceQueryOrEmptyQuery
+PASS: Whitespace query should return no results.
+PASS: Whitespace query should return no results.
+PASS: Whitespace query should return no results.
+PASS: Whitespace query should return no results.
+PASS: Empty query should return no results.
+
+-- Running test case: ExecuteQueryContainingWhitespace
+PASS: Should match one result.
+PASS: Should match one result.
+PASS: Should match one result.
+PASS: Should match one result.
+PASS: Should match one result.
+
+-- Running test case: ExecuteQueryMatchNone
+PASS: Query &quot;abcde&quot; shouldn't match &quot;abcd&quot;.
+PASS: Query &quot;abcd-&quot; shouldn't match &quot;abcde&quot;.
+PASS: Query &quot;abcde&quot; shouldn't match &quot;abced&quot;.
+
+-- Running test case: ExecuteQueryMatchesExpectedCharacters
+PASS: Query &quot;abcd&quot; should match &quot;abcd&quot; in &quot;abcde&quot;.
+PASS: Query &quot; abcd&quot; should match &quot;abcd&quot; in &quot;abcde&quot;.
+PASS: Query &quot;abcd &quot; should match &quot;abcd&quot; in &quot;abcde&quot;.
+PASS: Query &quot;a b c d&quot; should match &quot;abcd&quot; in &quot;abcde&quot;.
+PASS: Query &quot;a-bcde&quot; should match &quot;a    - bcde&quot; in &quot;abcde-abcde&quot;.
+PASS: Query &quot;abcde&quot; should match &quot;A B C D E&quot; in &quot;AaBbCcDdEe&quot;.
+PASS: Query &quot;abcde&quot; should match &quot;A   B  C De&quot; in &quot;AbcdBcdCdDe&quot;.
+PASS: Query &quot;abcdex&quot; should match &quot;A B C d ex&quot; in &quot;AxBxCxdxexDxyxEF&quot;.
+PASS: Query &quot;bc&quot; should match &quot; bC&quot; in &quot;abCd&quot;.
+
+-- Running test case: ExecuteQueryShouldIgnoreCase
+All case permutations of query &quot;abcd&quot; should match &quot;abcd&quot; in &quot;abcde&quot;.
+PASS: Permutation &quot;abcd&quot;.
+PASS: Permutation &quot;Abcd&quot;.
+PASS: Permutation &quot;aBcd&quot;.
+PASS: Permutation &quot;ABcd&quot;.
+PASS: Permutation &quot;abCd&quot;.
+PASS: Permutation &quot;AbCd&quot;.
+PASS: Permutation &quot;aBCd&quot;.
+PASS: Permutation &quot;ABCd&quot;.
+PASS: Permutation &quot;abcD&quot;.
+PASS: Permutation &quot;AbcD&quot;.
+PASS: Permutation &quot;aBcD&quot;.
+PASS: Permutation &quot;ABcD&quot;.
+PASS: Permutation &quot;abCD&quot;.
+PASS: Permutation &quot;AbCD&quot;.
+PASS: Permutation &quot;aBCD&quot;.
+PASS: Permutation &quot;ABCD&quot;.
+All case permutations of query &quot;abcde&quot; should match &quot;A B C D E&quot; in &quot;AaBbCcDdEe&quot;.
+PASS: Permutation &quot;abcde&quot;.
+PASS: Permutation &quot;Abcde&quot;.
+PASS: Permutation &quot;aBcde&quot;.
+PASS: Permutation &quot;ABcde&quot;.
+PASS: Permutation &quot;abCde&quot;.
+PASS: Permutation &quot;AbCde&quot;.
+PASS: Permutation &quot;aBCde&quot;.
+PASS: Permutation &quot;ABCde&quot;.
+PASS: Permutation &quot;abcDe&quot;.
+PASS: Permutation &quot;AbcDe&quot;.
+PASS: Permutation &quot;aBcDe&quot;.
+PASS: Permutation &quot;ABcDe&quot;.
+PASS: Permutation &quot;abCDe&quot;.
+PASS: Permutation &quot;AbCDe&quot;.
+PASS: Permutation &quot;aBCDe&quot;.
+PASS: Permutation &quot;ABCDe&quot;.
+PASS: Permutation &quot;abcdE&quot;.
+PASS: Permutation &quot;AbcdE&quot;.
+PASS: Permutation &quot;aBcdE&quot;.
+PASS: Permutation &quot;ABcdE&quot;.
+PASS: Permutation &quot;abCdE&quot;.
+PASS: Permutation &quot;AbCdE&quot;.
+PASS: Permutation &quot;aBCdE&quot;.
+PASS: Permutation &quot;ABCdE&quot;.
+PASS: Permutation &quot;abcDE&quot;.
+PASS: Permutation &quot;AbcDE&quot;.
+PASS: Permutation &quot;aBcDE&quot;.
+PASS: Permutation &quot;ABcDE&quot;.
+PASS: Permutation &quot;abCDE&quot;.
+PASS: Permutation &quot;AbCDE&quot;.
+PASS: Permutation &quot;aBCDE&quot;.
+PASS: Permutation &quot;ABCDE&quot;.
+All case permutations of query &quot;abcde&quot; should match &quot;A   B  C De&quot; in &quot;AbcdBcdCdDe&quot;.
+PASS: Permutation &quot;abcde&quot;.
+PASS: Permutation &quot;Abcde&quot;.
+PASS: Permutation &quot;aBcde&quot;.
+PASS: Permutation &quot;ABcde&quot;.
+PASS: Permutation &quot;abCde&quot;.
+PASS: Permutation &quot;AbCde&quot;.
+PASS: Permutation &quot;aBCde&quot;.
+PASS: Permutation &quot;ABCde&quot;.
+PASS: Permutation &quot;abcDe&quot;.
+PASS: Permutation &quot;AbcDe&quot;.
+PASS: Permutation &quot;aBcDe&quot;.
+PASS: Permutation &quot;ABcDe&quot;.
+PASS: Permutation &quot;abCDe&quot;.
+PASS: Permutation &quot;AbCDe&quot;.
+PASS: Permutation &quot;aBCDe&quot;.
+PASS: Permutation &quot;ABCDe&quot;.
+PASS: Permutation &quot;abcdE&quot;.
+PASS: Permutation &quot;AbcdE&quot;.
+PASS: Permutation &quot;aBcdE&quot;.
+PASS: Permutation &quot;ABcdE&quot;.
+PASS: Permutation &quot;abCdE&quot;.
+PASS: Permutation &quot;AbCdE&quot;.
+PASS: Permutation &quot;aBCdE&quot;.
+PASS: Permutation &quot;ABCdE&quot;.
+PASS: Permutation &quot;abcDE&quot;.
+PASS: Permutation &quot;AbcDE&quot;.
+PASS: Permutation &quot;aBcDE&quot;.
+PASS: Permutation &quot;ABcDE&quot;.
+PASS: Permutation &quot;abCDE&quot;.
+PASS: Permutation &quot;AbCDE&quot;.
+PASS: Permutation &quot;aBCDE&quot;.
+PASS: Permutation &quot;ABCDE&quot;.
+All case permutations of query &quot;abcdex&quot; should match &quot;A B C d ex&quot; in &quot;AxBxCxdxexDxyxEF&quot;.
+PASS: Permutation &quot;abcdex&quot;.
+PASS: Permutation &quot;Abcdex&quot;.
+PASS: Permutation &quot;aBcdex&quot;.
+PASS: Permutation &quot;ABcdex&quot;.
+PASS: Permutation &quot;abCdex&quot;.
+PASS: Permutation &quot;AbCdex&quot;.
+PASS: Permutation &quot;aBCdex&quot;.
+PASS: Permutation &quot;ABCdex&quot;.
+PASS: Permutation &quot;abcDex&quot;.
+PASS: Permutation &quot;AbcDex&quot;.
+PASS: Permutation &quot;aBcDex&quot;.
+PASS: Permutation &quot;ABcDex&quot;.
+PASS: Permutation &quot;abCDex&quot;.
+PASS: Permutation &quot;AbCDex&quot;.
+PASS: Permutation &quot;aBCDex&quot;.
+PASS: Permutation &quot;ABCDex&quot;.
+PASS: Permutation &quot;abcdEx&quot;.
+PASS: Permutation &quot;AbcdEx&quot;.
+PASS: Permutation &quot;aBcdEx&quot;.
+PASS: Permutation &quot;ABcdEx&quot;.
+PASS: Permutation &quot;abCdEx&quot;.
+PASS: Permutation &quot;AbCdEx&quot;.
+PASS: Permutation &quot;aBCdEx&quot;.
+PASS: Permutation &quot;ABCdEx&quot;.
+PASS: Permutation &quot;abcDEx&quot;.
+PASS: Permutation &quot;AbcDEx&quot;.
+PASS: Permutation &quot;aBcDEx&quot;.
+PASS: Permutation &quot;ABcDEx&quot;.
+PASS: Permutation &quot;abCDEx&quot;.
+PASS: Permutation &quot;AbCDEx&quot;.
+PASS: Permutation &quot;aBCDEx&quot;.
+PASS: Permutation &quot;ABCDEx&quot;.
+PASS: Permutation &quot;abcdeX&quot;.
+PASS: Permutation &quot;AbcdeX&quot;.
+PASS: Permutation &quot;aBcdeX&quot;.
+PASS: Permutation &quot;ABcdeX&quot;.
+PASS: Permutation &quot;abCdeX&quot;.
+PASS: Permutation &quot;AbCdeX&quot;.
+PASS: Permutation &quot;aBCdeX&quot;.
+PASS: Permutation &quot;ABCdeX&quot;.
+PASS: Permutation &quot;abcDeX&quot;.
+PASS: Permutation &quot;AbcDeX&quot;.
+PASS: Permutation &quot;aBcDeX&quot;.
+PASS: Permutation &quot;ABcDeX&quot;.
+PASS: Permutation &quot;abCDeX&quot;.
+PASS: Permutation &quot;AbCDeX&quot;.
+PASS: Permutation &quot;aBCDeX&quot;.
+PASS: Permutation &quot;ABCDeX&quot;.
+PASS: Permutation &quot;abcdEX&quot;.
+PASS: Permutation &quot;AbcdEX&quot;.
+PASS: Permutation &quot;aBcdEX&quot;.
+PASS: Permutation &quot;ABcdEX&quot;.
+PASS: Permutation &quot;abCdEX&quot;.
+PASS: Permutation &quot;AbCdEX&quot;.
+PASS: Permutation &quot;aBCdEX&quot;.
+PASS: Permutation &quot;ABCdEX&quot;.
+PASS: Permutation &quot;abcDEX&quot;.
+PASS: Permutation &quot;AbcDEX&quot;.
+PASS: Permutation &quot;aBcDEX&quot;.
+PASS: Permutation &quot;ABcDEX&quot;.
+PASS: Permutation &quot;abCDEX&quot;.
+PASS: Permutation &quot;AbCDEX&quot;.
+PASS: Permutation &quot;aBCDEX&quot;.
+PASS: Permutation &quot;ABCDEX&quot;.
+All case permutations of query &quot;bc&quot; should match &quot; bC&quot; in &quot;abCd&quot;.
+PASS: Permutation &quot;bc&quot;.
+PASS: Permutation &quot;Bc&quot;.
+PASS: Permutation &quot;bC&quot;.
+PASS: Permutation &quot;BC&quot;.
+
+-- Running test case: ExecuteQueryGeneralRankings
+PASS: Results should be ranked by descending relevancy.
+
+-- Running test case: ExecuteQueryPositionRankings
+PASS: Results should be ranked by descending relevancy.
+
+-- Running test case: GetMatchingTextRanges
+PASS: Result TextRanges should match the expected ranges.
+PASS: Result TextRanges should match the expected ranges.
+PASS: Result TextRanges should match the expected ranges.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorunittestsresourcequerycontrollerhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/unit-tests/resource-query-controller.html (0 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/unit-tests/resource-query-controller.html                                (rev 0)
+++ trunk/LayoutTests/inspector/unit-tests/resource-query-controller.html        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -0,0 +1,328 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../http/tests/inspector/resources/inspector-test.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+function test()
+{
+    let suite = InspectorTest.createSyncSuite(&quot;ResourceQueryController&quot;);
+
+    suite.addTestCase({
+        name: &quot;FindSpecialCharacterIndices&quot;,
+        description: &quot;Should correctly find special filename characters.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            let tests = [
+                {
+                    filename: &quot;Abcd&quot;,
+                    expected: &quot;^&quot;
+                },
+                {
+                    filename: &quot;ABCDE&quot;,
+                    expected: &quot;^&quot;
+                },
+                {
+                    filename: &quot;abcdef&quot;,
+                    expected: &quot;^&quot;,
+                },
+                {
+                    filename: &quot;abc-def&quot;,
+                    expected: &quot;^  ^^&quot;,
+                },
+                {
+                    filename: &quot;abc---def&quot;,
+                    expected: &quot;^  ^^^^&quot;,
+                },
+                {
+                    filename: &quot;a-bc_de.f&quot;,
+                    expected: &quot;^^^ ^^ ^^&quot;,
+                },
+                {
+                    filename: &quot;AxBxCxDxExFx&quot;,
+                    expected: &quot;^ ^ ^ ^ ^ ^&quot;,
+                },
+                {
+                    filename: &quot;ab-c_d.ef&quot;,
+                    expected: &quot;^ ^^^^^^&quot;,
+                },
+                {
+                    filename: &quot;AxBxCxdxexDxyxEF&quot;,
+                    expected: &quot;^ ^ ^     ^   ^&quot;,
+                },
+            ];
+
+            function createSpecialMask(filename, specialIndices) {
+                let mask = &quot; &quot;.repeat(filename.length);
+                specialIndices.forEach((index) =&gt; {
+                    mask = mask.substr(0, index) + &quot;^&quot; + mask.substr(index + 1);
+                });
+                return mask.trim();
+            }
+
+            for (let {filename, expected} of tests) {
+                let actual = createSpecialMask(filename, matcher._findSpecialCharacterIndices(filename));
+                InspectorTest.expectThat(actual === expected, &quot;Result should match expected special indices.&quot;);
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryAgainstNoResources&quot;,
+        description: &quot;Should return no results if no resources were added to the controller.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            let results = matcher.executeQuery(&quot;abcde&quot;);
+            InspectorTest.expectThat(!results.length, &quot;Should return no results.&quot;)
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteWhitespaceQueryOrEmptyQuery&quot;,
+        description: &quot;Empty queries and queries containing only whitespace should return no results.&quot;,
+        test: function() {
+            const whitespaceCharacters = &quot; \t\r\n&quot;;
+            let matcher = new WebInspector.ResourceQueryController;
+            matcher.addResource(new WebInspector.Resource(&quot;abcde&quot;));
+
+            for (let query of whitespaceCharacters) {
+                let results = matcher.executeQuery(query);
+                InspectorTest.expectThat(!results.length, &quot;Whitespace query should return no results.&quot;);
+            }
+
+            let results = matcher.executeQuery(&quot;&quot;);
+            InspectorTest.expectThat(!results.length, &quot;Empty query should return no results.&quot;);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryContainingWhitespace&quot;,
+        description: &quot;Whitespace within a query should be ignored.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            matcher.addResource(new WebInspector.Resource(&quot;abcde&quot;));
+
+            for (let query of [&quot; abcde&quot;, &quot;abcde &quot;, &quot; abcde &quot;, &quot;a b c d e&quot;, &quot;a  b  c  d  e&quot;]) {
+                let results = matcher.executeQuery(query);
+                InspectorTest.expectThat(results.length === 1, &quot;Should match one result.&quot;);
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryMatchNone&quot;,
+        description: &quot;Should not find a match.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            let tests = [
+                {query: &quot;abcde&quot;, filename: &quot;abcd&quot;},
+                {query: &quot;abcd-&quot;, filename: &quot;abcde&quot;},
+                {query: &quot;abcde&quot;, filename: &quot;abced&quot;},
+            ];
+
+            for (let {query, filename} of tests) {
+                matcher.reset();
+                matcher.addResource(new WebInspector.Resource(filename));
+                let results = matcher.executeQuery(query);
+                InspectorTest.expectThat(!results.length, `Query &quot;${query}&quot; shouldn't match &quot;${filename}&quot;.`);
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryMatchesExpectedCharacters&quot;,
+        description: &quot;Should match the expected query characters.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            let tests = [
+                {
+                    query: &quot;abcd&quot;,
+                    filename: &quot;abcde&quot;,
+                    expected: &quot;abcd&quot;
+                },
+                {
+                    query: &quot; abcd&quot;,
+                    filename: &quot;abcde&quot;,
+                    expected: &quot;abcd&quot;
+                },
+                {
+                    query: &quot;abcd &quot;,
+                    filename: &quot;abcde&quot;,
+                    expected: &quot;abcd&quot;
+                },
+                {
+                    query: &quot;a b c d&quot;,
+                    filename: &quot;abcde&quot;,
+                    expected: &quot;abcd&quot;
+                },
+                {
+                    query: &quot;a-bcde&quot;,
+                    filename: &quot;abcde-abcde&quot;,
+                    expected: &quot;a    - bcde&quot;
+                },
+                {
+                    query: &quot;abcde&quot;,
+                    filename: &quot;AaBbCcDdEe&quot;,
+                    expected: &quot;A B C D E&quot;
+                },
+                {
+                    query: &quot;abcde&quot;,
+                    filename: &quot;AbcdBcdCdDe&quot;,
+                    expected: &quot;A   B  C De&quot;
+                },
+                {
+                    query: &quot;abcdex&quot;,
+                    filename: &quot;AxBxCxdxexDxyxEF&quot;,
+                    expected: &quot;A B C d ex&quot;
+                },
+                {
+                    query: &quot;bc&quot;,
+                    filename: &quot;abCd&quot;,
+                    expected: &quot; bC&quot;
+                },
+            ];
+
+            for (let {query, filename, expected} of tests) {
+                matcher.reset();
+                matcher.addResource(new WebInspector.Resource(filename));
+
+                let results = matcher.executeQuery(query);
+                InspectorTest.assert(results.length === 1, &quot;Should return exactly one match.&quot;);
+                let actual = results[0].__test_createMatchesMask();
+                InspectorTest.expectThat(actual === expected, `Query &quot;${query}&quot; should match &quot;${expected}&quot; in &quot;${filename}&quot;.`);
+            }
+        }
+    });
+
+    // Generator for creating a sequence of case permutations for a string.
+    // Example: &quot;xx&quot; =&gt; [&quot;xx&quot;, &quot;Xx&quot;, &quot;xX&quot;, &quot;XX&quot;]
+    function *casePermutations(string) {
+        let permutationCount = Math.pow(2, string.length);
+        InspectorTest.assert(permutationCount !== Infinity, &quot;String length exceeds permutations limit.&quot;);
+        if (permutationCount === Infinity)
+            return;
+
+        let index = 0;
+        while (index &lt; permutationCount) {
+            let result = &quot;&quot;;
+            for (let i = 0; i &lt; string.length; ++i)
+                result += (index &amp; (1 &lt;&lt; i)) ? string[i].toUpperCase() : string[i].toLowerCase();
+
+            index++;
+            yield result;
+        }
+
+        return;
+    }
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryShouldIgnoreCase&quot;,
+        description: &quot;Queries that differ only in case should return identical results.&quot;,
+        test: function() {
+            let matcher = new WebInspector.ResourceQueryController;
+            let tests = [
+                {
+                    query: &quot;abcd&quot;,
+                    filename: &quot;abcde&quot;,
+                    expected: &quot;abcd&quot;
+                },
+                {
+                    query: &quot;abcde&quot;,
+                    filename: &quot;AaBbCcDdEe&quot;,
+                    expected: &quot;A B C D E&quot;
+                },
+                {
+                    query: &quot;abcde&quot;,
+                    filename: &quot;AbcdBcdCdDe&quot;,
+                    expected: &quot;A   B  C De&quot;
+                },
+                {
+                    query: &quot;abcdex&quot;,
+                    filename: &quot;AxBxCxdxexDxyxEF&quot;,
+                    expected: &quot;A B C d ex&quot;
+                },
+                {
+                    query: &quot;bc&quot;,
+                    filename: &quot;abCd&quot;,
+                    expected: &quot; bC&quot;
+                },
+            ];
+
+            for (let {query, filename, expected} of tests) {
+                InspectorTest.log(`All case permutations of query &quot;${query}&quot; should match &quot;${expected}&quot; in &quot;${filename}&quot;.`);
+
+                matcher.reset();
+                matcher.addResource(new WebInspector.Resource(filename));
+
+                for (let queryPermutation of casePermutations(query)) {
+                    let results = matcher.executeQuery(queryPermutation);
+                    let actual = results.length === 1 ? results[0].__test_createMatchesMask() : &quot;&quot;;
+                    InspectorTest.expectThat(expected === actual, `Permutation &quot;${queryPermutation}&quot;.`);
+                }
+            }
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryGeneralRankings&quot;,
+        description: &quot;Check that query results are ranked by descending relevance.&quot;,
+        test: function() {
+            let filenames = [&quot;AxBxCxDxEx&quot;, &quot;AbCdE&quot;, &quot;AbcDe&quot;, &quot;AxbcDe&quot;, &quot;AxbxcDe&quot;, &quot;abcde&quot;, &quot;xabcde&quot;]; // Filenames in order of descending rank.
+            let matcher = new WebInspector.ResourceQueryController;
+            filenames.forEach((filename) =&gt; matcher.addResource(new WebInspector.Resource(filename)));
+
+            let query = &quot;abcde&quot;;
+            let results = matcher.executeQuery(query);
+            let resultFilenames = results.map((filename) =&gt; filename.resource.displayName);
+            InspectorTest.expectThat(Object.shallowEqual(resultFilenames, filenames), &quot;Results should be ranked by descending relevancy.&quot;);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;ExecuteQueryPositionRankings&quot;,
+        description: &quot;Check that matches close to the beginning of the filename rank higher.&quot;,
+        test: function() {
+            let filenames = [&quot;BxCxDx&quot;, &quot;AxBxCxDx&quot;, &quot;xxxAxxxBxxxCxxxD&quot;, &quot;bcd&quot;, &quot;abcd&quot;]; // Filenames in order of descending rank.
+            let matcher = new WebInspector.ResourceQueryController;
+            filenames.forEach((filename) =&gt; matcher.addResource(new WebInspector.Resource(filename)));
+
+            let query = &quot;bcd&quot;;
+            let results = matcher.executeQuery(query);
+            let resultFilenames = results.map((result) =&gt; result.resource.displayName);
+            InspectorTest.expectThat(Object.shallowEqual(resultFilenames, filenames), &quot;Results should be ranked by descending relevancy.&quot;);
+        }
+    });
+
+    suite.addTestCase({
+        name: &quot;GetMatchingTextRanges&quot;,
+        description: &quot;Check that query result TextRanges are correct.&quot;,
+        test: function() {
+            function textRange(start, end) {
+                return new WebInspector.TextRange(0, start, 0, end);
+            }
+
+            let matcher = new WebInspector.ResourceQueryController;
+            let tests = [
+                {filename: &quot;a&quot;, ranges: []},
+                {filename: &quot;abcde&quot;, ranges: [textRange(0, 5)]},
+                {filename: &quot;AxBxCxDe&quot;, ranges: [textRange(0, 1), textRange(2, 3), textRange(4, 5), textRange(6, 8)]},
+            ];
+
+            for (let {filename, ranges} of tests) {
+                matcher.reset();
+                matcher.addResource(new WebInspector.Resource(filename));
+
+                let results = matcher.executeQuery(&quot;abcde&quot;);
+                let resultTextRanges = results.length ? results[0].matchingTextRanges : [];
+                InspectorTest.expectThat(JSON.stringify(resultTextRanges) === JSON.stringify(ranges), &quot;Result TextRanges should match the expected ranges.&quot;);
+            }
+        }
+    });
+
+    suite.runTestCasesAndFinish();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;runTest()&quot;&gt;
+    &lt;p&gt;Testing WebInspector.ResourceQueryController.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -1,3 +1,132 @@
</span><ins>+2016-04-06  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: Improve filtering in OpenResourceDialog
+        https://bugs.webkit.org/show_bug.cgi?id=155324
+        &lt;rdar://problem/25094504&gt;
+
+        Reviewed by Joseph Pecoraro and Timothy Hatcher.
+
+        * UserInterface/Base/Utilities.js:
+        (value):
+        Added String methods isLowerCase, isUpperCase, removeWhitespace.
+
+        * UserInterface/Controllers/ResourceQueryController.js: Added.
+        (WebInspector.ResourceQueryController):
+        (WebInspector.ResourceQueryController.prototype.addResource):
+        (WebInspector.ResourceQueryController.prototype.removeResource):
+        Add and remove the resources to be queried.
+
+        (WebInspector.ResourceQueryController.prototype.reset):
+        Reset controller state. Current just clears resources.
+
+        (WebInspector.ResourceQueryController.prototype.executeQuery):
+        Executes a query against the list of resources and returns a list of
+        QueryResult objects, with at most one result per resource, ordered by
+        descending rank.
+
+        The query string is stripped of whitespace characters and lowercased
+        before use. Prior to running the query, resources undergo a one-time
+        pre-processing step to locate special characters.
+
+        (WebInspector.ResourceQueryController.prototype._findQueryMatches.pushMatch):
+        (WebInspector.ResourceQueryController.prototype._findQueryMatches.matchNextSpecialCharacter):
+        (WebInspector.ResourceQueryController.prototype._findQueryMatches.backtrack):
+        (WebInspector.ResourceQueryController.prototype._findQueryMatches):
+        Returns a list of query matches for a single resource, along with metadata
+        which is used to rank the matches. The algorithm attempts to match the
+        entire query, first comparing each query character against &quot;special&quot; characters
+        in the resource (commonly used filename separators, the first character,
+        and camel-case word boundaries).
+
+        If there are remaining query characters after exhausting special characters,
+        regular characters are matched starting from the last matched special
+        character. Failing that, the algorithm attempts to find a match by backtracking.
+        To backtrack, the last match is discarded and the query position decremented.
+        If a special match is now the last match, matching starts again from the
+        next character in the filename after the match. If a normal match is now
+        the last match, keep discarding until a special match is found or no matches
+        remain. The query fails if no matches remain. For example, consider:
+
+           Query: &quot;abcd&quot;
+           Filename: &quot;AxBcdCx&quot;
+
+        The capital A, B, and C are all special characters, and are successfully
+        matched with the first three query characters. Having exhausted the special
+        characters the &quot;d&quot; at the end of the query is compared with the &quot;x&quot; at
+        the end of the filename, and fails to match. Backtracking then kicks in.
+        The last match, &quot;C&quot;, is discarded and the search position in the query
+        decremented. The search resumes after the next to last match, &quot;B&quot;, and now
+        matches the non-special characters &quot;cd&quot;, yielding the following: &quot;A Bcd  &quot;.
+
+        (WebInspector.ResourceQueryController.prototype._findSpecialCharacterIndices):
+        Pre-processing step for resources. Locates the positions of special
+        characters in the resource filename. Special characters are defined as:
+
+           1. The first character
+           2. Common filename separators, and the character immediately following.
+           3. A capital letter that follows a lowercase character.
+
+        * UserInterface/Models/ResourceQueryMatch.js: Added.
+        Helper class used internally by the controller and QueryResult classes.
+        (WebInspector.ResourceQueryMatch):
+        (WebInspector.ResourceQueryMatch.prototype.get type):
+        (WebInspector.ResourceQueryMatch.prototype.get index):
+        (WebInspector.ResourceQueryMatch.prototype.get queryIndex):
+
+        * UserInterface/Models/ResourceQueryResult.js: Added.
+        Holds a resource that matched the executed query.
+        (WebInspector.ResourceQueryResult):
+        (WebInspector.ResourceQueryResult.prototype.get resource):
+        (WebInspector.ResourceQueryResult.prototype.get rank):
+        Ranking relative to other results returned by the query. Used by
+        the ResourceQueryController to sort results.
+
+        (WebInspector.ResourceQueryResult.prototype.get matchingTextRanges):
+        Get TextRanges for matching substrings in the resource display name.
+
+        (WebInspector.ResourceQueryResult.prototype._calculateRank):
+        Calculate the rank of the result. Matches are scored based on the type
+        of match (Special vs. Normal), the location of the match within the filename
+        (matches closer to the beginning are scored higher), and whether the match
+        is adjacent to the previous match.
+
+        Values assigned to each ranking criteria are somewhat arbitrary, and may
+        be fine-tuned over time to produce better results.
+
+        (WebInspector.ResourceQueryResult.prototype._createMatchingTextRanges):
+        (WebInspector.ResourceQueryResult.prototype.__test_createMatchesMask):
+        Test API for visualizing matches. For a result returned from the query
+        &quot;abce&quot;, run against a filename &quot;abcde&quot;, the mask is &quot;a c e&quot;.
+
+        * UserInterface/Main.html:
+        * UserInterface/Test.html:
+        New files.
+
+        * UserInterface/Views/Dialog.js:
+        (WebInspector.Dialog.prototype.dismiss):
+        (WebInspector.Dialog.prototype.didDismissDialog):
+        Add hook for subclasses to perform actions after on dialog dismissal.
+
+        * UserInterface/Views/OpenResourceDialog.js:
+        (WebInspector.OpenResourceDialog):
+        (WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline.createHighlightedTitleFragment):
+        (WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline):
+        Add tree elements for each QueryResult returned by the last query, creating
+        titles with contiguous matching query characters wrapped in highlight spans.
+
+        (WebInspector.OpenResourceDialog.prototype.didDismissDialog):
+        Clear resources from the ResourceQueryController.
+        (WebInspector.OpenResourceDialog.prototype.didPresentDialog):
+        Add resources to the ResourceQueryController.
+        (WebInspector.OpenResourceDialog.prototype._updateFilter):
+        Execute the filter text as a resource query.
+
+        * UserInterface/Views/TreeOutline.css:
+        (.tree-outline.large .item .titles): Deleted.
+        Line height too small, hid the bottom border of highlighted matches in
+        tree element title spans. Removing the style had no negative visual impact
+        on the Quick Open or Timelines tree outlines (the only &quot;large&quot; trees).
+
</ins><span class="cx"> 2016-04-05  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Do not create CodeMirror color/gradient markers in JavaScript resources
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceBaseUtilitiesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -484,6 +484,22 @@
</span><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><ins>+Object.defineProperty(String.prototype, &quot;isLowerCase&quot;,
+{
+    value: function()
+    {
+        return String(this) === this.toLowerCase();
+    }
+});
+
+Object.defineProperty(String.prototype, &quot;isUpperCase&quot;,
+{
+    value: function()
+    {
+        return String(this) === this.toUpperCase();
+    }
+});
+
</ins><span class="cx"> Object.defineProperty(String.prototype, &quot;trimMiddle&quot;,
</span><span class="cx"> {
</span><span class="cx">     value: function(maxLength)
</span><span class="lines">@@ -532,6 +548,14 @@
</span><span class="cx">     }
</span><span class="cx"> });
</span><span class="cx"> 
</span><ins>+Object.defineProperty(String.prototype, &quot;removeWhitespace&quot;,
+{
+    value: function()
+    {
+        return this.replace(/[\s\xA0]+/g, &quot;&quot;);
+    }
+});
+
</ins><span class="cx"> Object.defineProperty(String.prototype, &quot;escapeCharacters&quot;,
</span><span class="cx"> {
</span><span class="cx">     value: function(chars)
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceControllersResourceQueryControllerjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Controllers/ResourceQueryController.js (0 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Controllers/ResourceQueryController.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/ResourceQueryController.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -0,0 +1,194 @@
</span><ins>+/*
+ * Copyright (C) 2016 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.
+ */
+
+WebInspector.ResourceQueryController = class ResourceQueryController extends WebInspector.Object
+{
+    constructor()
+    {
+        super();
+
+        this._resourceDataMap = new Map;
+    }
+
+    // Public
+
+    addResource(resource)
+    {
+        this._resourceDataMap.set(resource, {});
+    }
+
+    removeResource(resource)
+    {
+        this._resourceDataMap.delete(resource);
+    }
+
+    reset()
+    {
+        this._resourceDataMap.clear();
+    }
+
+    executeQuery(query)
+    {
+        if (!query || !this._resourceDataMap.size)
+            return [];
+
+        query = query.removeWhitespace().toLowerCase();
+
+        let results = [];
+        for (let [resource, cachedData] of this._resourceDataMap) {
+            if (!cachedData.searchString) {
+                let displayName = resource.displayName;
+                cachedData.searchString = displayName.toLowerCase();
+                cachedData.specialCharacterIndices = this._findSpecialCharacterIndices(displayName);
+            }
+
+            let matches = this._findQueryMatches(query, cachedData.searchString, cachedData.specialCharacterIndices);
+            if (matches.length)
+                results.push(new WebInspector.ResourceQueryResult(resource, matches));
+        }
+
+        // Resources are sorted in descending order by rank. Resources of equal
+        // rank are sorted by display name.
+        return results.sort((a, b) =&gt; {
+            if (a.rank === b.rank)
+                return a.resource.displayName.localeCompare(b.resource.displayName);
+            return b.rank - a.rank;
+        });
+    }
+
+    // Private
+
+    _findQueryMatches(query, searchString, specialCharacterIndices)
+    {
+        let matches = [];
+        let queryIndex = 0;
+        let searchIndex = 0;
+        let specialIndex = 0;
+        let deadBranches = new Array(query.length).fill(Infinity);
+        let type = WebInspector.ResourceQueryMatch.Type.Special;
+
+        function pushMatch(index)
+        {
+            matches.push(new WebInspector.ResourceQueryMatch(type, index, queryIndex));
+            searchIndex = index + 1;
+            queryIndex++;
+        }
+
+        function matchNextSpecialCharacter()
+        {
+            if (specialIndex &gt;= specialCharacterIndices.length)
+                return false;
+
+            let originalSpecialIndex = specialIndex;
+            while (specialIndex &lt; specialCharacterIndices.length) {
+                // Normal character matching can move past special characters,
+                // so advance the special character index if it's before the
+                // current search string position.
+                let index = specialCharacterIndices[specialIndex++];
+                if (index &lt; searchIndex)
+                    continue;
+
+                if (query[queryIndex] === searchString[index]) {
+                    pushMatch(index);
+                    return true;
+                }
+            }
+
+            specialIndex = originalSpecialIndex;
+            return false;
+        }
+
+        function backtrack()
+        {
+            while (matches.length) {
+                queryIndex--;
+
+                let lastMatch = matches.pop();
+                if (lastMatch.type !== WebInspector.ResourceQueryMatch.Type.Special)
+                    continue;
+
+                deadBranches[lastMatch.queryIndex] = lastMatch.index - 1;
+                searchIndex = matches.lastValue ? matches.lastValue.index + 1 : 0;
+                return true;
+            }
+
+            return false;
+        }
+
+        while (queryIndex &lt; query.length &amp;&amp; searchIndex &lt; searchString.length) {
+            if (type === WebInspector.ResourceQueryMatch.Type.Special &amp;&amp; !matchNextSpecialCharacter())
+                type = WebInspector.ResourceQueryMatch.Type.Normal;
+
+            if (type === WebInspector.ResourceQueryMatch.Type.Normal) {
+                let index = searchString.indexOf(query[queryIndex], searchIndex);
+                if (index &gt;= 0 &amp;&amp; index &lt; deadBranches[queryIndex]) {
+                    pushMatch(index);
+                    type = WebInspector.ResourceQueryMatch.Type.Special;
+                } else if (!backtrack())
+                    return [];
+            }
+        }
+
+        if (queryIndex &lt; query.length)
+            return [];
+
+        return matches;
+    }
+
+    _findSpecialCharacterIndices(string)
+    {
+        if (!string.length)
+            return [];
+
+        const filenameSeparators = &quot;_.-&quot;;
+
+        // Special characters include the following:
+        // 1. The first character.
+        // 2. Uppercase characters that follow a lowercase letter.
+        // 3. Filename separators and the first character following the separator.
+        let indices = [0];
+
+        for (let i = 1; i &lt; string.length; ++i) {
+            let character = string[i];
+            let isSpecial = false;
+
+            if (filenameSeparators.includes(character))
+                isSpecial = true;
+            else {
+                let previousCharacter = string[i - 1];
+                let previousCharacterIsSeparator = filenameSeparators.includes(previousCharacter);
+                if (previousCharacterIsSeparator)
+                    isSpecial = true;
+                else if (character.isUpperCase() &amp;&amp; previousCharacter.isLowerCase())
+                    isSpecial = true;
+            }
+
+            if (isSpecial)
+                indices.push(i);
+        }
+
+        return indices;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -351,6 +351,8 @@
</span><span class="cx">     &lt;script src=&quot;Models/ReplaySessionSegment.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Resource.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ResourceCollection.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Models/ResourceQueryMatch.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/ResourceQueryResult.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Models/ResourceTimelineRecord.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Revision.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ScopeChainNode.js&quot;&gt;&lt;/script&gt;
</span><span class="lines">@@ -690,6 +692,7 @@
</span><span class="cx">     &lt;script src=&quot;Controllers/MemoryManager.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Controllers/ProbeManager.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Controllers/ReplayManager.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Controllers/ResourceQueryController.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Controllers/RuntimeManager.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Controllers/SourceMapManager.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Controllers/StorageManager.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsResourceQueryMatchjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryMatch.js (0 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryMatch.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryMatch.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -0,0 +1,48 @@
</span><ins>+/*
+ * Copyright (C) 2016 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.
+ */
+
+WebInspector.ResourceQueryMatch = class QueryMatch extends WebInspector.Object
+{
+    constructor(type, index, queryIndex)
+    {
+        super();
+
+        this._type = type;
+        this._index = index;
+        this._queryIndex = queryIndex;
+        this._rank = undefined;
+    }
+
+    // Public
+
+    get type() { return this._type; }
+    get index() { return this._index; }
+    get queryIndex() { return this._queryIndex; }
+};
+
+WebInspector.ResourceQueryMatch.Type = {
+    Normal: Symbol(&quot;normal&quot;),
+    Special: Symbol(&quot;special&quot;)
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsResourceQueryResultjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryResult.js (0 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryResult.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/ResourceQueryResult.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -0,0 +1,126 @@
</span><ins>+/*
+ * Copyright (C) 2016 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.
+ */
+
+WebInspector.ResourceQueryResult = class QueryResult extends WebInspector.Object
+{
+    constructor(resource, matches)
+    {
+        console.assert(matches.length, &quot;Query matches list can't be empty.&quot;);
+
+        super();
+
+        this._resource = resource;
+        this._matches = matches;
+    }
+
+    // Public
+
+    get resource() { return this._resource; }
+
+    get rank()
+    {
+        if (this._rank === undefined)
+            this._calculateRank();
+
+        return this._rank;
+    }
+
+    get matchingTextRanges()
+    {
+        if (!this._matchingTextRanges)
+            this._matchingTextRanges = this._createMatchingTextRanges();
+
+        return this._matchingTextRanges;
+    }
+
+    // Private
+
+    _calculateRank()
+    {
+        const specialWeight = 50;
+        const normalWeight = 10;
+        const consecutiveMatchWeight = 5;
+
+        this._rank = 0;
+
+        let previousMatch = null;
+        for (let match of this._matches) {
+            this._rank += match.type === WebInspector.ResourceQueryMatch.Type.Special ? specialWeight : normalWeight;
+            if (previousMatch &amp;&amp; previousMatch.index === match.index - 1)
+                this._rank += consecutiveMatchWeight;
+
+            previousMatch = match;
+
+            // The match index is deducted from the total rank, so matches that
+            // occur closer to the beginning of the string are ranked higher.
+            this._rank -= match.index;
+        }
+    }
+
+    _createMatchingTextRanges()
+    {
+        if (!this._matches.length)
+            return [];
+
+        let ranges = [];
+        let startIndex = this._matches[0].index;
+        let endIndex = startIndex;
+        for (let i = 1; i &lt; this._matches.length; ++i) {
+            let match = this._matches[i];
+
+            // Increment endIndex for consecutive match.
+            if (match.index === endIndex + 1) {
+                endIndex++;
+                continue;
+            }
+
+            // Begin a new range when a gap between this match and the previous match is found.
+            ranges.push(new WebInspector.TextRange(0, startIndex, 0, endIndex + 1));
+            startIndex = match.index;
+            endIndex = startIndex;
+        }
+
+        ranges.push(new WebInspector.TextRange(0, startIndex, 0, endIndex + 1));
+        return ranges;
+    }
+
+    // Testing
+
+    __test_createMatchesMask()
+    {
+        let filename = this._resource.displayName;
+        let lastIndex = -1;
+        let result = &quot;&quot;;
+
+        for (let match of this._matches) {
+            let gap = &quot; &quot;.repeat(match.index - lastIndex - 1);
+            result += gap;
+            result += filename[match.index];
+            lastIndex = match.index;
+        }
+
+        return result;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceTesthtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Test.html (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Test.html        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Test.html        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -142,6 +142,8 @@
</span><span class="cx">     &lt;script src=&quot;Models/ReplaySessionSegment.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Resource.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ResourceCollection.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Models/ResourceQueryMatch.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Models/ResourceQueryResult.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Models/ResourceTimelineRecord.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/Revision.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Models/ScopeChainNode.js&quot;&gt;&lt;/script&gt;
</span><span class="lines">@@ -180,6 +182,7 @@
</span><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Controllers/Formatter.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Controllers/FormatterContentBuilder.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Controllers/ResourceQueryController.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/CodeMirrorAdditions.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/CodeMirrorFormatters.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDialogjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Dialog.js (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/Dialog.js        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Dialog.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -82,10 +82,17 @@
</span><span class="cx">             this._delegate.dialogWasDismissed(this);
</span><span class="cx"> 
</span><span class="cx">         this._dismissing = false;
</span><ins>+
+        this.didDismissDialog();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Protected
</span><span class="cx"> 
</span><ins>+    didDismissDialog()
+    {
+        // Implemented by subclasses.
+    }
+
</ins><span class="cx">     didPresetDialog()
</span><span class="cx">     {
</span><span class="cx">         // Implemented by subclasses.
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsOpenResourceDialogjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -58,14 +58,35 @@
</span><span class="cx"> 
</span><span class="cx">         this.element.appendChild(this._treeOutline.element);
</span><span class="cx"> 
</span><del>-        this._resources = [];
-        this._filteredResources = [];
</del><ins>+        this._queryController = new WebInspector.ResourceQueryController;
+        this._filteredResults = [];
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     _populateResourceTreeOutline()
</span><span class="cx">     {
</span><ins>+        function createHighlightedTitleFragment(title, highlightTextRanges)
+        {
+            let titleFragment = document.createDocumentFragment();
+            let lastIndex = 0;
+            for (let textRange of highlightTextRanges) {
+                if (textRange.startColumn &gt; lastIndex)
+                    titleFragment.append(title.substring(lastIndex, textRange.startColumn));
+
+                let highlightSpan = document.createElement(&quot;span&quot;);
+                highlightSpan.classList.add(&quot;highlighted&quot;);
+                highlightSpan.append(title.substring(textRange.startColumn, textRange.endColumn));
+                titleFragment.append(highlightSpan);
+                lastIndex = textRange.endColumn;
+            }
+
+            if (lastIndex &lt; title.length)
+                titleFragment.append(title.substring(lastIndex, title.length));
+
+            return titleFragment;
+        }
+
</ins><span class="cx">         function createTreeElement(representedObject)
</span><span class="cx">         {
</span><span class="cx">             let treeElement = null;
</span><span class="lines">@@ -80,14 +101,16 @@
</span><span class="cx">             return treeElement;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        for (let resource of this._filteredResources) {
</del><ins>+        for (let result of this._filteredResults) {
+            let resource = result.resource;
+            if (this._treeOutline.findTreeElement(resource))
+                continue;
+
</ins><span class="cx">             let treeElement = createTreeElement(resource);
</span><span class="cx">             if (!treeElement)
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            if (this._treeOutline.findTreeElement(resource))
-                continue;
-
</del><ins>+            treeElement.mainTitle = createHighlightedTitleFragment(resource.displayName, result.matchingTextRanges);
</ins><span class="cx">             this._treeOutline.appendChild(treeElement);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -95,6 +118,11 @@
</span><span class="cx">             this._treeOutline.children[0].select(true, false, true, true);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    didDismissDialog()
+    {
+        this._queryController.reset();
+    }
+
</ins><span class="cx">     didPresentDialog()
</span><span class="cx">     {
</span><span class="cx">         this._inputElement.focus();
</span><span class="lines">@@ -103,11 +131,12 @@
</span><span class="cx">         let frames = [WebInspector.frameResourceManager.mainFrame];
</span><span class="cx">         while (frames.length) {
</span><span class="cx">             let frame = frames.shift();
</span><del>-            for (let resource of frame.resources) {
</del><ins>+            let resources = [frame.mainResource].concat(frame.resources);
+            for (let resource of resources) {
</ins><span class="cx">                 if (!this.representedObjectIsValid(resource))
</span><span class="cx">                     continue;
</span><span class="cx"> 
</span><del>-                this._resources.push(resource);
</del><ins>+                this._queryController.addResource(resource);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             frames = frames.concat(frame.childFrames);
</span><span class="lines">@@ -193,7 +222,7 @@
</span><span class="cx"> 
</span><span class="cx">     _updateFilter()
</span><span class="cx">     {
</span><del>-        this._filteredResources = [];
</del><ins>+        this._filteredResults = [];
</ins><span class="cx">         this._treeOutline.hidden = true;
</span><span class="cx">         this._treeOutline.removeChildren();
</span><span class="cx"> 
</span><span class="lines">@@ -201,28 +230,8 @@
</span><span class="cx">         if (!filterText)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        // FIXME: &lt;https://webkit.org/b/155324&gt; Web Inspector: Improve filtering in OpenResourceDialog
-        let filters = [simpleGlobStringToRegExp(filterText)];
</del><ins>+        this._filteredResults = this._queryController.executeQuery(filterText);
</ins><span class="cx"> 
</span><del>-        for (let resource of this._resources) {
-            for (let i = 0; i &lt; filters.length; ++i) {
-                if (!filters[i].test(resource.displayName))
-                    continue;
-
-                resource.__weight = filters.length - i;
-                this._filteredResources.push(resource);
-                break;
-            }
-        }
-
-        // Sort filtered resources by weight, then alphabetically.
-        this._filteredResources.sort((a, b) =&gt; {
-            if (a.__weight === b.__weight)
-                return a.displayName.localeCompare(b.displayName);
-
-            return b.__weight - a.__weight;
-        });
-
</del><span class="cx">         this._populateResourceTreeOutline();
</span><span class="cx">         if (this._treeOutline.children.length)
</span><span class="cx">             this._treeOutline.hidden = false;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinecss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css (199142 => 199143)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css        2016-04-07 02:07:26 UTC (rev 199142)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css        2016-04-07 02:09:07 UTC (rev 199143)
</span><span class="lines">@@ -183,7 +183,6 @@
</span><span class="cx"> 
</span><span class="cx"> .tree-outline.large .item .titles {
</span><span class="cx">     top: 10px;
</span><del>-    line-height: 11px;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> .tree-outline .item .highlighted {
</span></span></pre>
</div>
</div>

</body>
</html>