| 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..7d289732c75e32a038d481335d70fa5e1d7839a9 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_coveragePendingStylesheets.push_back(newStyleSheet);
|
| }
|
|
|
| if (documentCSSStyleSheets->isEmpty())
|
| @@ -2413,82 +2415,110 @@ 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_coveragePendingStylesheets.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;
|
| +Response InspectorCSSAgent::stopRuleUsageTracking(
|
| + std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) {
|
| + Response response = takeCoverageDelta(result);
|
| + setCoverageEnabled(false);
|
| + return response;
|
| +}
|
|
|
| - std::unique_ptr<protocol::CSS::RuleUsage> result =
|
| - inspectorStyleSheet->buildObjectForRuleUsage(rule, used);
|
| +void InspectorCSSAgent::collectStyleSheetsForCoverage() {
|
| + DCHECK_EQ(0UL, m_coveragePendingStylesheets.size());
|
|
|
| - return result;
|
| + HeapVector<Member<Document>> documents = m_domAgent->documents();
|
| + for (Document* document : documents) {
|
| + document->setNeedsStyleRecalc(
|
| + SubtreeStyleChange,
|
| + StyleChangeReasonForTracing::create(StyleChangeReason::Inspector));
|
| + document->updateStyleAndLayoutTree();
|
| + }
|
| + m_coveragePendingStylesheets.appendRange(
|
| + m_idToInspectorStyleSheet.values().begin(),
|
| + m_idToInspectorStyleSheet.values().end());
|
| }
|
|
|
| -Response InspectorCSSAgent::stopRuleUsageTracking(
|
| +Response InspectorCSSAgent::takeCoverageDelta(
|
| std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) {
|
| - if (!m_tracker) {
|
| + if (!m_tracker)
|
| return Response::Error("CSS rule usage tracking is not enabled");
|
| +
|
| + if (!m_hadFirstCoverageRequest) {
|
| + m_hadFirstCoverageRequest = true;
|
| + collectStyleSheetsForCoverage();
|
| }
|
|
|
| + StyleRuleUsageTracker::RuleListByStyleSheet coverageDelta =
|
| + m_tracker->takeDelta();
|
| +
|
| *result = protocol::Array<protocol::CSS::RuleUsage>::create();
|
| + for (auto styleSheet : m_coveragePendingStylesheets) {
|
| + HeapVector<Member<const StyleRule>> usedRulesForStylesheet =
|
| + coverageDelta.take(styleSheet->pageStyleSheet());
|
| + HeapHashSet<Member<const StyleRule>> usedRules;
|
| + for (auto item : usedRulesForStylesheet)
|
| + usedRules.insert(item);
|
| +
|
| + const CSSRuleVector& ruleVector = styleSheet->flatRules();
|
| + for (auto rule : ruleVector) {
|
| + if (rule->type() != CSSRule::kStyleRule)
|
| + continue;
|
|
|
| - HeapVector<Member<Document>> documents = m_domAgent->documents();
|
| - for (Document* document : documents) {
|
| - HeapHashSet<Member<CSSStyleSheet>>* newSheetsVector =
|
| - m_documentToCSSStyleSheets.at(document);
|
| + const StyleRule* styleRule =
|
| + static_cast<CSSStyleRule*>(rule.get())->styleRule();
|
| + bool used = usedRules.contains(styleRule);
|
| + std::unique_ptr<protocol::CSS::RuleUsage> ruleUsageObject =
|
| + styleSheet->buildObjectForRuleUsage(rule, used);
|
|
|
| - if (!newSheetsVector)
|
| - continue;
|
| + if (ruleUsageObject)
|
| + (*result)->addItem(std::move(ruleUsageObject));
|
| + }
|
| + }
|
| + m_coveragePendingStylesheets.clear();
|
|
|
| - for (auto sheet : *newSheetsVector) {
|
| - InspectorStyleSheet* styleSheet =
|
| - m_cssStyleSheetToInspectorStyleSheet.at(sheet);
|
| - const CSSRuleVector ruleVector = styleSheet->flatRules();
|
| - for (auto rule : ruleVector) {
|
| - if (rule->type() != CSSRule::kStyleRule)
|
| + for (const auto& entry : coverageDelta) {
|
| + const CSSStyleSheet* cssStyleSheet = entry.key.get();
|
| + InspectorStyleSheet* styleSheet = m_cssStyleSheetToInspectorStyleSheet.at(
|
| + const_cast<CSSStyleSheet*>(cssStyleSheet));
|
| + if (!styleSheet)
|
| + continue;
|
| + const CSSRuleVector& rules = styleSheet->flatRules();
|
| + for (auto usedRule : entry.value) {
|
| + for (auto cssRule : rules) {
|
| + if (cssRule->type() != CSSRule::kStyleRule)
|
| continue;
|
| -
|
| - CSSStyleRule* cssRule = static_cast<CSSStyleRule*>(rule.get());
|
| -
|
| - StyleRule* styleRule = cssRule->styleRule();
|
| -
|
| - std::unique_ptr<protocol::CSS::RuleUsage> protocolRule =
|
| - buildObjectForRuleUsage(cssRule, m_tracker->contains(styleRule));
|
| - if (!protocolRule)
|
| + CSSStyleRule* cssStyleRule = asCSSStyleRule(cssRule);
|
| + if (cssStyleRule->styleRule() != usedRule)
|
| continue;
|
| -
|
| - result->get()->addItem(std::move(protocolRule));
|
| + if (std::unique_ptr<protocol::CSS::RuleUsage> ruleUsageObject =
|
| + styleSheet->buildObjectForRuleUsage(cssStyleRule, true)) {
|
| + (*result)->addItem(std::move(ruleUsageObject));
|
| + }
|
| + break;
|
| }
|
| }
|
| }
|
|
|
| - setUsageTrackerStatus(false);
|
| -
|
| return Response::OK();
|
| }
|
|
|
| @@ -2506,6 +2536,7 @@ DEFINE_TRACE(InspectorCSSAgent) {
|
| visitor->trace(m_nodeToInspectorStyleSheet);
|
| visitor->trace(m_inspectorUserAgentStyleSheet);
|
| visitor->trace(m_tracker);
|
| + visitor->trace(m_coveragePendingStylesheets);
|
| InspectorBaseAgent::trace(visitor);
|
| }
|
|
|
|
|