From 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 6 Oct 2020 12:48:11 +0200 Subject: BASELINE: Update Chromium to 84.0.4147.141 Change-Id: Ib85eb4cfa1cbe2b2b81e5022c8cad5c493969535 Reviewed-by: Allan Sandfeld Jensen --- .../blink/renderer/core/inspector/BUILD.gn | 2 + .../renderer/core/inspector/dom_traversal_utils.cc | 46 +++ .../renderer/core/inspector/dom_traversal_utils.h | 22 ++ .../core/inspector/inspect_tool_highlight.html | 327 ++++++++++++++++++--- .../blink/renderer/core/inspector/inspect_tools.cc | 8 +- .../blink/renderer/core/inspector/inspect_tools.h | 1 + .../core/inspector/inspector_animation_agent.cc | 20 +- .../core/inspector/inspector_audits_agent.cc | 225 +++++++++++--- .../renderer/core/inspector/inspector_css_agent.cc | 76 +++++ .../renderer/core/inspector/inspector_css_agent.h | 5 + .../renderer/core/inspector/inspector_dom_agent.cc | 10 +- .../core/inspector/inspector_dom_snapshot_agent.cc | 122 ++++---- .../core/inspector/inspector_dom_snapshot_agent.h | 12 +- .../core/inspector/inspector_emulation_agent.cc | 73 ++++- .../core/inspector/inspector_emulation_agent.h | 9 +- .../renderer/core/inspector/inspector_highlight.cc | 217 +++++++++++--- .../renderer/core/inspector/inspector_highlight.h | 24 ++ .../renderer/core/inspector/inspector_issue.cc | 18 +- .../renderer/core/inspector/inspector_issue.h | 5 +- .../core/inspector/inspector_issue_storage.cc | 6 + .../core/inspector/inspector_issue_storage.h | 3 + .../core/inspector/inspector_media_agent.cc | 120 +++++--- .../core/inspector/inspector_media_agent.h | 6 +- .../core/inspector/inspector_media_context_impl.cc | 129 ++++---- .../core/inspector/inspector_media_context_impl.h | 44 ++- .../core/inspector/inspector_network_agent.cc | 68 +++-- .../core/inspector/inspector_network_agent.h | 1 + .../core/inspector/inspector_overlay_agent.cc | 281 +++++++++++++----- .../core/inspector/inspector_overlay_agent.h | 38 ++- .../core/inspector/inspector_page_agent.cc | 30 +- .../renderer/core/inspector/inspector_page_agent.h | 3 +- .../inspector/inspector_resource_content_loader.cc | 5 +- .../core/inspector/inspector_style_sheet.cc | 2 +- .../core/inspector/legacy_dom_snapshot_agent.cc | 9 +- .../core/inspector/network_resources_data.cc | 2 +- .../core/inspector/network_resources_data.h | 5 +- .../renderer/core/inspector/thread_debugger.cc | 8 +- .../core/inspector/worker_inspector_controller.cc | 8 +- 38 files changed, 1514 insertions(+), 476 deletions(-) create mode 100644 chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc create mode 100644 chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h (limited to 'chromium/third_party/blink/renderer/core/inspector') diff --git a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn index a61b241165b..e8a912f1766 100644 --- a/chromium/third_party/blink/renderer/core/inspector/BUILD.gn +++ b/chromium/third_party/blink/renderer/core/inspector/BUILD.gn @@ -28,6 +28,8 @@ blink_core_sources("inspector") { "dom_editor.h", "dom_patch_support.cc", "dom_patch_support.h", + "dom_traversal_utils.cc", + "dom_traversal_utils.h", "identifiers_factory.cc", "identifiers_factory.h", "inspect_tools.cc", diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc new file mode 100644 index 00000000000..71a752e0ed9 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.cc @@ -0,0 +1,46 @@ +#include "third_party/blink/renderer/core/inspector/dom_traversal_utils.h" + +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" +#include "third_party/blink/renderer/core/dom/node.h" +#include "third_party/blink/renderer/core/dom/shadow_root.h" + +namespace blink { +namespace dom_traversal_utils { + +Node* FirstChild(const Node& node, bool include_user_agent_shadow_tree) { + DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot()); + if (!include_user_agent_shadow_tree) { + ShadowRoot* shadow_root = node.GetShadowRoot(); + if (shadow_root && shadow_root->GetType() == ShadowRootType::kUserAgent) { + Node* child = node.firstChild(); + while (child && !child->CanParticipateInFlatTree()) + child = child->nextSibling(); + return child; + } + } + return FlatTreeTraversal::FirstChild(node); +} + +// static +bool HasChildren(const Node& node, bool include_user_agent_shadow_tree) { + return FirstChild(node, include_user_agent_shadow_tree); +} + +// static +Node* NextSibling(const Node& node, bool include_user_agent_shadow_tree) { + DCHECK(include_user_agent_shadow_tree || !node.IsInUserAgentShadowRoot()); + if (!include_user_agent_shadow_tree) { + if (node.ParentElementShadowRoot() && + node.ParentElementShadowRoot()->GetType() == + ShadowRootType::kUserAgent) { + Node* sibling = node.nextSibling(); + while (sibling && !sibling->CanParticipateInFlatTree()) + sibling = sibling->nextSibling(); + return sibling; + } + } + return FlatTreeTraversal::NextSibling(node); +} + +} // namespace dom_traversal_utils +} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h new file mode 100644 index 00000000000..d4a52a40844 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/inspector/dom_traversal_utils.h @@ -0,0 +1,22 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_ + +namespace blink { + +class Node; + +namespace dom_traversal_utils { + +// These are deprecated, do not use in new code. Use FlatTreeTraversal directly. +Node* FirstChild(const Node& node, bool include_user_agent_shadow_tree); +bool HasChildren(const Node& node, bool include_user_agent_shadow_tree); +Node* NextSibling(const Node& node, bool include_user_agent_shadow_tree); + +} // namespace dom_traversal_utils +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DOM_TRAVERSAL_UTILS_H_ diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html b/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html index 2f9157c4a22..b5c7dbdb50f 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html +++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tool_highlight.html @@ -66,7 +66,7 @@ body { border-radius: 3px; box-sizing: border-box; min-width: 100px; - max-width: 300px; + max-width: min(300px, 100% - 4px); z-index: 1; background-clip: padding-box; will-change: transform; @@ -87,6 +87,20 @@ body { visibility: var(--arrow-visibility); } +.element-info-section { + margin-top: 12px; + margin-bottom: 6px; +} + +.section-name { + color: #333; + font-weight: 500; + font-size: 10px; + text-transform: uppercase; + letter-spacing: .05em; + line-height: 12px; +} + .element-info { display: flex; flex-direction: column; @@ -109,13 +123,20 @@ body { line-height: 19px; } -.element-info-contrast-row { +.separator-container { + display: flex; + align-items: center; + flex: auto; + margin-left: 7px; +} + +.separator { border-top: 1px solid #ddd; - padding-top: 5px; - margin-top: 5px; + width: 100%; } .element-info-name { + flex-shrink: 0; color: #666; } @@ -132,11 +153,21 @@ body { .element-info-value-contrast { display: flex; + align-items: center; text-align: right; color: rgb(48, 57, 66); margin-left: 10px; } +.element-info-value-contrast .a11y-icon { + margin-left: 8px; +} + +.element-info-value-icon { + display: flex; + align-items: center; +} + .element-info-value-text { text-align: right; color: rgb(48, 57, 66); @@ -205,16 +236,20 @@ body { .a11y-icon { width: 16px; height: 16px; - margin-left: 2px; background-repeat: no-repeat; + display: inline-block; +} + +.a11y-icon-not-ok { + background-image: url('data:image/svg+xml,'); } .a11y-icon-warning { - background-image: url("data:image/svg+xml;charset=UTF-8, %3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 18 18' fill='%23ffc107'%3e%3cpath d='M0 0h18v18H0z' fill='none'/%3e%3cpath d='M.5 16h17L9 1 .5 16zm9.5-2H8v-2h2v2zm0-3H8V7h2v4z'/%3e%3c/svg%3e "); + background-image: url('data:image/svg+xml,'); } .a11y-icon-ok { - background-image: url("data:image/svg+xml;charset=UTF-8, %3csvg xmlns='http://www.w3.org/2000/svg' width='16px' height='16px' viewBox='0 0 48 48' fill='%2300a000'%3e%3cpath d='M0 0h48v48H0z' fill='none'/%3e%3cpath d='M18 32.34L9.66 24l-2.83 2.83L18 38l24-24-2.83-2.83z'/%3e%3c/svg%3e"); + background-image: url('data:image/svg+xml,'); } @media (forced-colors: active) { @@ -233,13 +268,14 @@ body { } .color-swatch-inner, .contrast-text, - .element-info-contrast-row { + .separator { border-color: Highlight; } .dimensions, .element-info-name, .element-info-value-color, .element-info-value-contrast, + .element-info-value-icon, .element-info-value-text, .material-tag-name, .material-class-name, @@ -407,14 +443,68 @@ function parseHexa(hexa) { } /** - * @param {!String} hexa + * TODO(alexrudenko): import this and other color helpers from DevTools + * @param {!Array} rgba * @return {!Array} */ -function normalizeColorString(hexa) { - if (hexa.endsWith("FF")) +function rgbaToHsla(rgba) { + const [r, g, b] = rgba; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const diff = max - min; + const sum = max + min; + + let h; + if (min === max) { + h = 0; + } else if (r === max) { + h = ((1 / 6 * (g - b) / diff) + 1) % 1; + } else if (g === max) { + h = (1 / 6 * (b - r) / diff) + 1 / 3; + } else { + h = (1 / 6 * (r - g) / diff) + 2 / 3; + } + + const l = 0.5 * sum; + + let s; + if (l === 0) { + s = 0; + } else if (l === 1) { + s = 0; + } else if (l <= 0.5) { + s = diff / sum; + } else { + s = diff / (2 - sum); + } + + return [h, s, l, rgba[3]]; +} + +/** + * @param {!String} hexa + * @param {!String} colorFormat + * @return {!String} + */ +function formatColor(hexa, colorFormat) { + if (colorFormat === 'rgb') { + const [r, g, b, a] = parseHexa(hexa); + // rgb(r g b [ / a]) + return `rgb(${(r * 255).toFixed()} ${(g * 255).toFixed()} ${(b * 255).toFixed()}${a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`; + } + + if (colorFormat === 'hsl') { + const [h, s, l, a] = rgbaToHsla(parseHexa(hexa)); + // hsl(hdeg s l [ / a]) + return `hsl(${Math.round(h * 360)}deg ${Math.round(s * 100)} ${Math.round(l * 100)}${a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`; + } + + if (hexa.endsWith("FF")) { + // short hex if no alpha return hexa.substr(0, 7); - const [r, g, b, a] = parseHexa(hexa); - return `rgba(${(r * 255).toFixed()}, ${(g * 255).toFixed()}, ${(b * 255).toFixed()}, ${Math.round(a * 100) / 100})`; + } + + return hexa; } /** @@ -484,7 +574,7 @@ function computeIsLargeFont(contrast) { return fontSizePt >= 18; } -function _createElementDescription(elementInfo) +function _createElementDescription(elementInfo, colorFormat) { const elementInfoElement = createElement("div", "element-info"); const elementInfoHeaderElement = elementInfoElement.createChild("div", "element-info-header"); @@ -513,7 +603,7 @@ function _createElementDescription(elementInfo) const color = style["color"]; if (color && color !== "#00000000") - addColorRow("Color", color); + addColorRow("Color", color, colorFormat); const fontFamily = style["font-family"]; const fontSize = style["font-size"]; @@ -522,7 +612,7 @@ function _createElementDescription(elementInfo) const bgcolor = style["background-color"]; if (bgcolor && bgcolor !== "#00000000") - addColorRow("Background", bgcolor); + addColorRow("Background", bgcolor, colorFormat); const margin = style["margin"]; if (margin && margin !== "0px") @@ -533,12 +623,36 @@ function _createElementDescription(elementInfo) addTextRow("Padding", padding); const cbgColor = elementInfo.contrast ? elementInfo.contrast.backgroundColor : null; - if (color && color !== "#00000000" && cbgColor && cbgColor !== "#00000000") - addContrastRow(style["color"], elementInfo.contrast); + const hasContrastInfo = color && color !== "#00000000" && cbgColor && cbgColor !== "#00000000"; - function addRow(name, rowClassName, valueClassName) { + if (elementInfo.showAccessibilityInfo) { + addSection("Accessibility"); + + if (hasContrastInfo) + addContrastRow(style["color"], elementInfo.contrast); + + addTextRow("Name", elementInfo.accessibleName); + addTextRow("Role", elementInfo.accessibleRole); + addIconRow("Keyboard-focusable", elementInfo.isKeyboardFocusable ? "a11y-icon a11y-icon-ok" : "a11y-icon a11y-icon-not-ok"); + } + + function ensureElementInfoBody() { if (!elementInfoBodyElement) elementInfoBodyElement = elementInfoElement.createChild("div", "element-info-body") + } + + function addSection(name) { + ensureElementInfoBody(); + const rowElement = elementInfoBodyElement.createChild("div", "element-info-row element-info-section"); + const nameElement = rowElement.createChild("div", "section-name"); + nameElement.textContent = name; + const separatorElement = rowElement + .createChild("div", "separator-container") + .createChild("div", "separator"); + } + + function addRow(name, rowClassName, valueClassName) { + ensureElementInfoBody(); const rowElement = elementInfoBodyElement.createChild("div", "element-info-row"); if (rowClassName) rowElement.classList.add(rowClassName); @@ -548,22 +662,26 @@ function _createElementDescription(elementInfo) return rowElement.createChild("div", valueClassName || ""); } + function addIconRow(name, value) { + addRow(name, "", "element-info-value-icon").createChild('div', value); + } + function addTextRow(name, value) { addRow(name, "", "element-info-value-text").createTextChild(value); } - function addColorRow(name, color) { + function addColorRow(name, color, colorFormat) { const valueElement = addRow(name, "", "element-info-value-color"); const swatch = valueElement.createChild("div", "color-swatch"); const inner = swatch.createChild("div", "color-swatch-inner"); inner.style.backgroundColor = color; - valueElement.createTextChild(normalizeColorString(color)); + valueElement.createTextChild(formatColor(color, colorFormat)); } function addContrastRow(fgColor, contrast) { const ratio = contrastRatio(parseHexa(fgColor), parseHexa(contrast.backgroundColor)); const threshold = computeIsLargeFont(contrast) ? 3.0 : 4.5; - const valueElement = addRow("Contrast", "element-info-contrast-row", "element-info-value-contrast"); + const valueElement = addRow("Contrast", "", "element-info-value-contrast"); const sampleText = valueElement.createChild("div", "contrast-text"); sampleText.style.color = fgColor; sampleText.style.backgroundColor = contrast.backgroundColor; @@ -576,11 +694,11 @@ function _createElementDescription(elementInfo) return elementInfoElement; } -function _drawElementTitle(elementInfo, bounds) +function _drawElementTitle(elementInfo, bounds, colorFormat) { const tooltipContainer = document.getElementById("tooltip-container"); tooltipContainer.removeChildren(); - _createMaterialTooltip(tooltipContainer, bounds, _createElementDescription(elementInfo), true); + _createMaterialTooltip(tooltipContainer, bounds, _createElementDescription(elementInfo, colorFormat), true); } function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow) @@ -651,14 +769,17 @@ function _createMaterialTooltip(parentElement, bounds, contentElement, withArrow tooltipContent.style.setProperty('--arrow-left', (arrowX - boxX) + 'px'); } -function _drawRulers(context, bounds, rulerAtRight, rulerAtBottom) +function _drawRulers(context, bounds, rulerAtRight, rulerAtBottom, color, dash) { context.save(); var width = canvasWidth; var height = canvasHeight; - context.strokeStyle = "rgba(128, 128, 128, 0.3)"; + context.strokeStyle = color || "rgba(128, 128, 128, 0.3)"; context.lineWidth = 1; context.translate(0.5, 0.5); + if (dash) { + context.setLineDash([3, 3]); + } if (rulerAtRight) { for (var y in bounds.rightmostXForY) { @@ -779,22 +900,150 @@ function emptyBounds() function _drawLayoutGridHighlight(highlight, context) { + // Draw Grid border + if (highlight.gridHighlightConfig.gridBorderColor) { + context.save(); + context.translate(0.5, 0.5); + context.lineWidth = 0; + if (highlight.gridHighlightConfig.gridBorderDash) { + context.setLineDash([3, 3]); + } + context.strokeStyle = highlight.gridHighlightConfig.gridBorderColor; + context.stroke(buildPath(highlight.gridBorder, emptyBounds())); + context.restore(); + } + + // Draw Cell Border + if (highlight.gridHighlightConfig.cellBorderColor) { + const rowBounds = emptyBounds(); + const columnBounds = emptyBounds(); + const rowPath = buildPath(highlight.rows, rowBounds); + const columnPath = buildPath(highlight.columns, columnBounds); + context.save(); + context.translate(0.5, 0.5); + if (highlight.gridHighlightConfig.cellBorderDash) { + context.setLineDash([3, 3]); + } + context.lineWidth = 0; + context.strokeStyle = highlight.gridHighlightConfig.cellBorderColor; + + context.save(); + context.clip(columnPath); + context.stroke(rowPath); + context.restore(); + + context.save(); + context.clip(rowPath); + context.stroke(columnPath); + context.restore(); + + context.restore(); + + if (highlight.gridHighlightConfig.showGridExtensionLines) { + // Extend row gap lines left/up. + _drawRulers(context, rowBounds, /* rulerAtRight */ false, /* rulerAtBottom */ false, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash); + // Extend row gap right/down. + _drawRulers(context, rowBounds, /* rulerAtRight */ true, /* rulerAtBottom */ true, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash); + // Extend column lines left/up. + _drawRulers(context, columnBounds, /* rulerAtRight */ false, /* rulerAtBottom */ false, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash); + // Extend column right/down. + _drawRulers(context, columnBounds, /* rulerAtRight */ true, /* rulerAtBottom */ true, highlight.gridHighlightConfig.cellBorderColor, highlight.gridHighlightConfig.cellBorderDash); + } + } + + // Row Gaps + if (highlight.gridHighlightConfig.rowGapColor) { + context.save(); + context.translate(0.5, 0.5); + context.lineWidth = 0; + context.fillStyle = highlight.gridHighlightConfig.rowGapColor; + let bounds = emptyBounds(); + const path = buildPath(highlight.rowGaps, bounds); + if (highlight.gridHighlightConfig.rowHatchColor) { + hatchFillPath(context, path, bounds, 10, highlight.gridHighlightConfig.rowHatchColor, /* flipDirection */ true); + } + context.fill(path); + context.restore(); + } + + // Column Gaps + if (highlight.gridHighlightConfig.columnGapColor) { + context.save(); + context.translate(0.5, 0.5); + context.lineWidth = 0; + context.fillStyle = highlight.gridHighlightConfig.columnGapColor; + let bounds = emptyBounds(); + const path = buildPath(highlight.columnGaps, bounds); + if (highlight.gridHighlightConfig.columnHatchColor) { + hatchFillPath(context, path, bounds, 10, highlight.gridHighlightConfig.columnHatchColor); + } + context.fill(path); + context.restore(); + } +} + +/** + * Draw line hatching at a 45 degree angle for a given + * path. + * __________ + * |\ \ \ | + * | \ \ \| + * | \ \ | + * |\ \ \ | + * ********** + * + * @param {CanvasRenderingContext2D} context + * @param {Path2D} path + * @param {Object} bounds + * @param {delta} delta - vertical gap between hatching lines in pixels + * @param {string} color + * @param {boolean=} flipDirection - lines are drawn from top right to bottom left + * + */ +function hatchFillPath(context, path, bounds, delta, color, flipDirection) { + const dx = bounds.maxX - bounds.minX; + const dy = bounds.maxY - bounds.minY; + context.rect(bounds.minX, bounds.minY, dx, dy); context.save(); - context.translate(0.5, 0.5); - context.setLineDash([3, 3]); - context.lineWidth = 0; - context.strokeStyle = highlight.color; - context.stroke(buildPath(highlight.cells, emptyBounds())); + context.clip(path); + context.setLineDash([5, 3]); + const majorAxis = Math.max(dx, dy); + context.strokeStyle = color; + if (flipDirection) { + for (let i = -majorAxis; i < majorAxis; i += delta) { + context.beginPath(); + context.moveTo(bounds.maxX - i , bounds.minY); + context.lineTo(bounds.maxX - dy - i, bounds.maxY); + context.stroke(); + } + } else { + for (let i = -majorAxis; i < majorAxis; i += delta) { + context.beginPath(); + context.moveTo(i + bounds.minX, bounds.minY); + context.lineTo(dy + i + bounds.minX, bounds.maxY); + context.stroke(); + } + } context.restore(); } -function clipLayoutGridCells(highlight) { +function clipLayoutGridCells(highlight, context) { + // It may seem simpler to, before drawing the desired path, call context.clip() + // with the rows and then with the columns. However, the 2nd context.clip() call + // would try to find the intersection of the rows and columns, which is way too + // expensive if the grid is huge, e.g. a 1000x1000 grid has 1M cells. + // Therefore, it's better to draw the path first, set the globalCompositeOperation + // so that the existing canvas content is kept where it overlaps with new content, + // and then draw the rows and columns. if (highlight.gridInfo) { for (const grid of highlight.gridInfo) { if (!grid.isPrimaryGrid) continue; - const path = buildPath(grid.cells, emptyBounds()); - context.clip(path); + context.save(); + context.globalCompositeOperation = "destination-in"; + drawPath(context, grid.rows, "red", null, emptyBounds()); + drawPath(context, grid.columns, "red", null, emptyBounds()); + context.restore(); } } } @@ -808,15 +1057,15 @@ function drawHighlight(highlight, context) for (var paths = highlight.paths.slice(); paths.length;) { var path = paths.pop(); - // Clip content quad using the data grid cells info to create white stripes. context.save(); - if (path.name === "content") - clipLayoutGridCells(highlight); drawPath(context, path.path, path.fillColor, path.outlineColor, bounds); if (paths.length) { context.globalCompositeOperation = "destination-out"; drawPath(context, paths[paths.length - 1].path, "red", null, bounds); } + // Clip content quad using the data grid cells info to create white stripes. + if (path.name === "content") + clipLayoutGridCells(highlight, context); context.restore(); } context.restore(); @@ -834,7 +1083,7 @@ function drawHighlight(highlight, context) _drawRulers(context, bounds, rulerAtRight, rulerAtBottom); if (highlight.elementInfo) - _drawElementTitle(highlight.elementInfo, bounds); + _drawElementTitle(highlight.elementInfo, bounds, highlight.colorFormat); } if (highlight.gridInfo) { for (var grid of highlight.gridInfo) @@ -851,7 +1100,7 @@ function test() { drawHighlight( {"paths":[{"path":["M",122,133.796875,"L",822,133.796875,"L",822,208.796875,"L",122,208.796875,"Z"], "fillColor":"rgba(111, 168, 220, 0.658823529411765)","name":"content"}, {"path":["M",122,113.796875,"L",822,113.796875,"L",822,228.796875,"L",122,228.796875,"Z"],"fillColor":"rgba(246, 178, 107, 0.66)","name":"margin"}],"showRulers":false,"showExtensionLines":false, - "elementInfo":{"tagName":"button","className":"class.name", "idValue":"download-hero","nodeWidth":"700","nodeHeight":"75","style":{"color":"#FFFFFFFF","font-family":"\"Product Sans\", \"Open Sans\", Roboto, Arial, \"Product Sans\", \"Open Sans\", Roboto, Arial","font-size":"20px","line-height":"25px","padding":"0px","margin":"20px 0px","background-color":"#00000000"},"contrast":{"fontSize":"20px","fontWeight":"400","backgroundColor":"#F9B826BF"}}, showExtensionLines: true, showRulers: true}); + "elementInfo":{"tagName":"button","className":"class.name", "idValue":"download-hero","nodeWidth":"700","nodeHeight":"75","style":{"color":"#FFFFFFFF","font-family":"\"Product Sans\", \"Open Sans\", Roboto, Arial, \"Product Sans\", \"Open Sans\", Roboto, Arial","font-size":"20px","line-height":"25px","padding":"0px","margin":"20px 0px","background-color":"#00000000"},"contrast":{"fontSize":"20px","fontWeight":"400","backgroundColor":"#F9B826BF"},"isKeyboardFocusable":false,"accessibleName":"name","accessibleRole":"role","showAccessibilityInfo":true}, showExtensionLines: true, showRulers: true, colorFormat: "hsl"}); } diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc index 866afa057bf..502c7676fca 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc +++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.cc @@ -142,8 +142,8 @@ void SearchingForNodeTool::Draw(float scale) { bool SearchingForNodeTool::HandleInputEvent(LocalFrameView* frame_view, const WebInputEvent& input_event, bool* swallow_next_mouse_up) { - if (input_event.GetType() == WebInputEvent::kGestureScrollBegin || - input_event.GetType() == WebInputEvent::kGestureScrollUpdate) { + if (input_event.GetType() == WebInputEvent::Type::kGestureScrollBegin || + input_event.GetType() == WebInputEvent::Type::kGestureScrollUpdate) { hovered_node_.Clear(); event_target_node_.Clear(); overlay_->ScheduleUpdate(); @@ -297,6 +297,10 @@ bool NodeHighlightTool::HideOnHideHighlight() { return true; } +bool NodeHighlightTool::HideOnMouseMove() { + return true; +} + void NodeHighlightTool::Draw(float scale) { DrawNode(); DrawMatchingSelector(); diff --git a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h index 5117ebd7760..3d19e9ada1b 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h +++ b/chromium/third_party/blink/renderer/core/inspector/inspect_tools.h @@ -75,6 +75,7 @@ class NodeHighlightTool : public InspectTool { private: bool ForwardEventsToOverlay() override; + bool HideOnMouseMove() override; bool HideOnHideHighlight() override; void Draw(float scale) override; void DrawNode(); diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc index 786c300e858..734a3349e14 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc +++ b/chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc @@ -193,7 +193,7 @@ InspectorAnimationAgent::BuildObjectForAnimation(blink::Animation& animation) { .setPlayState(animation.PlayStateString()) .setPlaybackRate(animation.playbackRate()) .setStartTime(NormalizedStartTime(animation)) - .setCurrentTime(animation.currentTime()) + .setCurrentTime(animation.currentTime().value_or(Timing::NullValue())) .setType(animation_type) .build(); if (animation_type != AnimationType::WebAnimation) @@ -225,10 +225,10 @@ Response InspectorAnimationAgent::getCurrentTime(const String& id, animation = id_to_animation_clone_.at(id); if (animation->Paused() || !animation->timeline()->IsActive()) { - *current_time = animation->currentTime(); + *current_time = animation->currentTime().value_or(Timing::NullValue()); } else { // Use startTime where possible since currentTime is limited. - base::Optional timeline_time = animation->timeline()->CurrentTime(); + base::Optional timeline_time = animation->timeline()->currentTime(); // TODO(crbug.com/916117): Handle NaN values for scroll linked animations. *current_time = timeline_time ? timeline_time.value() - @@ -253,9 +253,9 @@ Response InspectorAnimationAgent::setPaused( // Ensure we restore a current time if the animation is limited. double current_time = 0; if (!clone->timeline()->IsActive()) { - current_time = clone->currentTime(); + current_time = clone->currentTime().value_or(Timing::NullValue()); } else { - base::Optional timeline_time = clone->timeline()->CurrentTime(); + base::Optional timeline_time = clone->timeline()->currentTime(); // TODO(crbug.com/916117): Handle NaN values. current_time = timeline_time ? timeline_time.value() - @@ -263,7 +263,7 @@ Response InspectorAnimationAgent::setPaused( : Timing::NullValue(); } clone->pause(); - clone->setCurrentTime(current_time, false); + clone->setCurrentTime(current_time); } else if (!paused && clone->Paused()) { clone->Unpause(); } @@ -310,8 +310,7 @@ blink::Animation* InspectorAnimationAgent::AnimationClone( id_to_animation_clone_.Set(id, clone); id_to_animation_.Set(String::Number(clone->SequenceNumber()), clone); clone->play(); - clone->setStartTime(animation->startTime().value_or(Timing::NullValue()), - false); + clone->setStartTime(animation->startTime().value_or(Timing::NullValue())); animation->SetEffectSuppressed(true); } @@ -331,7 +330,7 @@ Response InspectorAnimationAgent::seekAnimations( return Response::ServerError("Failed to clone a detached animation."); if (!clone->Paused()) clone->play(); - clone->setCurrentTime(current_time, false); + clone->setCurrentTime(current_time); } return Response::Success(); } @@ -515,7 +514,8 @@ double InspectorAnimationAgent::NormalizedStartTime( if (document_timeline) { if (ReferenceTimeline().PlaybackRate() == 0) { time_ms += - ReferenceTimeline().currentTime() - document_timeline->currentTime(); + ReferenceTimeline().currentTime().value_or(Timing::NullValue()) - + document_timeline->currentTime().value_or(Timing::NullValue()); } else { time_ms += (document_timeline->ZeroTime() - ReferenceTimeline().ZeroTime()) diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc index 7dfae515abc..de81a8e3df5 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc +++ b/chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc @@ -153,31 +153,43 @@ void InspectorAuditsAgent::InnerEnable() { } namespace { -std::unique_ptr> BuildCookies( - const WTF::Vector& cookies) { - auto result = - std::make_unique>(); - for (const auto& cookie : cookies) { - auto protocol_cookie = std::move(protocol::Audits::AffectedCookie::create() - .setName(cookie->name) - .setPath(cookie->path) - .setDomain(cookie->domain)); - if (cookie->site_for_cookies) { - protocol_cookie.setSiteForCookies(*cookie->site_for_cookies); - } - result->push_back(protocol_cookie.build()); +std::unique_ptr BuildAffectedCookie( + const mojom::blink::AffectedCookiePtr& cookie) { + auto protocol_cookie = std::move(protocol::Audits::AffectedCookie::create() + .setName(cookie->name) + .setPath(cookie->path) + .setDomain(cookie->domain)); + return protocol_cookie.build(); +} + +std::unique_ptr BuildAffectedRequest( + const mojom::blink::AffectedRequestPtr& request) { + auto protocol_request = protocol::Audits::AffectedRequest::create() + .setRequestId(request->request_id) + .build(); + if (!request->url.IsEmpty()) { + protocol_request->setUrl(request->url); } - return result; + return protocol_request; +} + +std::unique_ptr BuildAffectedFrame( + const mojom::blink::AffectedFramePtr& frame) { + return protocol::Audits::AffectedFrame::create() + .setFrameId(frame->frame_id) + .build(); } + blink::protocol::String InspectorIssueCodeValue( mojom::blink::InspectorIssueCode code) { switch (code) { case mojom::blink::InspectorIssueCode::kSameSiteCookieIssue: return protocol::Audits::InspectorIssueCodeEnum::SameSiteCookieIssue; + case mojom::blink::InspectorIssueCode::kMixedContentIssue: + return protocol::Audits::InspectorIssueCodeEnum::MixedContentIssue; } - NOTREACHED(); - return "unknown"; } + protocol::String BuildCookieExclusionReason( mojom::blink::SameSiteCookieExclusionReason exclusion_reason) { switch (exclusion_reason) { @@ -190,9 +202,8 @@ protocol::String BuildCookieExclusionReason( return protocol::Audits::SameSiteCookieExclusionReasonEnum:: ExcludeSameSiteNoneInsecure; } - NOTREACHED(); - return "unknown"; } + std::unique_ptr> BuildCookieExclusionReasons( const WTF::Vector& @@ -204,6 +215,7 @@ BuildCookieExclusionReasons( } return protocol_exclusion_reasons; } + protocol::String BuildCookieWarningReason( mojom::blink::SameSiteCookieWarningReason warning_reason) { switch (warning_reason) { @@ -220,33 +232,28 @@ protocol::String BuildCookieWarningReason( return protocol::Audits::SameSiteCookieWarningReasonEnum:: WarnSameSiteUnspecifiedLaxAllowUnsafe; case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeSecureUrlMethodUnsafe: - return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeSecureUrlMethodUnsafe; - case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeSecureUrlLax: + WarnSameSiteStrictLaxDowngradeStrict: return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeSecureUrlLax; + WarnSameSiteStrictLaxDowngradeStrict; case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeSecureUrlStrict: + WarnSameSiteStrictCrossDowngradeStrict: return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeSecureUrlStrict; + WarnSameSiteStrictCrossDowngradeStrict; case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe: + WarnSameSiteStrictCrossDowngradeLax: return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeInsecureUrlMethodUnsafe; + WarnSameSiteStrictCrossDowngradeLax; case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeInsecureUrlLax: + WarnSameSiteLaxCrossDowngradeStrict: return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeInsecureUrlLax; + WarnSameSiteLaxCrossDowngradeStrict; case blink::mojom::blink::SameSiteCookieWarningReason:: - WarnSameSiteCrossSchemeInsecureUrlStrict: + WarnSameSiteLaxCrossDowngradeLax: return protocol::Audits::SameSiteCookieWarningReasonEnum:: - WarnSameSiteCrossSchemeInsecureUrlStrict; + WarnSameSiteLaxCrossDowngradeLax; } - NOTREACHED(); - return "unknown"; } + std::unique_ptr> BuildCookieWarningReasons( const WTF::Vector& warning_reasons) { @@ -257,32 +264,154 @@ std::unique_ptr> BuildCookieWarningReasons( } return protocol_warning_reasons; } +protocol::String BuildCookieOperation( + mojom::blink::SameSiteCookieOperation operation) { + switch (operation) { + case blink::mojom::blink::SameSiteCookieOperation::SetCookie: + return protocol::Audits::SameSiteCookieOperationEnum::SetCookie; + case blink::mojom::blink::SameSiteCookieOperation::ReadCookie: + return protocol::Audits::SameSiteCookieOperationEnum::ReadCookie; + } +} + +protocol::String BuildMixedContentResolutionStatus( + mojom::blink::MixedContentResolutionStatus resolution_type) { + switch (resolution_type) { + case blink::mojom::blink::MixedContentResolutionStatus::MixedContentBlocked: + return protocol::Audits::MixedContentResolutionStatusEnum:: + MixedContentBlocked; + case blink::mojom::blink::MixedContentResolutionStatus:: + MixedContentAutomaticallyUpgraded: + return protocol::Audits::MixedContentResolutionStatusEnum:: + MixedContentAutomaticallyUpgraded; + case blink::mojom::blink::MixedContentResolutionStatus::MixedContentWarning: + return protocol::Audits::MixedContentResolutionStatusEnum:: + MixedContentWarning; + } +} + +protocol::String BuildMixedContentResourceType( + mojom::blink::RequestContextType request_context) { + switch (request_context) { + case blink::mojom::blink::RequestContextType::AUDIO: + return protocol::Audits::MixedContentResourceTypeEnum::Audio; + case blink::mojom::blink::RequestContextType::BEACON: + return protocol::Audits::MixedContentResourceTypeEnum::Beacon; + case blink::mojom::blink::RequestContextType::CSP_REPORT: + return protocol::Audits::MixedContentResourceTypeEnum::CSPReport; + case blink::mojom::blink::RequestContextType::DOWNLOAD: + return protocol::Audits::MixedContentResourceTypeEnum::Download; + case blink::mojom::blink::RequestContextType::EMBED: + return protocol::Audits::MixedContentResourceTypeEnum::PluginResource; + case blink::mojom::blink::RequestContextType::EVENT_SOURCE: + return protocol::Audits::MixedContentResourceTypeEnum::EventSource; + case blink::mojom::blink::RequestContextType::FAVICON: + return protocol::Audits::MixedContentResourceTypeEnum::Favicon; + case blink::mojom::blink::RequestContextType::FETCH: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::FONT: + return protocol::Audits::MixedContentResourceTypeEnum::Font; + case blink::mojom::blink::RequestContextType::FORM: + return protocol::Audits::MixedContentResourceTypeEnum::Form; + case blink::mojom::blink::RequestContextType::FRAME: + return protocol::Audits::MixedContentResourceTypeEnum::Frame; + case blink::mojom::blink::RequestContextType::HYPERLINK: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::IFRAME: + return protocol::Audits::MixedContentResourceTypeEnum::Frame; + case blink::mojom::blink::RequestContextType::IMAGE: + return protocol::Audits::MixedContentResourceTypeEnum::Image; + case blink::mojom::blink::RequestContextType::IMAGE_SET: + return protocol::Audits::MixedContentResourceTypeEnum::Image; + case blink::mojom::blink::RequestContextType::IMPORT: + return protocol::Audits::MixedContentResourceTypeEnum::Import; + case blink::mojom::blink::RequestContextType::INTERNAL: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::LOCATION: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::MANIFEST: + return protocol::Audits::MixedContentResourceTypeEnum::Manifest; + case blink::mojom::blink::RequestContextType::OBJECT: + return protocol::Audits::MixedContentResourceTypeEnum::PluginResource; + case blink::mojom::blink::RequestContextType::PING: + return protocol::Audits::MixedContentResourceTypeEnum::Ping; + case blink::mojom::blink::RequestContextType::PLUGIN: + return protocol::Audits::MixedContentResourceTypeEnum::PluginData; + case blink::mojom::blink::RequestContextType::PREFETCH: + return protocol::Audits::MixedContentResourceTypeEnum::Prefetch; + case blink::mojom::blink::RequestContextType::SCRIPT: + return protocol::Audits::MixedContentResourceTypeEnum::Script; + case blink::mojom::blink::RequestContextType::SERVICE_WORKER: + return protocol::Audits::MixedContentResourceTypeEnum::ServiceWorker; + case blink::mojom::blink::RequestContextType::SHARED_WORKER: + return protocol::Audits::MixedContentResourceTypeEnum::SharedWorker; + case blink::mojom::blink::RequestContextType::STYLE: + return protocol::Audits::MixedContentResourceTypeEnum::Stylesheet; + case blink::mojom::blink::RequestContextType::SUBRESOURCE: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::TRACK: + return protocol::Audits::MixedContentResourceTypeEnum::Track; + case blink::mojom::blink::RequestContextType::UNSPECIFIED: + return protocol::Audits::MixedContentResourceTypeEnum::Resource; + case blink::mojom::blink::RequestContextType::VIDEO: + return protocol::Audits::MixedContentResourceTypeEnum::Video; + case blink::mojom::blink::RequestContextType::WORKER: + return protocol::Audits::MixedContentResourceTypeEnum::Worker; + case blink::mojom::blink::RequestContextType::XML_HTTP_REQUEST: + return protocol::Audits::MixedContentResourceTypeEnum::XMLHttpRequest; + case blink::mojom::blink::RequestContextType::XSLT: + return protocol::Audits::MixedContentResourceTypeEnum::XSLT; + } +} + } // namespace void InspectorAuditsAgent::InspectorIssueAdded(InspectorIssue* issue) { auto issueDetails = protocol::Audits::InspectorIssueDetails::create(); - if (issue->Details()->sameSiteCookieIssueDetails) { + if (const auto* d = issue->Details()->sameSiteCookieIssueDetails.get()) { auto sameSiteCookieDetails = - protocol::Audits::SameSiteCookieIssueDetails::create() - .setCookieExclusionReasons(BuildCookieExclusionReasons( - issue->Details()->sameSiteCookieIssueDetails->exclusionReason)) - .setCookieWarningReasons(BuildCookieWarningReasons( - issue->Details()->sameSiteCookieIssueDetails->warningReason)) - .build(); - issueDetails.setSameSiteCookieIssueDetails( - std::move(sameSiteCookieDetails)); + std::move(protocol::Audits::SameSiteCookieIssueDetails::create() + .setCookie(BuildAffectedCookie(d->cookie)) + .setCookieExclusionReasons( + BuildCookieExclusionReasons(d->exclusionReason)) + .setCookieWarningReasons( + BuildCookieWarningReasons(d->warningReason)) + .setOperation(BuildCookieOperation(d->operation))); + + if (d->site_for_cookies) { + sameSiteCookieDetails.setSiteForCookies(*d->site_for_cookies); + } + if (d->cookie_url) { + sameSiteCookieDetails.setCookieUrl(*d->cookie_url); + } + if (d->request) { + sameSiteCookieDetails.setRequest(BuildAffectedRequest(d->request)); + } + issueDetails.setSameSiteCookieIssueDetails(sameSiteCookieDetails.build()); } - auto affectedResources = - protocol::Audits::AffectedResources::create() - .setCookies(BuildCookies(issue->Resources()->cookies)) - .build(); + if (const auto* d = issue->Details()->mixed_content_issue_details.get()) { + auto mixedContentDetails = + protocol::Audits::MixedContentIssueDetails::create() + .setResourceType(BuildMixedContentResourceType(d->request_context)) + .setResolutionStatus( + BuildMixedContentResolutionStatus(d->resolution_status)) + .setInsecureURL(d->insecure_url) + .setMainResourceURL(d->main_resource_url) + .build(); + if (d->request) { + mixedContentDetails->setRequest(BuildAffectedRequest(d->request)); + } + if (d->frame) { + mixedContentDetails->setFrame(BuildAffectedFrame(d->frame)); + } + issueDetails.setMixedContentIssueDetails(std::move(mixedContentDetails)); + } auto inspector_issue = protocol::Audits::InspectorIssue::create() .setCode(InspectorIssueCodeValue(issue->Code())) .setDetails(issueDetails.build()) - .setResources(std::move(affectedResources)) .build(); GetFrontend()->issueAdded(std::move(inspector_issue)); diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index b7637eadd7e..ef7c1ca3a0a 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc @@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -860,6 +861,19 @@ void InspectorCSSAgent::ForcePseudoState(Element* element, if (!node_id) return; + // First check whether focus-within was set because focus or focus-within was + // forced for a child node. + NodeIdToNumberFocusedChildren::iterator focused_it = + node_id_to_number_focused_children_.find(node_id); + unsigned focused_count = + focused_it == node_id_to_number_focused_children_.end() + ? 0 + : focused_it->value; + if (pseudo_type == CSSSelector::kPseudoFocusWithin && focused_count > 0) { + *result = true; + return; + } + NodeIdToForcedPseudoState::iterator it = node_id_to_forced_pseudo_state_.find(node_id); if (it == node_id_to_forced_pseudo_state_.end()) @@ -867,6 +881,7 @@ void InspectorCSSAgent::ForcePseudoState(Element* element, bool force = false; unsigned forced_pseudo_state = it->value; + switch (pseudo_type) { case CSSSelector::kPseudoActive: force = forced_pseudo_state & kPseudoActive; @@ -1637,11 +1652,65 @@ Response InspectorCSSAgent::forcePseudoState( node_id_to_forced_pseudo_state_.Set(node_id, forced_pseudo_state); else node_id_to_forced_pseudo_state_.erase(node_id); + + // When adding focus or focus-within, we force focus-within for ancestor + // nodes to emulate real focus for user convenience. + + // Flips from no forced focus to the forced focus (:focus or :focus-within). + if (((forced_pseudo_state & kPseudoFocus) == kPseudoFocus && + (current_forced_pseudo_state & kPseudoFocus) == 0) || + ((forced_pseudo_state & kPseudoFocusWithin) == kPseudoFocusWithin && + (current_forced_pseudo_state & kPseudoFocusWithin) == 0)) { + IncrementFocusedCountForAncestors(element); + } + + // Flips from the forced focus (:focus or :focus-within) to no focus. + if (((forced_pseudo_state & kPseudoFocus) == 0 && + (current_forced_pseudo_state & kPseudoFocus) == kPseudoFocus) || + ((forced_pseudo_state & kPseudoFocusWithin) == 0 && + (current_forced_pseudo_state & kPseudoFocusWithin) == + kPseudoFocusWithin)) { + DecrementFocusedCountForAncestors(element); + } + element->ownerDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kInspector)); return Response::Success(); } +void InspectorCSSAgent::IncrementFocusedCountForAncestors(Element* element) { + for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) { + int node_id = dom_agent_->BoundNodeId(&ancestor); + if (!node_id) + continue; + NodeIdToNumberFocusedChildren::iterator it = + node_id_to_number_focused_children_.find(node_id); + unsigned count = + it == node_id_to_number_focused_children_.end() ? 0 : it->value; + node_id_to_number_focused_children_.Set(node_id, count + 1); + } +} + +void InspectorCSSAgent::DecrementFocusedCountForAncestors(Element* element) { + for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) { + int node_id = dom_agent_->BoundNodeId(&ancestor); + if (!node_id) + continue; + NodeIdToNumberFocusedChildren::iterator it = + node_id_to_number_focused_children_.find(node_id); + unsigned count = + it == node_id_to_number_focused_children_.end() ? 1 : it->value; + if (count <= 1) { + // If `count - 1` is zero or overflows, erase the node_id + // from the map to save memory. If there is zero focused child + // elements, :focus-within should not be forced. + node_id_to_number_focused_children_.erase(node_id); + } else { + node_id_to_number_focused_children_.Set(node_id, count - 1); + } + } +} + std::unique_ptr InspectorCSSAgent::BuildMediaObject( const MediaList* media, MediaListSource media_list_source, @@ -2154,7 +2223,14 @@ void InspectorCSSAgent::ResetPseudoStates() { documents_to_change.insert(element->ownerDocument()); } + for (auto& count : node_id_to_number_focused_children_) { + auto* element = To(dom_agent_->NodeForId(count.key)); + if (element && element->ownerDocument()) + documents_to_change.insert(element->ownerDocument()); + } + node_id_to_forced_pseudo_state_.clear(); + node_id_to_number_focused_children_.clear(); for (auto& document : documents_to_change) { document->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kInspector)); diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h index 5815c86fbdb..449b85ea315 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h +++ b/chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.h @@ -245,6 +245,7 @@ class CORE_EXPORT InspectorCSSAgent final NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline // styles typedef HashMap NodeIdToForcedPseudoState; + typedef HashMap NodeIdToNumberFocusedChildren; void ResourceContentLoaded(std::unique_ptr); void CompleteEnabled(); @@ -303,6 +304,9 @@ class CORE_EXPORT InspectorCSSAgent final void ResetPseudoStates(); + void IncrementFocusedCountForAncestors(Element*); + void DecrementFocusedCountForAncestors(Element*); + Member dom_agent_; Member inspected_frames_; Member network_agent_; @@ -322,6 +326,7 @@ class CORE_EXPORT InspectorCSSAgent final NodeToInspectorStyleSheet node_to_inspector_style_sheet_; NodeIdToForcedPseudoState node_id_to_forced_pseudo_state_; + NodeIdToNumberFocusedChildren node_id_to_number_focused_children_; Member tracker_; diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc index ce49bb82a00..bcf226243cf 100644 --- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc +++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc @@ -1541,9 +1541,13 @@ std::unique_ptr InspectorDOMAgent::BuildObjectForNode( } if (auto* template_element = DynamicTo(*element)) { - value->setTemplateContent(BuildObjectForNode( - template_element->content(), 0, pierce, nodes_map, flatten_result)); - force_push_children = true; + // The inspector should not try to access the .content() property of + // declarative Shadow DOM