Chrome · Paint › HiC
CVE-2026-113000
Memory Corruption in Paint (HiC)
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
forthird_party/blink/renderer/core/dom/element.cc |
modified | |
TEST_Pthird_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc |
modified | |
GCOnFocusChangeObserverthird_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc |
modified |
Files Changed
third_party/blink/renderer/core/html/html_install_element.hthird_party/blink/renderer/core/dom/element.hthird_party/blink/renderer/core/html/forms/html_select_element.ccthird_party/blink/renderer/core/html/media/html_video_element.ccthird_party/blink/renderer/core/dom/element.ccthird_party/blink/renderer/core/html/forms/html_select_element.hthird_party/blink/renderer/core/html/canvas/html_canvas_element_test.ccthird_party/blink/renderer/core/html/media/html_video_element.hthird_party/blink/renderer/core/html/forms/html_input_element.ccthird_party/blink/renderer/core/html/forms/html_text_area_element.ccthird_party/blink/renderer/core/html/html_frame_owner_element.hthird_party/blink/renderer/core/html/html_frame_owner_element.ccthird_party/blink/renderer/core/html/forms/html_input_element.hthird_party/blink/renderer/core/html/html_install_element.ccthird_party/blink/renderer/core/html/forms/html_text_area_element.h
Patch
From 2ec1ba2211a0c11af30296fc755a83d5bf7a7684 Mon Sep 17 00:00:00 2001
From: Stefan Zager <szager@chromium.org>
Date: Tue, 13 Oct 2026 19:33:19 -0700
Subject: [PATCH] [HiC] Invalidate iframe contents correctly on top layer removal
This adds the `CanvasSubtreePropagation` enum to allow forcibly
invalidating an entire subtree as necessary. A heavy hammer, but should
probably be the default fix for under-invalidation bugs unless and until
we can figure out a more fine-grained fix.
Fixed: 572598342
Change-Id: Iceb8dd3f0001d8afc46377ff374f75426549fc6b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8560060
Commit-Queue: Stefan Zager <szager@chromium.org>
Reviewed-by: Joey Arhar <jarhar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1718252}
---
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 7eb579c..4dde3c9b 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4513,8 +4513,11 @@
}
#endif
-void Element::SetIsInCanvasSubtree(bool value) {
- if (value == IsInCanvasSubtree()) {
+void Element::SetIsInCanvasSubtree(
+ bool value,
+ CanvasSubtreePropagation propagation_behavior) {
+ if (propagation_behavior == CanvasSubtreePropagation::kOnlyIfChanged &&
+ value == IsInCanvasSubtree()) {
#if DCHECK_IS_ON()
if (!GetDocument().IsSlotAssignmentRecalcForbidden()) {
VerifySubtreeIsInCanvas(value);
@@ -4525,7 +4528,7 @@
SetElementFlag(ElementFlags::kIsInCanvasSubtree, value);
// Note that this call leads to HTMLFrameOwnerElement updating iframes.
- DidChangeIsInCanvasSubtree();
+ DidChangeIsInCanvasSubtree(propagation_behavior);
if (!value && IsA<HTMLCanvasElement>(*this)) {
// Nested canvas element must reset the value to true.
value = true;
@@ -4540,7 +4543,7 @@
// this visits active fallback content).
if (ShadowRoot* shadow_root = GetShadowRoot()) {
for (Element& child : ElementTraversal::ChildrenOf(*shadow_root)) {
- child.SetIsInCanvasSubtree(value);
+ child.SetIsInCanvasSubtree(value, propagation_behavior);
}
} else if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(*this)) {
const HeapVector<Member<Node>> assigned_nodes =
@@ -4548,22 +4551,22 @@
for (Node* node : assigned_nodes) {
if (auto* child = DynamicTo<Element>(node);
child && child->AssignedSlotWithoutRecalc() == slot) {
- child->SetIsInCanvasSubtree(value);
+ child->SetIsInCanvasSubtree(value, propagation_behavior);
}
}
// Fallback content
for (Element& child : ElementTraversal::ChildrenOf(*this)) {
- child.SetIsInCanvasSubtree(value &&
- slot->AssignedNodesNoRecalc().empty());
+ child.SetIsInCanvasSubtree(value && slot->AssignedNodesNoRecalc().empty(),
+ propagation_behavior);
}
} else {
for (Element& child : ElementTraversal::ChildrenOf(*this)) {
- child.SetIsInCanvasSubtree(value);
+ child.SetIsInCanvasSubtree(value, propagation_behavior);
}
}
if (const NodeRareData* rare_data = RareData()) {
for (PseudoElement* pseudo_element : rare_data->GetPseudoElements()) {
- pseudo_element->SetIsInCanvasSubtree(value);
+ pseudo_element->SetIsInCanvasSubtree(value, propagation_behavior);
}
}
}
@@ -4578,7 +4581,7 @@
return false;
}
-void Element::DidChangeIsInCanvasSubtree() {
+void Element::DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) {
if (auto* layout_object = GetLayoutObject()) {
layout_object->SetNeedsPaintPropertyUpdate();
layout_object->SetSubtreeShouldDoFullPaintInvalidation();
@@ -12087,7 +12090,10 @@
// A popover inside a canvas subtree does not render with privacy
// protections when in the top layer. So treat transitioning between top
// layer states as equivalent to moving in or out of the canvas subtree.
- DidChangeIsInCanvasSubtree();
+ // Moving into or out of the top layer does not by itself imply a change in
+ // IsInCanvasSubtree state, so kAlways is used to force invalidation.
+ SetIsInCanvasSubtree(IsInCanvasSubtree(),
+ CanvasSubtreePropagation::kAlways);
}
bool user_action_stops_at_top_layer =
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 3f61c16d..813a0bdbd 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -1170,8 +1170,16 @@
SetElementFlag(ElementFlags::kStyleAffectedByEmpty);
}
+ enum class CanvasSubtreePropagation { kOnlyIfChanged, kAlways };
+
// Recursively sets the IsInCanvasSubtree bit for the element and its subtree.
- void SetIsInCanvasSubtree(bool value);
+ // If propagation_behavior is kOnlyIfChanged, the recursion stops when it
+ // reaches a Node where `value` is the same as the Node's current state. If
+ // the behavior is kAlways, the recursion forcibly continues all the way down
+ // the tree regardless of the previous value.
+ void SetIsInCanvasSubtree(bool value,
+ CanvasSubtreePropagation propagation_behavior =
+ CanvasSubtreePropagation::kOnlyIfChanged);
// True if this element has a flat-tree DOM ancestor <canvas> (including
// across local frame boundaries).
// Warning: This is a pure DOM check; it is true regardless of
@@ -1183,8 +1191,10 @@
}
// Like `IsInCanvasSubtree()`, but includes <canvas> elements.
bool IsCanvasOrInCanvasSubtree() const;
- // Called when `IsInCanvasSubtree()` changes.
- virtual void DidChangeIsInCanvasSubtree();
+ // Called when `IsInCanvasSubtree()` changes, or when content should be
+ // invalidated *as if* `IsInCanvasSubtree()` changed (e.g., when showing
+ // or hiding a popover).
+ virtual void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation);
#if DCHECK_IS_ON()
void VerifySubtreeIsInCanvas(bool value);
#endif
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc
index 1b57117e..7bf0187 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1351,8 +1351,9 @@
input_type_view_->UpdateView();
}
-void HTMLInputElement::DidChangeIsInCanvasSubtree() {
- TextControlElement::DidChangeIsInCanvasSubtree();
+void HTMLInputElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ TextControlElement::DidChangeIsInCanvasSubtree(propagation_behavior);
if (IsInCanvasSubtree()) {
// Hide suggested values when under canvas, to prevent leaking this
// information to javascript.
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h
index 80db469..401f172 100644
--- a/third_party/blink/renderer/core/html/forms/html_input_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -545,7 +545,7 @@
void MaybeReportPiiMetrics();
- void DidChangeIsInCanvasSubtree() final;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) final;
AtomicString name_;
// The value string in |value| value mode.
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc
index 0d924ab8..ee76b80a4 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -904,8 +904,10 @@
return -1;
}
-void HTMLSelectElement::DidChangeIsInCanvasSubtree() {
- HTMLFormControlElementWithState::DidChangeIsInCanvasSubtree();
+void HTMLSelectElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ HTMLFormControlElementWithState::DidChangeIsInCanvasSubtree(
+ propagation_behavior);
if (IsInCanvasSubtree()) {
// Hide suggested values when under canvas, to prevent leaking this
// information to javascript.
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.h b/third_party/blink/renderer/core/html/forms/html_select_element.h
index 9330525..cd3f45d 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.h
@@ -540,7 +540,7 @@
// Helper to update the select descendants' mutation observer.
void UpdateMutationObserver();
- void DidChangeIsInCanvasSubtree() final;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) final;
// last_on_change_option_ is the currently selected option. It provides faster
// access to the currently selected option than iterating through each option
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
index 3504f79..0c153d7 100644
--- a/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.cc
@@ -742,8 +742,9 @@
StyleChangeReasonForTracing::Create(style_change_reason::kControlValue));
}
-void HTMLTextAreaElement::DidChangeIsInCanvasSubtree() {
- TextControlElement::DidChangeIsInCanvasSubtree();
+void HTMLTextAreaElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ TextControlElement::DidChangeIsInCanvasSubtree(propagation_behavior);
if (IsInCanvasSubtree()) {
// Hide suggested values when under canvas, to prevent leaking this
// information to javascript.
diff --git a/third_party/blink/renderer/core/html/forms/html_text_area_element.h b/third_party/blink/renderer/core/html/forms/html_text_area_element.h
index c309eb5f..0752635 100644
--- a/third_party/blink/renderer/core/html/forms/html_text_area_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_text_area_element.h
@@ -174,7 +174,7 @@
bool TooLong(const String*, NeedsToCheckDirtyFlag) const;
bool TooShort(const String*, NeedsToCheckDirtyFlag) const;
- void DidChangeIsInCanvasSubtree() final;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) final;
unsigned rows_;
unsigned cols_;
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index 6d83a091..ad9fe20f 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -217,11 +217,12 @@
return result;
}
-void HTMLFrameOwnerElement::DidChangeIsInCanvasSubtree() {
- HTMLElement::DidChangeIsInCanvasSubtree();
+void HTMLFrameOwnerElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ HTMLElement::DidChangeIsInCanvasSubtree(propagation_behavior);
if (Document* inner_document = contentDocument()) {
if (Element* root = inner_document->documentElement()) {
- root->SetIsInCanvasSubtree(IsInCanvasSubtree());
+ root->SetIsInCanvasSubtree(IsInCanvasSubtree(), propagation_behavior);
if (auto* layout_view = inner_document->GetLayoutView()) {
layout_view->SetNeedsPaintPropertyUpdate();
layout_view->SetSubtreeShouldDoFullPaintInvalidation();
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h
index 1b04e48..c89ea2c 100644
--- a/third_party/blink/renderer/core/html/html_frame_owner_element.h
+++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -93,7 +93,7 @@
// Node overrides:
Node::InsertionNotificationRequest InsertedInto(
ContainerNode& insertion_point) override;
- void DidChangeIsInCanvasSubtree() override;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) override;
void RemovedFrom(ContainerNode& insertion_point) override;
// Element overrides:
void DidRecalcStyle(const StyleRecalcChange) override;
diff --git a/third_party/blink/renderer/core/html/html_install_element.cc b/third_party/blink/renderer/core/html/html_install_element.cc
index ae0ff83..1479b936 100644
--- a/third_party/blink/renderer/core/html/html_install_element.cc
+++ b/third_party/blink/renderer/core/html/html_install_element.cc
@@ -161,8 +161,9 @@
HTMLElement::IsURLAttribute(attr);
}
-void HTMLInstallElement::DidChangeIsInCanvasSubtree() {
- HTMLCapabilityElementBase::DidChangeIsInCanvasSubtree();
+void HTMLInstallElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ HTMLCapabilityElementBase::DidChangeIsInCanvasSubtree(propagation_behavior);
UpdateAppearance();
}
diff --git a/third_party/blink/renderer/core/html/html_install_element.h b/third_party/blink/renderer/core/html/html_install_element.h
index 3063b33..dfd6270 100644
--- a/third_party/blink/renderer/core/html/html_install_element.h
+++ b/third_party/blink/renderer/core/html/html_install_element.h
@@ -58,7 +58,7 @@
// HTMLElement:
bool IsURLAttribute(const Attribute&) const override;
- void DidChangeIsInCanvasSubtree() override;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) override;
// HTMLCapabilityElementBase:
void UpdateAppearance() override;
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 07d37b8..13d5500 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -898,8 +898,9 @@
return 0;
}
-void HTMLVideoElement::DidChangeIsInCanvasSubtree() {
- HTMLMediaElement::DidChangeIsInCanvasSubtree();
+void HTMLVideoElement::DidChangeIsInCanvasSubtree(
+ CanvasSubtreePropagation propagation_behavior) {
+ HTMLMediaElement::DidChangeIsInCanvasSubtree(propagation_behavior);
if (IsInCanvasSubtree()) {
UpdateLayoutObject();
if (auto* wmp = GetWebMediaPlayer()) {
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.h b/third_party/blink/renderer/core/html/media/html_video_element.h
index 9f5dd5d5..9163038 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.h
+++ b/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -252,7 +252,7 @@
void RequestVisibility(RequestVisibilityCallback request_visibility_cb) final;
void DidMoveToNewDocument(Document& old_document) override;
- void DidChangeIsInCanvasSubtree() override;
+ void DidChangeIsInCanvasSubtree(CanvasSubtreePropagation) override;
void UpdatePictureInPictureAvailability();
void UpdateVideoFrameAvailability() override;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
index c94d465..614d273b 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -829,6 +829,74 @@
EXPECT_TRUE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
}
+TEST_P(HTMLCanvasElementTest, TopLayerRemovalInvalidatesSubtreeAcrossFrames) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ [popover] {
+ display: block !important;
+ }
+ </style>
+ <canvas id="canvas" content="drawable">
+ <div id="drawable" drawable>
+ <div id="popover" popover="manual">
+ <div id="child"></div>
+ <iframe id="iframe"></iframe>
+ </div>
+ </div>
+ </canvas>
+ )HTML");
+ SetChildFrameHTML(R"HTML(
+ <div id="inner_target">Hello</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* popover =
+ To<HTMLElement>(GetDocument().getElementById(AtomicString("popover")));
+ auto* child = GetDocument().getElementById(AtomicString("child"));
+ auto* iframe = GetDocument().getElementById(AtomicString("iframe"));
+ auto* inner_target =
+ ChildDocument().getElementById(AtomicString("inner_target"));
+
+ popover->ShowPopoverInternal(nullptr, nullptr);
+ UpdateAllLifecyclePhasesForTest();
+ ASSERT_TRUE(popover->IsInTopLayer());
+
+ EXPECT_FALSE(
+ popover->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(
+ child->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(child->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ iframe->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(iframe->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ ChildDocument().GetLayoutView()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(ChildDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ inner_target->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(inner_target->GetLayoutObject()->NeedsPaintPropertyUpdate());
+
+ popover->HidePopoverInternal(
+ /*invoker=*/nullptr, HidePopoverFocusBehavior::kNone,
+ HidePopoverTransitionBehavior::kNoEventsNoWaiting,
+ /*exception_state=*/nullptr);
+ GetDocument().UpdateStyleAndLayoutTree();
+ ASSERT_FALSE(popover->IsInTopLayer());
+
+ EXPECT_TRUE(popover->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(popover->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(child->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(child->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(iframe->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(iframe->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(
+ ChildDocument().GetLayoutView()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(ChildDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(
+ inner_target->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(inner_target->GetLayoutObject()->NeedsPaintPropertyUpdate());
+}
+
TEST_P(HTMLCanvasElementTest, SlotAssignmentDuringSetIsInCanvasSubtree) {
class GCOnFocusChangeObserver final
: public GarbageCollected<GCOnFocusChangeObserver>,
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
index c94d465..614d273b 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element_test.cc
@@ -829,6 +829,74 @@
EXPECT_TRUE(host->GetPseudoElement(kPseudoIdAfter)->IsInCanvasSubtree());
}
+TEST_P(HTMLCanvasElementTest, TopLayerRemovalInvalidatesSubtreeAcrossFrames) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ [popover] {
+ display: block !important;
+ }
+ </style>
+ <canvas id="canvas" content="drawable">
+ <div id="drawable" drawable>
+ <div id="popover" popover="manual">
+ <div id="child"></div>
+ <iframe id="iframe"></iframe>
+ </div>
+ </div>
+ </canvas>
+ )HTML");
+ SetChildFrameHTML(R"HTML(
+ <div id="inner_target">Hello</div>
+ )HTML");
+ UpdateAllLifecyclePhasesForTest();
+
+ auto* popover =
+ To<HTMLElement>(GetDocument().getElementById(AtomicString("popover")));
+ auto* child = GetDocument().getElementById(AtomicString("child"));
+ auto* iframe = GetDocument().getElementById(AtomicString("iframe"));
+ auto* inner_target =
+ ChildDocument().getElementById(AtomicString("inner_target"));
+
+ popover->ShowPopoverInternal(nullptr, nullptr);
+ UpdateAllLifecyclePhasesForTest();
+ ASSERT_TRUE(popover->IsInTopLayer());
+
+ EXPECT_FALSE(
+ popover->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(
+ child->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(child->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ iframe->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(iframe->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ ChildDocument().GetLayoutView()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(ChildDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
+ EXPECT_FALSE(
+ inner_target->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_FALSE(inner_target->GetLayoutObject()->NeedsPaintPropertyUpdate());
+
+ popover->HidePopoverInternal(
+ /*invoker=*/nullptr, HidePopoverFocusBehavior::kNone,
+ HidePopoverTransitionBehavior::kNoEventsNoWaiting,
+ /*exception_state=*/nullptr);
+ GetDocument().UpdateStyleAndLayoutTree();
+ ASSERT_FALSE(popover->IsInTopLayer());
+
+ EXPECT_TRUE(popover->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(popover->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(child->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(child->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(iframe->GetLayoutObject()->ShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(iframe->GetLayoutObject()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(
+ ChildDocument().GetLayoutView()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(ChildDocument().GetLayoutView()->NeedsPaintPropertyUpdate());
+ EXPECT_TRUE(
+ inner_target->GetLayoutObject()->SubtreeShouldDoFullPaintInvalidation());
+ EXPECT_TRUE(inner_target->GetLayoutObject()->NeedsPaintPropertyUpdate());
+}
+
TEST_P(HTMLCanvasElementTest, SlotAssignmentDuringSetIsInCanvasSubtree) {
class GCOnFocusChangeObserver final
: public GarbageCollected<GCOnFocusChangeObserver>,
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page