Commit 9fba1345 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

Exit early if the layer has been deleted in OnLayerBoundsChanged

This can happen when a layer is recreated for animation for example.
(observed in crrev.com/c/2375686)

Bug: None
Test: Covered by unittest
Change-Id: Ia8e4bae050ef5c281ad498a461171900ceae13a0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2384070Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803058}
parent 72699d4a
...@@ -1400,9 +1400,15 @@ void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds, ...@@ -1400,9 +1400,15 @@ void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds,
if (old_bounds.origin() != bounds_.origin()) if (old_bounds.origin() != bounds_.origin())
RecomputePosition(); RecomputePosition();
auto ptr = weak_ptr_factory_.GetWeakPtr();
if (delegate_) if (delegate_)
delegate_->OnLayerBoundsChanged(old_bounds, reason); delegate_->OnLayerBoundsChanged(old_bounds, reason);
// The layer may be deleted in the observer.
if (!ptr)
return;
if (bounds.size() == old_bounds.size()) { if (bounds.size() == old_bounds.size()) {
// Don't schedule a draw if we're invisible. We'll schedule one // Don't schedule a draw if we're invisible. We'll schedule one
// automatically when we get visible. // automatically when we get visible.
......
...@@ -212,4 +212,37 @@ TEST_F(LayerOwnerTestWithCompositor, ...@@ -212,4 +212,37 @@ TEST_F(LayerOwnerTestWithCompositor,
EXPECT_TRUE(animation->animation_timeline()); EXPECT_TRUE(animation->animation_timeline());
} }
namespace {
class TestLayerDelegate : public LayerDelegate {
public:
explicit TestLayerDelegate(ui::LayerOwner* owner) : owner_(owner) {}
TestLayerDelegate(TestLayerDelegate&) = delete;
TestLayerDelegate& operator=(TestLayerDelegate&) = delete;
~TestLayerDelegate() override = default;
// LayerDelegate:
void OnPaintLayer(const PaintContext& context) override {}
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override {}
void OnLayerBoundsChanged(const gfx::Rect& old_bounds,
PropertyChangeReason reason) override {
owner_->RecreateLayer();
}
private:
ui::LayerOwner* owner_;
};
} // namespace
// Test if recreating a layer in OnLayerBoundsChanged will not
// cause a use-after-free.
TEST_F(LayerOwnerTestWithCompositor, DeleteOnLayerBoundsChanged) {
LayerOwnerForTesting owner(std::make_unique<Layer>());
TestLayerDelegate delegate(&owner);
owner.layer()->set_delegate(&delegate);
owner.layer()->SetBounds(gfx::Rect(100, 100));
}
} // namespace ui } // namespace ui
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment