fix: crash in AutofillPopup teardown (#51317)

Fix a crash in AutofillPopupView::Show() when the popup
tried to show itself after the parent's native view had
already gone away during teardown.

2026-04-23T20:44:32.7015810Z Received signal 11 SEGV_ACCERR 000000000160
2026-04-23T20:44:32.9322010Z 4   Electron Framework  ... views::Widget::IsVisible() const + 28
2026-04-23T20:44:32.9528810Z 6   Electron Framework  ... electron::AutofillPopupView::Show() + 200
2026-04-23T20:44:32.9632090Z 7   Electron Framework  ... electron::AutofillPopup::CreateView(...) + 1380
2026-04-23T20:44:32.9749770Z 8   Electron Framework  ... electron::AutofillDriver::ShowAutofillPopup(...) + 736
2026-04-23T20:44:33.0015220Z ✗ Electron tests failed with kill signal SIGSEGV.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
trop[bot]
2026-04-26 08:50:34 -05:00
committed by GitHub
parent ab52a57491
commit cd4ebc497a
2 changed files with 38 additions and 11 deletions

View File

@@ -172,20 +172,30 @@ void AutofillPopup::CreateView(content::RenderFrameHost* frame_host,
bool offscreen,
views::View* parent,
const gfx::RectF& r) {
DCHECK(parent);
Hide();
// A Widget can outlive its NativeWidget during teardown.
// Do not create a child popup once the parent native view is gone.
views::Widget* parent_widget = parent->GetWidget();
if (!parent_widget || parent_widget->IsClosed() ||
!parent_widget->GetNativeView()) {
return;
}
frame_host_ = frame_host;
element_bounds_ = gfx::ToEnclosedRect(r);
gfx::Vector2d height_offset(0, element_bounds_.height());
gfx::Point menu_position(element_bounds_.origin() + height_offset);
gfx::Vector2d height_offset{0, element_bounds_.height()};
gfx::Point menu_position{element_bounds_.origin() + height_offset};
views::View::ConvertPointToScreen(parent, &menu_position);
popup_bounds_ = gfx::Rect(menu_position, element_bounds_.size());
popup_bounds_ = gfx::Rect{menu_position, element_bounds_.size()};
parent_ = parent;
parent_->AddObserver(this);
view_ = new AutofillPopupView(this, parent->GetWidget());
view_ = new AutofillPopupView{this, parent_widget};
if (offscreen) {
auto* rwhv = embedder_frame_host ? embedder_frame_host->GetView()
@@ -212,13 +222,19 @@ void AutofillPopup::Hide() {
void AutofillPopup::SetItems(const std::vector<std::u16string>& values,
const std::vector<std::u16string>& labels) {
DCHECK(view_);
values_ = values;
labels_ = labels;
if (!view_)
return;
UpdatePopupBounds();
view_->OnSuggestionsChanged();
if (view_) // could be hidden after the change
view_->DoUpdateBoundsAndRedrawPopup();
if (!view_)
return;
view_->DoUpdateBoundsAndRedrawPopup();
}
void AutofillPopup::AcceptSuggestion(int index) {

View File

@@ -69,9 +69,16 @@ AutofillPopupView::~AutofillPopupView() {
void AutofillPopupView::Show() {
if (!popup_)
return;
bool visible = parent_widget_->IsVisible();
visible = visible || view_proxy_;
if (!visible || parent_widget_->IsClosed())
DCHECK(parent_widget_);
// The parent Widget can outlive its NativeWidget during teardown.
// Don't initialize the popup after the native parent view is gone.
if (parent_widget_->IsClosed() || !parent_widget_->GetNativeView())
return;
const bool visible = view_proxy_ || parent_widget_->IsVisible();
if (!visible)
return;
const bool initialize_widget = !GetWidget();
@@ -234,10 +241,14 @@ void AutofillPopupView::DoUpdateBoundsAndRedrawPopup() {
if (!popup_)
return;
views::Widget* const widget = GetWidget();
if (!widget)
return;
// Clamp popup_bounds_ to ensure it's never zero-width.
popup_->popup_bounds_.Union(
gfx::Rect(popup_->popup_bounds_.origin(), gfx::Size(1, 1)));
GetWidget()->SetBounds(popup_->popup_bounds_);
widget->SetBounds(popup_->popup_bounds_);
if (view_proxy_.get()) {
view_proxy_->SetBounds(popup_->popup_bounds_in_view());
}