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 <[email protected]> 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 <[email protected]> Reviewed-by: Joey Arhar <[email protected]> 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