OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 #include "core/platform/JSONValues.h" | 59 #include "core/platform/JSONValues.h" |
60 #include "core/rendering/RenderRegion.h" | 60 #include "core/rendering/RenderRegion.h" |
61 #include "wtf/CurrentTime.h" | 61 #include "wtf/CurrentTime.h" |
62 #include "wtf/HashSet.h" | 62 #include "wtf/HashSet.h" |
63 #include "wtf/Vector.h" | 63 #include "wtf/Vector.h" |
64 #include "wtf/text/CString.h" | 64 #include "wtf/text/CString.h" |
65 #include "wtf/text/StringConcatenate.h" | 65 #include "wtf/text/StringConcatenate.h" |
66 | 66 |
67 namespace CSSAgentState { | 67 namespace CSSAgentState { |
68 static const char cssAgentEnabled[] = "cssAgentEnabled"; | 68 static const char cssAgentEnabled[] = "cssAgentEnabled"; |
69 static const char isSelectorProfiling[] = "isSelectorProfiling"; | |
70 } | 69 } |
71 | 70 |
72 namespace WebCore { | 71 namespace WebCore { |
73 | 72 |
74 enum ForcePseudoClassFlags { | 73 enum ForcePseudoClassFlags { |
75 PseudoNone = 0, | 74 PseudoNone = 0, |
76 PseudoHover = 1 << 0, | 75 PseudoHover = 1 << 0, |
77 PseudoFocus = 1 << 1, | 76 PseudoFocus = 1 << 1, |
78 PseudoActive = 1 << 2, | 77 PseudoActive = 1 << 2, |
79 PseudoVisited = 1 << 3 | 78 PseudoVisited = 1 << 3 |
80 }; | 79 }; |
81 | 80 |
82 struct RuleMatchData { | |
83 String selector; | |
84 String url; | |
85 unsigned lineNumber; | |
86 double startTime; | |
87 }; | |
88 | |
89 struct RuleMatchingStats { | |
90 RuleMatchingStats() | |
91 : lineNumber(0), totalTime(0.0), hits(0), matches(0) | |
92 { | |
93 } | |
94 RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits
, unsigned matches) | |
95 : selector(data.selector), url(data.url), lineNumber(data.lineNumber), t
otalTime(totalTime), hits(hits), matches(matches) | |
96 { | |
97 } | |
98 | |
99 String selector; | |
100 String url; | |
101 unsigned lineNumber; | |
102 double totalTime; | |
103 unsigned hits; | |
104 unsigned matches; | |
105 }; | |
106 | |
107 class SelectorProfile { | |
108 WTF_MAKE_FAST_ALLOCATED; | |
109 public: | |
110 SelectorProfile() | |
111 : m_totalMatchingTimeMs(0.0) | |
112 { | |
113 } | |
114 virtual ~SelectorProfile() | |
115 { | |
116 } | |
117 | |
118 double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; } | |
119 | |
120 String makeKey(); | |
121 void startSelector(const CSSStyleRule*); | |
122 void commitSelector(bool); | |
123 void commitSelectorTime(); | |
124 PassRefPtr<TypeBuilder::CSS::SelectorProfile> toInspectorObject() const; | |
125 | |
126 private: | |
127 | |
128 // Key is "selector?url:line". | |
129 typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap; | |
130 | |
131 double m_totalMatchingTimeMs; | |
132 RuleMatchingStatsMap m_ruleMatchingStats; | |
133 RuleMatchData m_currentMatchData; | |
134 }; | |
135 | |
136 class StyleSheetAppender { | 81 class StyleSheetAppender { |
137 public: | 82 public: |
138 StyleSheetAppender(CSSStyleSheetToInspectorStyleSheet& cssStyleSheetToInspec
torStyleSheet, Vector<CSSStyleSheet*>& result) | 83 StyleSheetAppender(CSSStyleSheetToInspectorStyleSheet& cssStyleSheetToInspec
torStyleSheet, Vector<CSSStyleSheet*>& result) |
139 : m_cssStyleSheetToInspectorStyleSheet(cssStyleSheetToInspectorStyleShee
t) | 84 : m_cssStyleSheetToInspectorStyleSheet(cssStyleSheetToInspectorStyleShee
t) |
140 , m_result(result) { } | 85 , m_result(result) { } |
141 | 86 |
142 void run(CSSStyleSheet* styleSheet) | 87 void run(CSSStyleSheet* styleSheet) |
143 { | 88 { |
144 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspe
ctorStyleSheet.get(styleSheet); | 89 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspe
ctorStyleSheet.get(styleSheet); |
145 // Avoid creating m_childRuleCSSOMWrappers in the stylesheet if it is in
the process of re-parsing. | 90 // Avoid creating m_childRuleCSSOMWrappers in the stylesheet if it is in
the process of re-parsing. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 result |= PseudoHover; | 130 result |= PseudoHover; |
186 else if (pseudoClass == focus) | 131 else if (pseudoClass == focus) |
187 result |= PseudoFocus; | 132 result |= PseudoFocus; |
188 else if (pseudoClass == visited) | 133 else if (pseudoClass == visited) |
189 result |= PseudoVisited; | 134 result |= PseudoVisited; |
190 } | 135 } |
191 | 136 |
192 return result; | 137 return result; |
193 } | 138 } |
194 | 139 |
195 inline String SelectorProfile::makeKey() | |
196 { | |
197 return m_currentMatchData.selector + "?" + m_currentMatchData.url + ":" + St
ring::number(m_currentMatchData.lineNumber); | |
198 } | |
199 | |
200 inline void SelectorProfile::startSelector(const CSSStyleRule* rule) | |
201 { | |
202 m_currentMatchData.selector = rule->selectorText(); | |
203 CSSStyleSheet* styleSheet = rule->parentStyleSheet(); | |
204 String url = emptyString(); | |
205 if (styleSheet) { | |
206 url = InspectorStyleSheet::styleSheetURL(styleSheet); | |
207 if (url.isEmpty()) | |
208 url = InspectorDOMAgent::documentURLString(styleSheet->ownerDocument
()); | |
209 } | |
210 m_currentMatchData.url = url; | |
211 m_currentMatchData.lineNumber = rule->styleRule()->sourceLine(); | |
212 m_currentMatchData.startTime = WTF::currentTimeMS(); | |
213 } | |
214 | |
215 inline void SelectorProfile::commitSelector(bool matched) | |
216 { | |
217 double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime; | |
218 m_totalMatchingTimeMs += matchTimeMs; | |
219 | |
220 RuleMatchingStatsMap::AddResult result = m_ruleMatchingStats.add(makeKey(),
RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0)); | |
221 if (!result.isNewEntry) { | |
222 result.iterator->value.totalTime += matchTimeMs; | |
223 result.iterator->value.hits += 1; | |
224 if (matched) | |
225 result.iterator->value.matches += 1; | |
226 } | |
227 } | |
228 | |
229 inline void SelectorProfile::commitSelectorTime() | |
230 { | |
231 double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTim
e; | |
232 m_totalMatchingTimeMs += processingTimeMs; | |
233 | |
234 RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey()); | |
235 if (it == m_ruleMatchingStats.end()) | |
236 return; | |
237 | |
238 it->value.totalTime += processingTimeMs; | |
239 } | |
240 | |
241 PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject
() const | |
242 { | |
243 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry> > selector
ProfileData = TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry>::create
(); | |
244 for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin();
it != m_ruleMatchingStats.end(); ++it) { | |
245 RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS:
:SelectorProfileEntry::create() | |
246 .setSelector(it->value.selector) | |
247 .setUrl(it->value.url) | |
248 .setLineNumber(it->value.lineNumber) | |
249 .setTime(it->value.totalTime) | |
250 .setHitCount(it->value.hits) | |
251 .setMatchCount(it->value.matches); | |
252 selectorProfileData->addItem(entry.release()); | |
253 } | |
254 | |
255 RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::Selecto
rProfile::create() | |
256 .setTotalTime(totalMatchingTimeMs()) | |
257 .setData(selectorProfileData); | |
258 return result.release(); | |
259 } | |
260 | |
261 class UpdateRegionLayoutTask { | 140 class UpdateRegionLayoutTask { |
262 public: | 141 public: |
263 UpdateRegionLayoutTask(InspectorCSSAgent*); | 142 UpdateRegionLayoutTask(InspectorCSSAgent*); |
264 void scheduleFor(NamedFlow*, int documentNodeId); | 143 void scheduleFor(NamedFlow*, int documentNodeId); |
265 void unschedule(NamedFlow*); | 144 void unschedule(NamedFlow*); |
266 void reset(); | 145 void reset(); |
267 void onTimer(Timer<UpdateRegionLayoutTask>*); | 146 void onTimer(Timer<UpdateRegionLayoutTask>*); |
268 | 147 |
269 private: | 148 private: |
270 InspectorCSSAgent* m_cssAgent; | 149 InspectorCSSAgent* m_cssAgent; |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 { | 737 { |
859 ASSERT(!m_frontend); | 738 ASSERT(!m_frontend); |
860 m_frontend = frontend->css(); | 739 m_frontend = frontend->css(); |
861 } | 740 } |
862 | 741 |
863 void InspectorCSSAgent::clearFrontend() | 742 void InspectorCSSAgent::clearFrontend() |
864 { | 743 { |
865 ASSERT(m_frontend); | 744 ASSERT(m_frontend); |
866 m_frontend = 0; | 745 m_frontend = 0; |
867 resetNonPersistentData(); | 746 resetNonPersistentData(); |
868 stopSelectorProfilerImpl(0, false); | |
869 } | 747 } |
870 | 748 |
871 void InspectorCSSAgent::discardAgent() | 749 void InspectorCSSAgent::discardAgent() |
872 { | 750 { |
873 m_domAgent->setDOMListener(0); | 751 m_domAgent->setDOMListener(0); |
874 m_domAgent = 0; | 752 m_domAgent = 0; |
875 } | 753 } |
876 | 754 |
877 void InspectorCSSAgent::restore() | 755 void InspectorCSSAgent::restore() |
878 { | 756 { |
879 if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) { | 757 if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) { |
880 ErrorString error; | 758 ErrorString error; |
881 enable(&error); | 759 enable(&error); |
882 } | 760 } |
883 if (m_state->getBoolean(CSSAgentState::isSelectorProfiling)) { | |
884 String errorString; | |
885 startSelectorProfiler(&errorString); | |
886 } | |
887 } | 761 } |
888 | 762 |
889 void InspectorCSSAgent::reset() | 763 void InspectorCSSAgent::reset() |
890 { | 764 { |
891 m_idToInspectorStyleSheet.clear(); | 765 m_idToInspectorStyleSheet.clear(); |
892 m_cssStyleSheetToInspectorStyleSheet.clear(); | 766 m_cssStyleSheetToInspectorStyleSheet.clear(); |
893 m_nodeToInspectorStyleSheet.clear(); | 767 m_nodeToInspectorStyleSheet.clear(); |
894 m_documentToInspectorStyleSheet.clear(); | 768 m_documentToInspectorStyleSheet.clear(); |
895 resetNonPersistentData(); | 769 resetNonPersistentData(); |
896 } | 770 } |
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 parentRule = styleSheet->ownerRule(); | 1339 parentRule = styleSheet->ownerRule(); |
1466 if (parentRule) | 1340 if (parentRule) |
1467 break; | 1341 break; |
1468 styleSheet = styleSheet->parentStyleSheet(); | 1342 styleSheet = styleSheet->parentStyleSheet(); |
1469 } | 1343 } |
1470 } | 1344 } |
1471 } | 1345 } |
1472 return hasItems ? mediaArray : 0; | 1346 return hasItems ? mediaArray : 0; |
1473 } | 1347 } |
1474 | 1348 |
1475 void InspectorCSSAgent::startSelectorProfiler(ErrorString*) | |
1476 { | |
1477 m_currentSelectorProfile = adoptPtr(new SelectorProfile()); | |
1478 m_state->setBoolean(CSSAgentState::isSelectorProfiling, true); | |
1479 } | |
1480 | |
1481 void InspectorCSSAgent::stopSelectorProfiler(ErrorString* errorString, RefPtr<Ty
peBuilder::CSS::SelectorProfile>& result) | |
1482 { | |
1483 result = stopSelectorProfilerImpl(errorString, true); | |
1484 } | |
1485 | |
1486 PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorPro
filerImpl(ErrorString*, bool needProfile) | |
1487 { | |
1488 if (!m_state->getBoolean(CSSAgentState::isSelectorProfiling)) | |
1489 return 0; | |
1490 m_state->setBoolean(CSSAgentState::isSelectorProfiling, false); | |
1491 RefPtr<TypeBuilder::CSS::SelectorProfile> result; | |
1492 if (m_frontend && needProfile) | |
1493 result = m_currentSelectorProfile->toInspectorObject(); | |
1494 m_currentSelectorProfile.clear(); | |
1495 return result.release(); | |
1496 } | |
1497 | |
1498 void InspectorCSSAgent::willMatchRule(StyleRule* rule, InspectorCSSOMWrappers& i
nspectorCSSOMWrappers, DocumentStyleSheetCollection* styleSheetCollection) | |
1499 { | |
1500 if (m_currentSelectorProfile) | |
1501 m_currentSelectorProfile->startSelector(inspectorCSSOMWrappers.getWrappe
rForRuleInSheets(rule, styleSheetCollection)); | |
1502 } | |
1503 | |
1504 void InspectorCSSAgent::didMatchRule(bool matched) | |
1505 { | |
1506 if (m_currentSelectorProfile) | |
1507 m_currentSelectorProfile->commitSelector(matched); | |
1508 } | |
1509 | |
1510 void InspectorCSSAgent::willProcessRule(StyleRule* rule, StyleResolver* styleRes
olver) | |
1511 { | |
1512 if (m_currentSelectorProfile) | |
1513 m_currentSelectorProfile->startSelector(styleResolver->inspectorCSSOMWra
ppers().getWrapperForRuleInSheets(rule, styleResolver->document()->styleSheetCol
lection())); | |
1514 } | |
1515 | |
1516 void InspectorCSSAgent::didProcessRule() | |
1517 { | |
1518 if (m_currentSelectorProfile) | |
1519 m_currentSelectorProfile->commitSelectorTime(); | |
1520 } | |
1521 | |
1522 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Elem
ent* element) | 1349 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Elem
ent* element) |
1523 { | 1350 { |
1524 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(el
ement); | 1351 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(el
ement); |
1525 if (it != m_nodeToInspectorStyleSheet.end()) | 1352 if (it != m_nodeToInspectorStyleSheet.end()) |
1526 return it->value.get(); | 1353 return it->value.get(); |
1527 | 1354 |
1528 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() :
0; | 1355 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() :
0; |
1529 if (!style) | 1356 if (!style) |
1530 return 0; | 1357 return 0; |
1531 | 1358 |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 documentsToChange.add(element->ownerDocument()); | 1705 documentsToChange.add(element->ownerDocument()); |
1879 } | 1706 } |
1880 | 1707 |
1881 m_nodeIdToForcedPseudoState.clear(); | 1708 m_nodeIdToForcedPseudoState.clear(); |
1882 for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = docu
mentsToChange.end(); it != end; ++it) | 1709 for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = docu
mentsToChange.end(); it != end; ++it) |
1883 (*it)->setNeedsStyleRecalc(); | 1710 (*it)->setNeedsStyleRecalc(); |
1884 } | 1711 } |
1885 | 1712 |
1886 } // namespace WebCore | 1713 } // namespace WebCore |
1887 | 1714 |
OLD | NEW |