From 9af9f37ef6f0cecaa595a9de28efef92115feb38 Mon Sep 17 00:00:00 2001 From: Geoffrey Ostosh Date: Thu, 28 May 2026 19:29:45 -0500 Subject: [PATCH] fix(electron-ozone): NativeWindowViews leak on rohtmlwidget cycle OS-21158 Continuously creating and destroying Electron BrowserWindows in a loop causes the Electron main process's memory consumption to grow monotonically. Part of this is caused by NativeWindowViews::SetContentView, which when replacing a content view detaches the child from the view hierarchy but does not delete it. Under the views ownership model, child views are implicitly owned by their parent, so the detached subtree, including the WebContentsView and associated widget plumbing, becomes unreachable and leaks. Switch to RemoveChildViewT, which transfers ownership back to the caller as a unique_ptr that is immediately dropped to destroy the subtree. The existing RemoveChildView path is retained for views with owned_by_client() set, since the framework must not delete those (see crbug/40115694). Future upstream merges may address this leak differently. This change should be re-evaluated when Electron/Chromium is upgraded. --- shell/browser/native_window_views.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index a5652d27ceeb1..960038dd6486a 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -521,8 +521,15 @@ void NativeWindowViews::SetWindowTransform( #endif void NativeWindowViews::SetContentView(views::View* view) { - if (content_view()) { - root_view_.RemoveChildView(content_view()); + auto* cv = content_view(); + if (cv) { + set_content_view(nullptr); + focused_view_ = nullptr; + if (!cv->owned_by_client()) { + root_view_.RemoveChildViewT(cv); + } else { + root_view_.RemoveChildView(cv); + } } set_content_view(view); focused_view_ = view;