Web Inspector: Search: allow DOM searches to be case sensitive
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 16:21:37 +0000 (16:21 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 16:21:37 +0000 (16:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194673
<rdar://problem/48087577>

Reviewed by Timothy Hatcher.

Source/JavaScriptCore:

Since `DOM.performSearch` also searches by selector and XPath, some results may appear
as unexpected. As an example, searching for "BoDy" will still return the <body> as a result,
as although the literal node name ("BODY") didn't match, it did match via selector/XPath.

* inspector/protocol/DOM.json:
Allow `DOM.performSearch` to be case sensitive.

Source/WebCore:

Tests: inspector/dom/dom-search.html
       inspector/dom/dom-search-caseSensitive.html

Since `DOM.performSearch` also searches by selector and XPath, some results may appear
as unexpected. As an example, searching for "BoDy" will still return the <body> as a result,
as although the literal node name ("BODY") didn't match, it did match via selector/XPath.

* inspector/agents/InspectorDOMAgent.h:
* inspector/agents/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::performSearch):

* inspector/InspectorNodeFinder.h:
* inspector/InspectorNodeFinder.cpp:
(WebCore::InspectorNodeFinder::InspectorNodeFinder):
(WebCore::InspectorNodeFinder::searchUsingDOMTreeTraversal):
(WebCore::InspectorNodeFinder::checkEquals): Added.
(WebCore::InspectorNodeFinder::checkContains): Added.
(WebCore::InspectorNodeFinder::checkStartsWith): Added.
(WebCore::InspectorNodeFinder::checkEndsWith): Added.
(WebCore::InspectorNodeFinder::matchesAttribute):
(WebCore::InspectorNodeFinder::matchesElement):
(WebCore::InspectorNodeFinder::searchUsingXPath):
(WebCore::InspectorNodeFinder::searchUsingCSSSelectors):

Source/WebInspectorUI:

* UserInterface/Views/SearchSidebarPanel.js:
(WI.SearchSidebarPanel.prototype.performSearch):

* UserInterface/Views/DOMTreeContentView.js:
(WI.DOMTreeContentView.prototype.performSearch.contextNodesReady):

* UserInterface/Controllers/DOMManager.js:
(WI.DOMManager.prototype.performSearch.callback): Deleted.
(WI.DOMManager.prototype.performSearch): Deleted.
(WI.DOMManager.prototype.searchResult.mycallback): Deleted.
(WI.DOMManager.prototype.searchResult): Deleted.
(WI.DOMManager.prototype.cancelSearch): Deleted.
Drive-by: remove unused code.
LayoutTests:

* inspector/dom/dom-search-caseSensitive.html: Copied from LayoutTests/inspector/dom/dom-search.html.
* inspector/dom/dom-search-caseSensitive-expected.txt: Copied from LayoutTests/inspector/dom/dom-search-expected.txt.
* inspector/dom/dom-search-expected.txt:
* inspector/dom/resources/dom-search-queries.js:
(TestPage.registerInitializer):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243207 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/dom/dom-search-caseSensitive-expected.txt [new file with mode: 0644]
LayoutTests/inspector/dom/dom-search-caseSensitive.html [new file with mode: 0644]
LayoutTests/inspector/dom/dom-search-expected.txt
LayoutTests/inspector/dom/resources/dom-search-queries.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/DOM.json
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorNodeFinder.cpp
Source/WebCore/inspector/InspectorNodeFinder.h
Source/WebCore/inspector/agents/InspectorDOMAgent.cpp
Source/WebCore/inspector/agents/InspectorDOMAgent.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/DOMManager.js
Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js
Source/WebInspectorUI/UserInterface/Views/SearchSidebarPanel.js

index 79d06fa..e040417 100644 (file)
@@ -1,3 +1,17 @@
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Search: allow DOM searches to be case sensitive
+        https://bugs.webkit.org/show_bug.cgi?id=194673
+        <rdar://problem/48087577>
+
+        Reviewed by Timothy Hatcher.
+
+        * inspector/dom/dom-search-caseSensitive.html: Copied from LayoutTests/inspector/dom/dom-search.html.
+        * inspector/dom/dom-search-caseSensitive-expected.txt: Copied from LayoutTests/inspector/dom/dom-search-expected.txt.
+        * inspector/dom/dom-search-expected.txt:
+        * inspector/dom/resources/dom-search-queries.js:
+        (TestPage.registerInitializer):
+
 2019-03-20  Zalan Bujtas  <zalan@apple.com>
 
         Unreviewed test gardening.
diff --git a/LayoutTests/inspector/dom/dom-search-caseSensitive-expected.txt b/LayoutTests/inspector/dom/dom-search-caseSensitive-expected.txt
new file mode 100644 (file)
index 0000000..8fed16d
--- /dev/null
@@ -0,0 +1,115 @@
+Testing DOM.performSearch with no parent node ids.
+
+
+=== Query: "body" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<body" ===
+Count: 0
+=== Query: "body>" ===
+Count: 0
+=== Query: "<body>" ===
+Count: 0
+=== Query: "bOdY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<bOdY" ===
+Count: 0
+=== Query: "bOdY>" ===
+Count: 0
+=== Query: "<bOdY>" ===
+Count: 0
+=== Query: "BODY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<BODY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "BODY>" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<BODY>" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "onload" ===
+Count: 1
+body.main-frame
+=== Query: "oNLoAd" ===
+Count: 0
+=== Query: "ONLOAD" ===
+Count: 0
+=== Query: "runTest()" ===
+Count: 1
+body.main-frame
+=== Query: "\"runTest()" ===
+Count: 1
+body.main-frame
+=== Query: "runTest()\"" ===
+Count: 1
+body.main-frame
+=== Query: "\"runTest()\"" ===
+Count: 1
+body.main-frame
+=== Query: "runtest()" ===
+Count: 0
+=== Query: "\"runtest()" ===
+Count: 0
+=== Query: "runtest()\"" ===
+Count: 0
+=== Query: "\"runtest()\"" ===
+Count: 0
+=== Query: "rUnTeSt()" ===
+Count: 0
+=== Query: "\"rUnTeSt()" ===
+Count: 0
+=== Query: "rUnTeSt()\"" ===
+Count: 0
+=== Query: "\"rUnTeSt()\"" ===
+Count: 0
+=== Query: "RUNTEST()" ===
+Count: 0
+=== Query: "\"RUNTEST()" ===
+Count: 0
+=== Query: "RUNTEST()\"" ===
+Count: 0
+=== Query: "\"RUNTEST()\"" ===
+Count: 0
+=== Query: ".body-inside-iframe" ===
+Count: 0
+=== Query: "*" ===
+Count: 14
+html
+head
+script
+script
+script
+script
+body.main-frame
+p
+iframe
+html.inside-iframe
+head.inside-iframe
+body.inside-iframe
+div.base1.inside-iframe
+p.inside-iframe
+=== Query: "BODY[ONLOAD]" ===
+Count: 1
+body.main-frame
+=== Query: "/html/body" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "/html/body/@onload" ===
+Count: 1
+body.main-frame
+=== Query: "/HTML/BODY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+
diff --git a/LayoutTests/inspector/dom/dom-search-caseSensitive.html b/LayoutTests/inspector/dom/dom-search-caseSensitive.html
new file mode 100644 (file)
index 0000000..e3b8dec
--- /dev/null
@@ -0,0 +1,70 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
+<script src="../../http/tests/inspector/dom/resources/InspectorDOMListener.js"></script>
+<!-- Loading the queries from external file to avoid having them show up in the results. -->
+<script src="resources/dom-search-queries.js"></script>
+<script>
+function test()
+{
+    // Create a DOM listener to convert nodeIds to tag names.
+    var dom = createDOMListener();
+
+    // Caching the output to avoid searching through the log.
+    var output = [];
+
+    InspectorProtocol.sendCommand("DOM.getDocument", {}, onGotDocument);
+
+    function onGotDocument(message) {
+        InspectorProtocol.checkForError(message);
+        dom.collectNode(message.result.root);
+        performSearches(domSearchQueries, testFinished);
+    }
+
+    function performSearches(list, callback)
+    {
+        function next() {
+            if (list.length)
+                search(list.shift(), next);
+            else
+                callback();
+        }
+        next();
+    }
+
+    function search(query, callback)
+    {
+        output.push("=== Query: " + JSON.stringify(query) + " ===");
+        InspectorProtocol.sendCommand("DOM.performSearch", {query, caseSensitive: true}, function(message) {
+            InspectorProtocol.checkForError(message);
+            printSearchResults(message.result, callback);
+        });
+    }
+
+    function printSearchResults(results, callback)
+    {
+        output.push("Count: " + results.resultCount);
+        if (!results.resultCount)
+            return callback();
+
+        var options = {"searchId": results.searchId, "fromIndex": 0, "toIndex": results.resultCount};
+        InspectorProtocol.sendCommand("DOM.getSearchResults", options, function onResultsReceived(message) {
+            for (var nodeId of message.result.nodeIds)
+                output.push(dom.getNodeIdentifier(nodeId));
+            callback();
+        });
+    }
+
+    function testFinished()
+    {
+        ProtocolTest.log(output.join("\n"));
+        ProtocolTest.completeTest();
+    }
+}
+</script>
+</head>
+<body onload="runTest()" class="main-frame">
+    <p>Testing DOM.performSearch with no parent node ids.</p>
+    <iframe src="resources/dom-search-iframe.html"></iframe>
+</body>
+</html>
index 690e663..fd1435b 100644 (file)
@@ -17,6 +17,34 @@ body.inside-iframe
 Count: 2
 body.main-frame
 body.inside-iframe
+=== Query: "bOdY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<bOdY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "bOdY>" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<bOdY>" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "BODY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "<BODY" ===
+Count: 2
+body.main-frame
+body.inside-iframe
+=== Query: "BODY>" ===
+Count: 2
+body.main-frame
+body.inside-iframe
 === Query: "<BODY>" ===
 Count: 2
 body.main-frame
@@ -24,6 +52,9 @@ body.inside-iframe
 === Query: "onload" ===
 Count: 1
 body.main-frame
+=== Query: "oNLoAd" ===
+Count: 1
+body.main-frame
 === Query: "ONLOAD" ===
 Count: 1
 body.main-frame
@@ -33,16 +64,46 @@ body.main-frame
 === Query: "\"runTest()" ===
 Count: 1
 body.main-frame
+=== Query: "runTest()\"" ===
+Count: 1
+body.main-frame
 === Query: "\"runTest()\"" ===
 Count: 1
 body.main-frame
-=== Query: "runTest()\"" ===
+=== Query: "runtest()" ===
+Count: 1
+body.main-frame
+=== Query: "\"runtest()" ===
+Count: 1
+body.main-frame
+=== Query: "runtest()\"" ===
+Count: 1
+body.main-frame
+=== Query: "\"runtest()\"" ===
+Count: 1
+body.main-frame
+=== Query: "rUnTeSt()" ===
+Count: 1
+body.main-frame
+=== Query: "\"rUnTeSt()" ===
+Count: 1
+body.main-frame
+=== Query: "rUnTeSt()\"" ===
+Count: 1
+body.main-frame
+=== Query: "\"rUnTeSt()\"" ===
 Count: 1
 body.main-frame
 === Query: "RUNTEST()" ===
 Count: 1
 body.main-frame
-=== Query: "runtest()" ===
+=== Query: "\"RUNTEST()" ===
+Count: 1
+body.main-frame
+=== Query: "RUNTEST()\"" ===
+Count: 1
+body.main-frame
+=== Query: "\"RUNTEST()\"" ===
 Count: 1
 body.main-frame
 === Query: ".body-inside-iframe" ===
index 1d84724..c79a797 100644 (file)
@@ -3,30 +3,59 @@ TestPage.registerInitializer(function() {
 // Having the queries in an external file, so that DOM search will not find the script when searching for values.
 
 window.domSearchQueries = [
+    // Tag names
+
     "body",
     "<body",
     "body>",
     "<body>",
+
+    "bOdY",
+    "<bOdY",
+    "bOdY>",
+    "<bOdY>",
+
+    "BODY",
+    "<BODY",
+    "BODY>",
     "<BODY>",
 
     // Attribute names
+
     "onload",
+    "oNLoAd",
     "ONLOAD",
 
     // Attribute values
+
     "runTest()",
     "\"runTest()",
-    "\"runTest()\"",
     "runTest()\"",
-    "RUNTEST()",
+    "\"runTest()\"",
+
     "runtest()",
+    "\"runtest()",
+    "runtest()\"",
+    "\"runtest()\"",
+
+    "rUnTeSt()",
+    "\"rUnTeSt()",
+    "rUnTeSt()\"",
+    "\"rUnTeSt()\"",
+
+    "RUNTEST()",
+    "\"RUNTEST()",
+    "RUNTEST()\"",
+    "\"RUNTEST()\"",
 
     // CSS selectors
+
     ".body-inside-iframe",
     "*",
     "BODY[ONLOAD]",
 
     // XPath query
+
     "/html/body",
     "/html/body/@onload",
     "/HTML/BODY"
index 0bcd8c0..11fa9b6 100644 (file)
@@ -1,3 +1,18 @@
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Search: allow DOM searches to be case sensitive
+        https://bugs.webkit.org/show_bug.cgi?id=194673
+        <rdar://problem/48087577>
+
+        Reviewed by Timothy Hatcher.
+
+        Since `DOM.performSearch` also searches by selector and XPath, some results may appear
+        as unexpected. As an example, searching for "BoDy" will still return the <body> as a result,
+        as although the literal node name ("BODY") didn't match, it did match via selector/XPath.
+
+        * inspector/protocol/DOM.json:
+        Allow `DOM.performSearch` to be case sensitive.
+
 2019-03-20  Saam Barati  <sbarati@apple.com>
 
         AI rule for ValueBitNot/ValueBitXor/ValueBitAnd/ValueBitOr is wrong
index cade521..0edc68b 100644 (file)
             "description": "Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.",
             "parameters": [
                 { "name": "query", "type": "string", "description": "Plain text or query selector or XPath search query." },
-                { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "optional": true, "description": "Ids of nodes to use as starting points for the search." }
+                { "name": "nodeIds", "type": "array", "items": { "$ref": "NodeId" }, "optional": true, "description": "Ids of nodes to use as starting points for the search." },
+                { "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." }
             ],
             "returns": [
                 { "name": "searchId", "type": "string", "description": "Unique search session identifier." },
index 36e99b0..755ae1b 100644 (file)
@@ -1,3 +1,35 @@
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Search: allow DOM searches to be case sensitive
+        https://bugs.webkit.org/show_bug.cgi?id=194673
+        <rdar://problem/48087577>
+
+        Reviewed by Timothy Hatcher.
+
+        Tests: inspector/dom/dom-search.html
+               inspector/dom/dom-search-caseSensitive.html
+
+        Since `DOM.performSearch` also searches by selector and XPath, some results may appear
+        as unexpected. As an example, searching for "BoDy" will still return the <body> as a result,
+        as although the literal node name ("BODY") didn't match, it did match via selector/XPath.
+
+        * inspector/agents/InspectorDOMAgent.h:
+        * inspector/agents/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::performSearch):
+
+        * inspector/InspectorNodeFinder.h:
+        * inspector/InspectorNodeFinder.cpp:
+        (WebCore::InspectorNodeFinder::InspectorNodeFinder):
+        (WebCore::InspectorNodeFinder::searchUsingDOMTreeTraversal):
+        (WebCore::InspectorNodeFinder::checkEquals): Added.
+        (WebCore::InspectorNodeFinder::checkContains): Added.
+        (WebCore::InspectorNodeFinder::checkStartsWith): Added.
+        (WebCore::InspectorNodeFinder::checkEndsWith): Added.
+        (WebCore::InspectorNodeFinder::matchesAttribute):
+        (WebCore::InspectorNodeFinder::matchesElement):
+        (WebCore::InspectorNodeFinder::searchUsingXPath):
+        (WebCore::InspectorNodeFinder::searchUsingCSSSelectors):
+
 2019-03-20  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Remove copyRef() calls added in r243163
index f92a5d8..191a6a7 100644 (file)
@@ -53,13 +53,14 @@ static String stripCharacters(const String& string, const char startCharacter, c
     return string.substring(start, end - start);
 }
 
-InspectorNodeFinder::InspectorNodeFinder(const String& whitespaceTrimmedQuery)
-    : m_whitespaceTrimmedQuery(whitespaceTrimmedQuery)
+InspectorNodeFinder::InspectorNodeFinder(const String& query, bool caseSensitive)
+    : m_query(query)
+    , m_caseSensitive(caseSensitive)
 {
-    m_tagNameQuery = stripCharacters(whitespaceTrimmedQuery, '<', '>', m_startTagFound, m_endTagFound);
+    m_tagNameQuery = stripCharacters(query, '<', '>', m_startTagFound, m_endTagFound);
 
     bool startQuoteFound, endQuoteFound;
-    m_attributeQuery = stripCharacters(whitespaceTrimmedQuery, '"', '"', startQuoteFound, endQuoteFound);
+    m_attributeQuery = stripCharacters(query, '"', '"', startQuoteFound, endQuoteFound);
     m_exactAttributeMatch = startQuoteFound && endQuoteFound;
 }
 
@@ -83,7 +84,7 @@ void InspectorNodeFinder::searchUsingDOMTreeTraversal(Node& parentNode)
         case Node::TEXT_NODE:
         case Node::COMMENT_NODE:
         case Node::CDATA_SECTION_NODE:
-            if (node->nodeValue().containsIgnoringASCIICase(m_whitespaceTrimmedQuery))
+            if (checkContains(node->nodeValue(), m_query))
                 m_results.add(node);
             break;
         case Node::ELEMENT_NODE:
@@ -98,20 +99,50 @@ void InspectorNodeFinder::searchUsingDOMTreeTraversal(Node& parentNode)
     }
 }
 
+bool InspectorNodeFinder::checkEquals(const String& a, const String& b)
+{
+    if (m_caseSensitive)
+        return a == b;
+    return equalIgnoringASCIICase(a, b);
+}
+
+bool InspectorNodeFinder::checkContains(const String& a, const String& b)
+{
+    if (m_caseSensitive)
+        return a.contains(b);
+    return a.containsIgnoringASCIICase(b);
+}
+
+bool InspectorNodeFinder::checkStartsWith(const String& a, const String& b)
+{
+    if (m_caseSensitive)
+        return a.startsWith(b);
+    return a.startsWithIgnoringASCIICase(b);
+}
+
+bool InspectorNodeFinder::checkEndsWith(const String& a, const String& b)
+{
+    if (m_caseSensitive)
+        return a.endsWith(b);
+    return a.endsWithIgnoringASCIICase(b);
+}
+
 bool InspectorNodeFinder::matchesAttribute(const Attribute& attribute)
 {
-    if (attribute.localName().string().containsIgnoringASCIICase(m_whitespaceTrimmedQuery))
+    if (checkContains(attribute.localName().string(), m_query))
         return true;
-    return m_exactAttributeMatch ? attribute.value() == m_attributeQuery : attribute.value().string().containsIgnoringASCIICase(m_attributeQuery);
+
+    auto value = attribute.value().string();
+    return m_exactAttributeMatch ? checkEquals(value, m_attributeQuery) : checkContains(value, m_attributeQuery);
 }
 
 bool InspectorNodeFinder::matchesElement(const Element& element)
 {
     String nodeName = element.nodeName();
-    if ((!m_startTagFound && !m_endTagFound && nodeName.containsIgnoringASCIICase(m_tagNameQuery))
-        || (m_startTagFound && m_endTagFound && equalIgnoringASCIICase(nodeName, m_tagNameQuery))
-        || (m_startTagFound && !m_endTagFound && nodeName.startsWithIgnoringASCIICase(m_tagNameQuery))
-        || (!m_startTagFound && m_endTagFound && nodeName.endsWithIgnoringASCIICase(m_tagNameQuery)))
+    if ((!m_startTagFound && !m_endTagFound && checkContains(nodeName, m_tagNameQuery))
+        || (m_startTagFound && m_endTagFound && checkEquals(nodeName, m_tagNameQuery))
+        || (m_startTagFound && !m_endTagFound && checkStartsWith(nodeName, m_tagNameQuery))
+        || (!m_startTagFound && m_endTagFound && checkEndsWith(nodeName, m_tagNameQuery)))
         return true;
 
     if (!element.hasAttributes())
@@ -127,7 +158,7 @@ bool InspectorNodeFinder::matchesElement(const Element& element)
 
 void InspectorNodeFinder::searchUsingXPath(Node& parentNode)
 {
-    auto evaluateResult = parentNode.document().evaluate(m_whitespaceTrimmedQuery, &parentNode, nullptr, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
+    auto evaluateResult = parentNode.document().evaluate(m_query, &parentNode, nullptr, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
     if (evaluateResult.hasException())
         return;
     auto result = evaluateResult.releaseReturnValue();
@@ -157,7 +188,7 @@ void InspectorNodeFinder::searchUsingCSSSelectors(Node& parentNode)
     if (!is<ContainerNode>(parentNode))
         return;
 
-    auto queryResult = downcast<ContainerNode>(parentNode).querySelectorAll(m_whitespaceTrimmedQuery);
+    auto queryResult = downcast<ContainerNode>(parentNode).querySelectorAll(m_query);
     if (queryResult.hasException())
         return;
 
index 5d55dd3..468c152 100644 (file)
@@ -41,11 +41,16 @@ class Node;
 
 class InspectorNodeFinder {
 public:
-    InspectorNodeFinder(const String& whitespaceTrimmedQuery);
+    InspectorNodeFinder(const String& query, bool caseSensitive);
     void performSearch(Node*);
     const ListHashSet<Node*>& results() const { return m_results; }
 
 private:
+    bool checkEquals(const String&, const String&);
+    bool checkContains(const String&, const String&);
+    bool checkStartsWith(const String&, const String&);
+    bool checkEndsWith(const String&, const String&);
+
     bool matchesAttribute(const Attribute&);
     bool matchesElement(const Element&);
 
@@ -53,15 +58,15 @@ private:
     void searchUsingXPath(Node&);
     void searchUsingCSSSelectors(Node&);
 
-    bool m_startTagFound;
-    bool m_endTagFound;
-    bool m_exactAttributeMatch;
-
-    String m_whitespaceTrimmedQuery;
+    String m_query;
     String m_tagNameQuery;
     String m_attributeQuery;
+    bool m_caseSensitive;
 
     ListHashSet<Node*> m_results;
+    bool m_startTagFound;
+    bool m_endTagFound;
+    bool m_exactAttributeMatch;
 };
 
 } // namespace WebCore
index 59859ed..5ebd416 100644 (file)
@@ -1005,10 +1005,10 @@ void InspectorDOMAgent::getAccessibilityPropertiesForNode(ErrorString& errorStri
     axProperties = buildObjectForAccessibilityProperties(node);
 }
 
-void InspectorDOMAgent::performSearch(ErrorString& errorString, const String& whitespaceTrimmedQuery, const JSON::Array* nodeIds, String* searchId, int* resultCount)
+void InspectorDOMAgent::performSearch(ErrorString& errorString, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount)
 {
     // FIXME: Search works with node granularity - number of matches within node is not calculated.
-    InspectorNodeFinder finder(whitespaceTrimmedQuery);
+    InspectorNodeFinder finder(query, caseSensitive && *caseSensitive);
 
     if (nodeIds) {
         for (auto& nodeValue : *nodeIds) {
index 837b7be..cc7e226 100644 (file)
@@ -134,7 +134,7 @@ public:
     void setBreakpointForEventListener(ErrorString&, int eventListenerId) override;
     void removeBreakpointForEventListener(ErrorString&, int eventListenerId) override;
     void getAccessibilityPropertiesForNode(ErrorString&, int nodeId, RefPtr<Inspector::Protocol::DOM::AccessibilityProperties>& axProperties) override;
-    void performSearch(ErrorString&, const String& whitespaceTrimmedQuery, const JSON::Array* nodeIds, String* searchId, int* resultCount) override;
+    void performSearch(ErrorString&, const String& query, const JSON::Array* nodeIds, const bool* caseSensitive, String* searchId, int* resultCount) override;
     void getSearchResults(ErrorString&, const String& searchId, int fromIndex, int toIndex, RefPtr<JSON::ArrayOf<int>>&) override;
     void discardSearchResults(ErrorString&, const String& searchId) override;
     void resolveNode(ErrorString&, int nodeId, const String* objectGroup, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result) override;
index dadd058..4c1fd6b 100644 (file)
@@ -1,3 +1,25 @@
+2019-03-20  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Search: allow DOM searches to be case sensitive
+        https://bugs.webkit.org/show_bug.cgi?id=194673
+        <rdar://problem/48087577>
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Views/SearchSidebarPanel.js:
+        (WI.SearchSidebarPanel.prototype.performSearch):
+
+        * UserInterface/Views/DOMTreeContentView.js:
+        (WI.DOMTreeContentView.prototype.performSearch.contextNodesReady):
+
+        * UserInterface/Controllers/DOMManager.js:
+        (WI.DOMManager.prototype.performSearch.callback): Deleted.
+        (WI.DOMManager.prototype.performSearch): Deleted.
+        (WI.DOMManager.prototype.searchResult.mycallback): Deleted.
+        (WI.DOMManager.prototype.searchResult): Deleted.
+        (WI.DOMManager.prototype.cancelSearch): Deleted.
+        Drive-by: remove unused code.
+
 2019-03-19  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Sources: provide option to group by path
index 95ecfc6..bf7d31a 100644 (file)
@@ -438,47 +438,6 @@ WI.DOMManager = class DOMManager extends WI.Object
         remoteObject.pushNodeToFrontend(nodeAvailable.bind(this));
     }
 
-    performSearch(query, searchCallback)
-    {
-        this.cancelSearch();
-
-        function callback(error, searchId, resultsCount)
-        {
-            this._searchId = searchId;
-            searchCallback(resultsCount);
-        }
-        DOMAgent.performSearch(query, callback.bind(this));
-    }
-
-    searchResult(index, callback)
-    {
-        function mycallback(error, nodeIds)
-        {
-            if (error) {
-                console.error(error);
-                callback(null);
-                return;
-            }
-            if (nodeIds.length !== 1)
-                return;
-
-            callback(this._idToDOMNode[nodeIds[0]]);
-        }
-
-        if (this._searchId)
-            DOMAgent.getSearchResults(this._searchId, index, index + 1, mycallback.bind(this));
-        else
-            callback(null);
-    }
-
-    cancelSearch()
-    {
-        if (this._searchId) {
-            DOMAgent.discardSearchResults(this._searchId);
-            this._searchId = undefined;
-        }
-    }
-
     querySelector(nodeOrNodeId, selector, callback)
     {
         let nodeId = nodeOrNodeId instanceof WI.DOMNode ? nodeOrNodeId.id : nodeOrNodeId;
index 1c41783..920a96f 100644 (file)
@@ -302,7 +302,15 @@ WI.DOMTreeContentView = class DOMTreeContentView extends WI.ContentView
 
         function contextNodesReady(nodeIds)
         {
-            DOMAgent.performSearch(query, nodeIds, searchResultsReady.bind(this));
+            if (this._searchQuery !== query)
+                return;
+
+            let commandArguments = {
+                query: this._searchQuery,
+                nodeIds,
+                caseSensitive: WI.SearchUtilities.defaultSettings.caseSensitive.value,
+            };
+            DOMAgent.performSearch.invoke(commandArguments, searchResultsReady.bind(this));
         }
 
         this.getSearchContextNodes(contextNodesReady.bind(this));
index cb0f454..4812d7d 100644 (file)
@@ -304,7 +304,11 @@ WI.SearchSidebarPanel = class SearchSidebarPanel extends WI.NavigationSidebarPan
                 this._domSearchIdentifier = undefined;
             }
 
-            countPromise(DOMAgent.performSearch(searchQuery), domCallback);
+            let commandArguments = {
+                query: searchQuery,
+                caseSensitive: isCaseSensitive,
+            };
+            countPromise(DOMAgent.performSearch.invoke(commandArguments), domCallback);
         }
 
         // FIXME: Resource search should work in JSContext inspection.