#include "Document.h"
#include "EventListenerMap.h"
#include "Frame.h"
+#include "InspectorFrontend.h"
#include "InspectorState.h"
#include "InspectorValues.h"
#include "InstrumentingAgents.h"
#include <wtf/HashSet.h>
#include <wtf/text/StringBuilder.h>
+using WebCore::TypeBuilder::Memory::DOMGroup;
+using WebCore::TypeBuilder::Memory::ListenerCount;
+using WebCore::TypeBuilder::Memory::NodeCount;
+
namespace WebCore {
namespace {
-class CounterVisitor : public DOMWrapperVisitor {
-public:
- CounterVisitor(Page* page) : m_page(page), m_counters(InspectorArray::create()) { }
+String nodeName(Node* node)
+{
+ if (node->document()->isXHTMLDocument())
+ return node->nodeName();
+ return node->nodeName().lower();
+}
- InspectorArray* counters() { return m_counters.get(); }
+typedef HashSet<StringImpl*, PtrHash<StringImpl*> > StringImplIdentitySet;
- virtual void visitNode(Node* node)
+class DOMTreeStatistics {
+public:
+ DOMTreeStatistics(Node* rootNode) : m_totalNodeCount(0)
{
- if (node->document()->frame() && m_page != node->document()->frame()->page())
- return;
+ collectTreeStatistics(rootNode);
+ }
- Node* rootNode = node;
- while (rootNode->parentNode())
- rootNode = rootNode->parentNode();
+ int totalNodeCount() { return m_totalNodeCount; }
- if (m_roots.contains(rootNode))
- return;
- m_roots.add(rootNode);
+ PassRefPtr<InspectorArray> nodeCount()
+ {
+ RefPtr<InspectorArray> childrenStats = InspectorArray::create();
+ for (HashMap<String, int>::iterator it = m_nodeNameToCount.begin(); it != m_nodeNameToCount.end(); ++it) {
+ RefPtr<NodeCount> nodeCount = NodeCount::create().setNodeName(it->first)
+ .setCount(it->second);
+ childrenStats->pushObject(nodeCount);
+ }
+ return childrenStats.release();
+ }
- 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);
+ PassRefPtr<InspectorArray> listenerCount()
+ {
+ RefPtr<InspectorArray> listenerStats = InspectorArray::create();
+ for (HashMap<AtomicString, int>::iterator it = m_eventTypeToCount.begin(); it != m_eventTypeToCount.end(); ++it) {
+ RefPtr<ListenerCount> listenerCount = ListenerCount::create().setType(it->first)
+ .setCount(it->second);
+ listenerStats->pushObject(listenerCount);
+ }
+ return listenerStats.release();
}
private:
- static void collectTreeStatistics(Node* rootNode, InspectorObject* result)
+ void collectTreeStatistics(Node* rootNode)
{
- unsigned count = 0;
- HashMap<AtomicString, int> eventTypeToCount;
- HashMap<String, int> nameToCount;
Node* currentNode = rootNode;
- collectListenersInfo(rootNode, eventTypeToCount);
+ collectListenersInfo(rootNode);
while ((currentNode = currentNode->traverseNextNode(rootNode))) {
- ++count;
- String name = nodeName(currentNode);
- int currentCount = nameToCount.get(name);
- nameToCount.set(name, currentCount + 1);
- collectListenersInfo(currentNode, eventTypeToCount);
- }
-
- 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);
- }
-
- RefPtr<InspectorArray> listenerStats = InspectorArray::create();
- for (HashMap<AtomicString, int>::iterator it = eventTypeToCount.begin(); it != eventTypeToCount.end(); ++it) {
- RefPtr<InspectorObject> eventCount = InspectorObject::create();
- eventCount->setString("type", it->first);
- eventCount->setNumber("count", it->second);
- listenerStats->pushObject(eventCount);
+ ++m_totalNodeCount;
+ collectNodeStatistics(currentNode);
}
+ }
+ void collectNodeStatistics(Node* node)
+ {
+ collectCharacterData(node);
+ collectNodeNameInfo(node);
+ collectListenersInfo(node);
+ }
+
+ void collectCharacterData(Node* node)
+ {
+ }
- result->setNumber("size", count);
- result->setArray("nodeCount", childrenStats);
- result->setArray("listenerCount", listenerStats);
+ void collectNodeNameInfo(Node* node)
+ {
+ String name = nodeName(node);
+ int currentCount = m_nodeNameToCount.get(name);
+ m_nodeNameToCount.set(name, currentCount + 1);
}
- static void collectListenersInfo(Node* node, HashMap<AtomicString, int>& result)
+ void collectListenersInfo(Node* node)
{
EventTargetData* d = node->eventTargetData();
if (!d)
++count;
}
if (count)
- result.set(name, result.get(name) + count);
+ m_eventTypeToCount.set(name, m_eventTypeToCount.get(name) + count);
}
}
- static String nodeName(Node* node)
+ int m_totalNodeCount;
+ HashMap<AtomicString, int> m_eventTypeToCount;
+ HashMap<String, int> m_nodeNameToCount;
+ StringImplIdentitySet m_domStringImplSet;
+};
+
+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()->isXHTMLDocument())
- return node->nodeName();
- return node->nodeName().lower();
+ 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);
+
+ DOMTreeStatistics domTreeStats(rootNode);
+
+ RefPtr<DOMGroup> domGroup = DOMGroup::create()
+ .setSize(domTreeStats.totalNodeCount())
+ .setTitle(rootNode->nodeType() == Node::ELEMENT_NODE ? elementTitle(static_cast<Element*>(rootNode)) : rootNode->nodeName())
+ .setNodeCount(domTreeStats.nodeCount())
+ .setListenerCount(domTreeStats.listenerCount());
+ if (rootNode->nodeType() == Node::DOCUMENT_NODE)
+ domGroup->setDocumentURI(static_cast<Document*>(rootNode)->documentURI());
+
+ m_counters->pushObject(domGroup);
}
+private:
String elementTitle(Element* element)
{
StringBuilder result;