Title: [102569] trunk/Source/WebCore
Revision
102569
Author
[email protected]
Date
2011-12-12 05:09:50 -0800 (Mon, 12 Dec 2011)

Log Message

Web Inspector: provide per Document Node count statistics
https://bugs.webkit.org/show_bug.cgi?id=74100

Memory agent now returns counters for nodes with given names. For each
object group root user will see total number of its descendtants and per
tag name counts.

This patch also moves generic CounterVisitor code out of V8 bindings. It
may well be used with both JS engines.

Reviewed by Pavel Feldman.

* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ScriptProfiler.h:
(WebCore::ScriptProfiler::visitJSDOMWrappers):
* bindings/v8/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::visitJSDOMWrappers):
* bindings/v8/ScriptProfiler.h:
* inspector/DOMWrapperVisitor.h: Added.
(WebCore::DOMWrapperVisitor::~DOMWrapperVisitor):
* inspector/Inspector.json:
* inspector/InspectorMemoryAgent.cpp:
(WebCore::InspectorMemoryAgent::getDOMNodeCount):
* inspector/InspectorMemoryAgent.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (102568 => 102569)


--- trunk/Source/WebCore/ChangeLog	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/ChangeLog	2011-12-12 13:09:50 UTC (rev 102569)
@@ -1,3 +1,34 @@
+2011-12-09  Yury Semikhatsky  <[email protected]>
+
+        Web Inspector: provide per Document Node count statistics
+        https://bugs.webkit.org/show_bug.cgi?id=74100
+
+        Memory agent now returns counters for nodes with given names. For each
+        object group root user will see total number of its descendtants and per
+        tag name counts.
+
+        This patch also moves generic CounterVisitor code out of V8 bindings. It
+        may well be used with both JS engines.
+
+        Reviewed by Pavel Feldman.
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/ScriptProfiler.h:
+        (WebCore::ScriptProfiler::visitJSDOMWrappers):
+        * bindings/v8/ScriptProfiler.cpp:
+        (WebCore::ScriptProfiler::visitJSDOMWrappers):
+        * bindings/v8/ScriptProfiler.h:
+        * inspector/DOMWrapperVisitor.h: Added.
+        (WebCore::DOMWrapperVisitor::~DOMWrapperVisitor):
+        * inspector/Inspector.json:
+        * inspector/InspectorMemoryAgent.cpp:
+        (WebCore::InspectorMemoryAgent::getDOMNodeCount):
+        * inspector/InspectorMemoryAgent.h:
+
 2011-12-12  Noel Gordon  <[email protected]>
 
         WebPImageDecoder: Increase image/webp decoding performance 10-20%

Modified: trunk/Source/WebCore/GNUmakefile.list.am (102568 => 102569)


--- trunk/Source/WebCore/GNUmakefile.list.am	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/GNUmakefile.list.am	2011-12-12 13:09:50 UTC (rev 102569)
@@ -2027,6 +2027,7 @@
 	Source/WebCore/inspector/ContentSearchUtils.h \
 	Source/WebCore/inspector/DOMNodeHighlighter.cpp \
 	Source/WebCore/inspector/DOMNodeHighlighter.h \
+	Source/WebCore/inspector/DOMWrapperVisitor.h \
 	Source/WebCore/inspector/IdentifiersFactory.cpp \
 	Source/WebCore/inspector/IdentifiersFactory.h \
 	Source/WebCore/inspector/InjectedScript.cpp \

Modified: trunk/Source/WebCore/Target.pri (102568 => 102569)


--- trunk/Source/WebCore/Target.pri	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/Target.pri	2011-12-12 13:09:50 UTC (rev 102569)
@@ -1894,6 +1894,7 @@
     inspector/ConsoleMessage.h \
     inspector/ContentSearchUtils.h \
     inspector/DOMNodeHighlighter.h \
+    inspector/DOMWrapperVisitor.h \
     inspector/IdentifiersFactory.h \
     inspector/InjectedScript.h \
     inspector/InjectedScriptHost.h \

Modified: trunk/Source/WebCore/WebCore.gypi (102568 => 102569)


--- trunk/Source/WebCore/WebCore.gypi	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/WebCore.gypi	2011-12-12 13:09:50 UTC (rev 102569)
@@ -2724,6 +2724,7 @@
             'inspector/ContentSearchUtils.h',
             'inspector/DOMNodeHighlighter.cpp',
             'inspector/DOMNodeHighlighter.h',
+            'inspector/DOMWrapperVisitor.h',
             'inspector/IdentifiersFactory.cpp',
             'inspector/IdentifiersFactory.h',
             'inspector/InjectedScript.cpp',

Modified: trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj (102568 => 102569)


--- trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj	2011-12-12 13:09:50 UTC (rev 102569)
@@ -68458,6 +68458,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\inspector\DOMWrapperVisitor.h"
+				>
+			</File>
+			<File
 				RelativePath="..\inspector\IdentifiersFactory.cpp"
 				>
 			</File>

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (102568 => 102569)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2011-12-12 13:09:50 UTC (rev 102569)
@@ -6027,6 +6027,7 @@
 		F34742E81343635000531BC2 /* WorkerScriptDebugServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F34742E61343635000531BC2 /* WorkerScriptDebugServer.cpp */; };
 		F34742E91343635000531BC2 /* WorkerScriptDebugServer.h in Headers */ = {isa = PBXBuildFile; fileRef = F34742E71343635000531BC2 /* WorkerScriptDebugServer.h */; };
 		F350B73513F1377D00880C43 /* InstrumentingAgents.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F350B73413F1377D00880C43 /* InstrumentingAgents.cpp */; };
+		F35AE5AC14925F5B004D5776 /* DOMWrapperVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = F35AE5AB14925F5B004D5776 /* DOMWrapperVisitor.h */; };
 		F3644AFF1119805900E0D537 /* InjectedScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F3644AFD1119805900E0D537 /* InjectedScript.cpp */; };
 		F3644B001119805900E0D537 /* InjectedScript.h in Headers */ = {isa = PBXBuildFile; fileRef = F3644AFE1119805900E0D537 /* InjectedScript.h */; };
 		F36E07A41358A8BE00AACBC9 /* WorkerInspectorController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F36E07A21358A8BE00AACBC9 /* WorkerInspectorController.cpp */; };
@@ -13411,6 +13412,7 @@
 		F34742E61343635000531BC2 /* WorkerScriptDebugServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerScriptDebugServer.cpp; sourceTree = "<group>"; };
 		F34742E71343635000531BC2 /* WorkerScriptDebugServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerScriptDebugServer.h; sourceTree = "<group>"; };
 		F350B73413F1377D00880C43 /* InstrumentingAgents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InstrumentingAgents.cpp; sourceTree = "<group>"; };
+		F35AE5AB14925F5B004D5776 /* DOMWrapperVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWrapperVisitor.h; sourceTree = "<group>"; };
 		F3644AFD1119805900E0D537 /* InjectedScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedScript.cpp; sourceTree = "<group>"; };
 		F3644AFE1119805900E0D537 /* InjectedScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedScript.h; sourceTree = "<group>"; };
 		F36E07A21358A8BE00AACBC9 /* WorkerInspectorController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerInspectorController.cpp; sourceTree = "<group>"; };
@@ -14530,6 +14532,7 @@
 				59102FBA14327D3B003C9D04 /* ContentSearchUtils.h */,
 				4F1442261339FD6200E0D6F8 /* DOMNodeHighlighter.cpp */,
 				4F1442271339FD6200E0D6F8 /* DOMNodeHighlighter.h */,
+				F35AE5AB14925F5B004D5776 /* DOMWrapperVisitor.h */,
 				5913A23F13D49EBA00F5B05C /* IdentifiersFactory.cpp */,
 				5913A24013D49EBA00F5B05C /* IdentifiersFactory.h */,
 				F3644AFD1119805900E0D537 /* InjectedScript.cpp */,
@@ -24805,6 +24808,7 @@
 				265541391489811C000DFC5D /* KeyEventCodesIOS.h in Headers */,
 				8A195932147EA16E00D1EA61 /* DOMWebKitNamedFlow.h in Headers */,
 				8A195934147EA16E00D1EA61 /* DOMWebKitNamedFlowInternal.h in Headers */,
+				F35AE5AC14925F5B004D5776 /* DOMWrapperVisitor.h in Headers */,
 				26C17A3E1491D2D400D12BA2 /* FileSystemIOS.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

Modified: trunk/Source/WebCore/bindings/js/ScriptProfiler.h (102568 => 102569)


--- trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/bindings/js/ScriptProfiler.h	2011-12-12 13:09:50 UTC (rev 102569)
@@ -37,8 +37,8 @@
 
 namespace WebCore {
 
+class DOMWrapperVisitor;
 class InjectedScriptManager;
-class Page;
 
 class ScriptProfiler {
     WTF_MAKE_NONCOPYABLE(ScriptProfiler);
@@ -61,7 +61,7 @@
     static bool isSampling() { return false; }
     static bool hasHeapProfiler() { return false; }
     // FIXME: Implement this counter for JSC. See bug 73936 for more details.
-    static PassRefPtr<InspectorArray> domNodeCount(Page*) { return 0; };
+    static void visitJSDOMWrappers(DOMWrapperVisitor*) { }
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp (102568 => 102569)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.cpp	2011-12-12 13:09:50 UTC (rev 102569)
@@ -31,14 +31,13 @@
 #include "config.h"
 #include "ScriptProfiler.h"
 
-#include "DOMNodeHighlighter.h"
+#include "DOMWrapperVisitor.h"
 #include "InjectedScript.h"
 #include "InspectorValues.h"
 #include "RetainedDOMInfo.h"
 #include "V8Binding.h"
 #include "V8DOMMap.h"
 #include "V8Node.h"
-#include <wtf/text/StringBuilder.h>
 
 #include <v8-profiler.h>
 
@@ -148,83 +147,20 @@
 #endif // ENABLE(INSPECTOR)
 }
 
-namespace {
+void ScriptProfiler::visitJSDOMWrappers(DOMWrapperVisitor* visitor)
+{
+    class VisitorAdapter : public DOMWrapperMap<Node>::Visitor {
+    public:
+        VisitorAdapter(DOMWrapperVisitor* visitor) : m_visitor(visitor) { }
 
-class CounterVisitor : public DOMWrapperMap<Node>::Visitor {
-public:
-    CounterVisitor(Page* page, InspectorArray* counters) : m_page(page), m_counters(counters) { }
-
-    void visitDOMWrapper(DOMDataStore* store, Node* node, v8::Persistent<v8::Object> wrapper)
-    {
-        if (node->document()->frame() && m_page != node->document()->frame()->page())
-            return;
-
-        Node* rootNode = node;
-        while (rootNode->parentNode())
-            rootNode = rootNode->parentNode();
-
-        if (m_roots.contains(rootNode))
-            return;
-        m_roots.add(rootNode);
-
-        unsigned count = 0;
-        Node* currentNode = rootNode;
-        while ((currentNode = currentNode->traverseNextNode(rootNode)))
-            ++count;
-
-        RefPtr<InspectorObject> entry = InspectorObject::create();
-        entry->setNumber("size", count);
-
-        entry->setString("title", rootNode->nodeType() == Node::ELEMENT_NODE ? elementTitle(static_cast<Element*>(rootNode)) : rootNode->nodeName());
-        if (rootNode->nodeType() == Node::DOCUMENT_NODE)
-            entry->setString("documentURI", static_cast<Document*>(rootNode)->documentURI());
-        m_counters->pushObject(entry);
-    }
-
-private:
-    String elementTitle(Element* element)
-    {
-        StringBuilder result;
-        bool isXHTML = element->document()->isXHTMLDocument();
-        result.append(isXHTML ? element->nodeName() : element->nodeName().lower());
-
-        const AtomicString& idValue = element->getIdAttribute();
-        String idString;
-        if (!idValue.isNull() && !idValue.isEmpty()) {
-            result.append("#");
-            result.append(idValue);
+        virtual void visitDOMWrapper(DOMDataStore*, Node* node, v8::Persistent<v8::Object>)
+        {
+            m_visitor->visitNode(node);
         }
-
-        HashSet<AtomicString> usedClassNames;
-        if (element->hasClass() && element->isStyledElement()) {
-            const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
-            size_t classNameCount = classNamesString.size();
-            for (size_t i = 0; i < classNameCount; ++i) {
-                const AtomicString& className = classNamesString[i];
-                if (usedClassNames.contains(className))
-                    continue;
-                usedClassNames.add(className);
-                result.append(".");
-                result.append(className);
-            }
-        }
-        return result.toString();
-    }
-
-    HashSet<Node*> m_roots;
-    Page* m_page;
-    InspectorArray* m_counters;
-};
-
-} // namespace
-
-PassRefPtr<InspectorArray> ScriptProfiler::domNodeCount(Page* page)
-{
-    RefPtr<InspectorArray> result = InspectorArray::create();
-    CounterVisitor counterVisitor(page, result.get());
-    visitDOMNodes(&counterVisitor);
-    return result;
+    private:
+        DOMWrapperVisitor* m_visitor;
+    } adapter(visitor);
+    visitDOMNodes(&adapter);
 }
 
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/bindings/v8/ScriptProfiler.h (102568 => 102569)


--- trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/bindings/v8/ScriptProfiler.h	2011-12-12 13:09:50 UTC (rev 102569)
@@ -41,8 +41,8 @@
 
 namespace WebCore {
 
+class DOMWrapperVisitor;
 class InjectedScriptManager;
-class Page;
 
 class ScriptProfiler {
     WTF_MAKE_NONCOPYABLE(ScriptProfiler);
@@ -65,7 +65,7 @@
     static bool isSampling() { return true; }
     static bool hasHeapProfiler() { return true; }
     static void initialize();
-    static PassRefPtr<InspectorArray> domNodeCount(Page*);
+    static void visitJSDOMWrappers(DOMWrapperVisitor*);
 };
 
 } // namespace WebCore

Added: trunk/Source/WebCore/inspector/DOMWrapperVisitor.h (0 => 102569)


--- trunk/Source/WebCore/inspector/DOMWrapperVisitor.h	                        (rev 0)
+++ trunk/Source/WebCore/inspector/DOMWrapperVisitor.h	2011-12-12 13:09:50 UTC (rev 102569)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011 Google 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
+ */
+
+#ifndef DOMWrapperVisitor_h
+#define DOMWrapperVisitor_h
+
+namespace WebCore {
+
+class Node;
+
+class DOMWrapperVisitor {
+public:
+    virtual void visitNode(Node*) = 0;
+protected:
+    virtual ~DOMWrapperVisitor() { }
+};
+
+} // namespace WebCore
+
+#endif // DOMWrapperVisitor_h
Property changes on: trunk/Source/WebCore/inspector/DOMWrapperVisitor.h
___________________________________________________________________

Added: svn:eol-style

Modified: trunk/Source/WebCore/inspector/Inspector.json (102568 => 102569)


--- trunk/Source/WebCore/inspector/Inspector.json	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/inspector/Inspector.json	2011-12-12 13:09:50 UTC (rev 102569)
@@ -50,11 +50,22 @@
         "hidden": true,
         "types": [
             {
+                "id": "NodeCount",
+                "type": "object",
+                "properties": [
+                    { "name": "nodeName", "type": "string" },
+                    { "name": "count", "type": "integer" }
+                ],
+                "description": "Number of nodes with given name."
+            },
+            {
                 "id": "DOMGroup",
                 "type": "object",
                 "properties": [
                     { "name": "size", "type": "integer" },
-                    { "name": "title", "type": "string" }
+                    { "name": "title", "type": "string" },
+                    { "name": "documentURI", "type": "string", "optional": true },
+                    { "name": "nodeCount", "type": "array", "items": { "$ref": "NodeCount" }}
                 ]
             }
         ],

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp (102568 => 102569)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.cpp	2011-12-12 13:09:50 UTC (rev 102569)
@@ -1,55 +1,165 @@
 /*
-* Copyright (C) 2011 Google 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:
-*
-*     * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-*     * 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.
-*     * Neither the name of Google Inc. nor the names of its
-* contributors may be used to endorse or promote products derived from
-* this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
-* OWNER OR 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.
-*/
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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.
+ */
 
 #include "config.h"
 #include "InspectorMemoryAgent.h"
 
 #if ENABLE(INSPECTOR)
 
+#include "DOMWrapperVisitor.h"
+#include "Document.h"
+#include "Frame.h"
 #include "InspectorState.h"
 #include "InspectorValues.h"
 #include "InstrumentingAgents.h"
 #include "Node.h"
 #include "Page.h"
 #include "ScriptProfiler.h"
+#include "StyledElement.h"
 #include <wtf/HashSet.h>
+#include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
 
+namespace {
+
+class CounterVisitor : public DOMWrapperVisitor {
+public:
+    CounterVisitor(Page* page) : m_page(page), m_counters(InspectorArray::create()) { }
+
+    InspectorArray* counters() { return m_counters.get(); }
+
+    virtual void visitNode(Node* node)
+    {
+        if (node->document()->frame() && m_page != node->document()->frame()->page())
+            return;
+
+        Node* rootNode = node;
+        while (rootNode->parentNode())
+            rootNode = rootNode->parentNode();
+
+        if (m_roots.contains(rootNode))
+            return;
+        m_roots.add(rootNode);
+
+        RefPtr<InspectorObject> entry = InspectorObject::create();
+        entry->setString("title", rootNode->nodeType() == Node::ELEMENT_NODE ? elementTitle(static_cast<Element*>(rootNode)) : rootNode->nodeName());
+        if (rootNode->nodeType() == Node::DOCUMENT_NODE)
+            entry->setString("documentURI", static_cast<Document*>(rootNode)->documentURI());
+        collectTreeStatistics(rootNode, entry.get());
+        m_counters->pushObject(entry);
+    }
+
+private:
+    static void collectTreeStatistics(Node* rootNode, InspectorObject* result)
+    {
+        unsigned count = 0;
+        HashMap<String, int> nameToCount;
+        Node* currentNode = rootNode;
+        while ((currentNode = currentNode->traverseNextNode(rootNode))) {
+            ++count;
+            String name = nodeName(currentNode);
+            int currentCount = nameToCount.get(name);
+            nameToCount.set(name, currentCount + 1);
+        }
+
+        RefPtr<InspectorArray> childrenStats = InspectorArray::create();
+        for (HashMap<String, int>::iterator it = nameToCount.begin(); it != nameToCount.end(); ++it) {
+            RefPtr<InspectorObject> nodeCount = InspectorObject::create();
+            nodeCount->setString("nodeName", it->first);
+            nodeCount->setNumber("count", it->second);
+            childrenStats->pushObject(nodeCount);
+        }
+
+        result->setNumber("size", count);
+        result->setArray("nodeCount", childrenStats);
+    }
+
+    static String nodeName(Node* node)
+    {
+        if (node->document()->isXHTMLDocument())
+             return node->nodeName();
+        return node->nodeName().lower();
+    }
+
+    String elementTitle(Element* element)
+    {
+        StringBuilder result;
+        result.append(nodeName(element));
+
+        const AtomicString& idValue = element->getIdAttribute();
+        String idString;
+        if (!idValue.isNull() && !idValue.isEmpty()) {
+            result.append("#");
+            result.append(idValue);
+        }
+
+        HashSet<AtomicString> usedClassNames;
+        if (element->hasClass() && element->isStyledElement()) {
+            const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames();
+            size_t classNameCount = classNamesString.size();
+            for (size_t i = 0; i < classNameCount; ++i) {
+                const AtomicString& className = classNamesString[i];
+                if (usedClassNames.contains(className))
+                    continue;
+                usedClassNames.add(className);
+                result.append(".");
+                result.append(className);
+            }
+        }
+        return result.toString();
+    }
+
+    HashSet<Node*> m_roots;
+    Page* m_page;
+    RefPtr<InspectorArray> m_counters;
+};
+
+} // namespace
+
 InspectorMemoryAgent::~InspectorMemoryAgent()
 {
 }
 
 void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<InspectorArray>* result)
 {
-    *result = ScriptProfiler::domNodeCount(m_page);
+    CounterVisitor counterVisitor(m_page);
+    ScriptProfiler::visitJSDOMWrappers(&counterVisitor);
+
+    // Make sure all documents reachable from the main frame are accounted.
+    for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
+        if (Document* doc = frame->document())
+            counterVisitor.visitNode(doc);
+    }
+
+    *result = counterVisitor.counters();
 }
 
 InspectorMemoryAgent::InspectorMemoryAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, Page* page, InspectorDOMAgent* domAgent)

Modified: trunk/Source/WebCore/inspector/InspectorMemoryAgent.h (102568 => 102569)


--- trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2011-12-12 13:08:57 UTC (rev 102568)
+++ trunk/Source/WebCore/inspector/InspectorMemoryAgent.h	2011-12-12 13:09:50 UTC (rev 102569)
@@ -1,32 +1,32 @@
 /*
-* Copyright (C) 2011 Google 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:
-*
-*     * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-*     * 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.
-*     * Neither the name of Google Inc. nor the names of its
-* contributors may be used to endorse or promote products derived from
-* this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
-* OWNER OR 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.
-*/
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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.
+ */
 
 #ifndef InspectorMemoryAgent_h
 #define InspectorMemoryAgent_h
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to