Chromium Code Reviews| Index: third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| index de9995e67a792f67b96557734130d82dbb37b010..8704ef0217059eb7c28e6fd3b5ae4e4f96d0522b 100644 |
| --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp |
| @@ -690,7 +690,7 @@ void InspectorCSSAgent::restore() { |
| if (m_state->booleanProperty(CSSAgentState::cssAgentEnabled, false)) |
| wasEnabled(); |
| if (m_state->booleanProperty(CSSAgentState::ruleRecordingEnabled, false)) |
| - setUsageTrackerStatus(true); |
| + setCoverageEnabled(true); |
| } |
| void InspectorCSSAgent::flushPendingProtocolNotifications() { |
| @@ -755,7 +755,7 @@ Response InspectorCSSAgent::disable() { |
| m_state->setBoolean(CSSAgentState::cssAgentEnabled, false); |
| m_resourceContentLoader->cancel(m_resourceContentLoaderClientId); |
| m_state->setBoolean(CSSAgentState::ruleRecordingEnabled, false); |
| - setUsageTrackerStatus(false); |
| + setCoverageEnabled(false); |
| return Response::OK(); |
| } |
| @@ -824,6 +824,8 @@ void InspectorCSSAgent::setActiveStyleSheets( |
| frontend()->styleSheetAdded( |
| newStyleSheet->buildObjectForStyleSheetInfo()); |
| } |
| + if (m_tracker && m_hadFirstCoverageRequest) |
| + m_coveragePendingStylsheets.push_back(newStyleSheet); |
| } |
| if (documentCSSStyleSheets->isEmpty()) |
| @@ -2413,81 +2415,100 @@ void InspectorCSSAgent::visitLayoutTreeNodes( |
| } |
| } |
| -void InspectorCSSAgent::setUsageTrackerStatus(bool enabled) { |
| +void InspectorCSSAgent::setCoverageEnabled(bool enabled) { |
| + if (enabled == !!m_tracker) |
| + return; |
| if (enabled) { |
| - if (!m_tracker) |
| - m_tracker = new StyleRuleUsageTracker(); |
| + m_tracker = new StyleRuleUsageTracker(); |
| + m_hadFirstCoverageRequest = false; |
| } else { |
| m_tracker = nullptr; |
| + m_coveragePendingStylsheets.clear(); |
| + m_unusedStyleRuleToCSSStyleRule.clear(); |
| } |
| - HeapVector<Member<Document>> documents = m_domAgent->documents(); |
| - for (Document* document : documents) { |
| + for (Document* document : m_domAgent->documents()) |
| document->styleEngine().setRuleUsageTracker(m_tracker); |
| - |
| - document->setNeedsStyleRecalc( |
| - SubtreeStyleChange, |
| - StyleChangeReasonForTracing::create(StyleChangeReason::Inspector)); |
| - } |
| } |
| Response InspectorCSSAgent::startRuleUsageTracking() { |
| m_state->setBoolean(CSSAgentState::ruleRecordingEnabled, true); |
| - setUsageTrackerStatus(true); |
| + setCoverageEnabled(true); |
| return Response::OK(); |
| } |
| -std::unique_ptr<protocol::CSS::RuleUsage> |
| -InspectorCSSAgent::buildObjectForRuleUsage(CSSStyleRule* rule, bool used) { |
| - InspectorStyleSheet* inspectorStyleSheet = inspectorStyleSheetForRule(rule); |
| - if (!inspectorStyleSheet) |
| - return nullptr; |
| - |
| - std::unique_ptr<protocol::CSS::RuleUsage> result = |
| - inspectorStyleSheet->buildObjectForRuleUsage(rule, used); |
| - |
| - return result; |
| -} |
| - |
| Response InspectorCSSAgent::stopRuleUsageTracking( |
| std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) { |
| - if (!m_tracker) { |
| - return Response::Error("CSS rule usage tracking is not enabled"); |
| - } |
| + Response response = takeCoverageDelta(result); |
| + setCoverageEnabled(false); |
| + return response; |
| +} |
| - *result = protocol::Array<protocol::CSS::RuleUsage>::create(); |
| +void InspectorCSSAgent::collectStyleSheetsForCoverage() { |
| + DCHECK_EQ(0UL, m_coveragePendingStylsheets.size()); |
| HeapVector<Member<Document>> documents = m_domAgent->documents(); |
| for (Document* document : documents) { |
| - HeapHashSet<Member<CSSStyleSheet>>* newSheetsVector = |
| - m_documentToCSSStyleSheets.at(document); |
| + document->setNeedsStyleRecalc( |
| + SubtreeStyleChange, |
| + StyleChangeReasonForTracing::create(StyleChangeReason::Inspector)); |
| + document->updateStyleAndLayoutTree(); |
| + } |
| + m_coveragePendingStylsheets.appendRange( |
| + m_idToInspectorStyleSheet.values().begin(), |
| + m_idToInspectorStyleSheet.values().end()); |
| +} |
| - if (!newSheetsVector) |
| - continue; |
| +Response InspectorCSSAgent::takeCoverageDelta( |
| + std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) { |
| + if (!m_tracker) |
| + return Response::Error("CSS rule usage tracking is not enabled"); |
| - for (auto sheet : *newSheetsVector) { |
| - InspectorStyleSheet* styleSheet = |
| - m_cssStyleSheetToInspectorStyleSheet.at(sheet); |
| - const CSSRuleVector ruleVector = styleSheet->flatRules(); |
| - for (auto rule : ruleVector) { |
| - if (rule->type() != CSSRule::kStyleRule) |
| - continue; |
| + if (!m_hadFirstCoverageRequest) { |
| + m_hadFirstCoverageRequest = true; |
| + collectStyleSheetsForCoverage(); |
| + } |
| - CSSStyleRule* cssRule = static_cast<CSSStyleRule*>(rule.get()); |
| + HeapVector<Member<StyleRule>> coverageDeltaVector = m_tracker->takeDelta(); |
| + HeapHashSet<Member<StyleRule>> coverageDelta; |
| + for (auto item : coverageDeltaVector) |
| + coverageDelta.insert(item); |
| - StyleRule* styleRule = cssRule->styleRule(); |
| + *result = protocol::Array<protocol::CSS::RuleUsage>::create(); |
| + for (auto styleSheet : m_coveragePendingStylsheets) { |
| + const CSSRuleVector& ruleVector = styleSheet->flatRules(); |
| + for (auto rule : ruleVector) { |
| + if (rule->type() != CSSRule::kStyleRule) |
| + continue; |
| - std::unique_ptr<protocol::CSS::RuleUsage> protocolRule = |
| - buildObjectForRuleUsage(cssRule, m_tracker->contains(styleRule)); |
| - if (!protocolRule) |
| - continue; |
| + StyleRule* styleRule = |
| + static_cast<CSSStyleRule*>(rule.get())->styleRule(); |
| + bool used = !!coverageDelta.take(styleRule); |
|
alph
2017/03/20 20:48:31
contains
|
| + std::unique_ptr<protocol::CSS::RuleUsage> ruleUsageObject = |
| + styleSheet->buildObjectForRuleUsage(rule, used); |
| - result->get()->addItem(std::move(protocolRule)); |
| - } |
| + if (ruleUsageObject) |
| + (*result)->addItem(std::move(ruleUsageObject)); |
| + if (!used) |
| + m_unusedStyleRuleToCSSStyleRule.set(styleRule, asCSSStyleRule(rule)); |
| } |
| } |
| + m_coveragePendingStylsheets.clear(); |
| - setUsageTrackerStatus(false); |
| + for (Member<StyleRule> rule : coverageDelta) { |
| + HeapHashMap<Member<const StyleRule>, Member<CSSStyleRule>>::iterator it = |
|
alph
2017/03/20 20:48:31
nit: auto it =
|
| + m_unusedStyleRuleToCSSStyleRule.find(rule); |
| + if (it == m_unusedStyleRuleToCSSStyleRule.end()) |
| + continue; |
| + InspectorStyleSheet* styleSheet = inspectorStyleSheetForRule(it->value); |
| + if (!styleSheet) |
| + continue; |
| + std::unique_ptr<protocol::CSS::RuleUsage> ruleUsageObject = |
| + styleSheet->buildObjectForRuleUsage(it->value, true); |
| + if (ruleUsageObject) |
| + (*result)->addItem(std::move(ruleUsageObject)); |
| + m_unusedStyleRuleToCSSStyleRule.remove(it); |
| + } |
| return Response::OK(); |
| } |
| @@ -2506,6 +2527,8 @@ DEFINE_TRACE(InspectorCSSAgent) { |
| visitor->trace(m_nodeToInspectorStyleSheet); |
| visitor->trace(m_inspectorUserAgentStyleSheet); |
| visitor->trace(m_tracker); |
| + visitor->trace(m_unusedStyleRuleToCSSStyleRule); |
| + visitor->trace(m_coveragePendingStylsheets); |
| InspectorBaseAgent::trace(visitor); |
| } |