From aa6835662aa8ffcac6ace83cfd573c404711a41d Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 19:05:11 -0700 Subject: [PATCH] fix: clamp autofill popup bounds to the requesting frame viewport (#50944) Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Sam Attard --- shell/browser/electron_autofill_driver.cc | 22 +++++++++++++++++++++- spec/autofill-spec.ts | 5 +++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/shell/browser/electron_autofill_driver.cc b/shell/browser/electron_autofill_driver.cc index b731c687d9..cfe25e8efe 100644 --- a/shell/browser/electron_autofill_driver.cc +++ b/shell/browser/electron_autofill_driver.cc @@ -8,10 +8,12 @@ #include +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_widget_host_view.h" #include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/javascript_environment.h" #include "shell/browser/native_window.h" +#include "ui/gfx/geometry/rect_f.h" namespace electron { @@ -43,11 +45,29 @@ void AutofillDriver::ShowAutofillPopup( if (!owner_window) return; + // |bounds| is supplied by the renderer in the calling frame's RenderWidget + // coordinate space. Convert to the root view's space and clamp to the + // calling frame's visible viewport so a (potentially compromised) subframe + // cannot position the native popup over arbitrary application UI. + auto* frame_view = render_frame_host_->GetView(); + if (!frame_view) + return; + gfx::RectF popup_bounds(bounds); + popup_bounds.set_origin( + frame_view->TransformPointToRootCoordSpaceF(popup_bounds.origin())); + const gfx::Size frame_size = frame_view->GetViewBounds().size(); + const gfx::RectF frame_clip = gfx::BoundingRect( + frame_view->TransformPointToRootCoordSpaceF(gfx::PointF()), + frame_view->TransformPointToRootCoordSpaceF( + gfx::PointF(frame_size.width(), frame_size.height()))); + popup_bounds.Intersect(frame_clip); + if (popup_bounds.IsEmpty()) + return; + auto* embedder = web_contents->embedder(); bool osr = web_contents->IsOffScreen() || (embedder && embedder->IsOffScreen()); - gfx::RectF popup_bounds(bounds); content::RenderFrameHost* embedder_frame_host = nullptr; if (embedder) { auto* embedder_view = diff --git a/spec/autofill-spec.ts b/spec/autofill-spec.ts index 9868e9d633..1488c18144 100644 --- a/spec/autofill-spec.ts +++ b/spec/autofill-spec.ts @@ -47,4 +47,9 @@ describe('autofill', () => { const value = await w.webContents.executeJavaScript("document.querySelector('input').value"); expect(value).to.equal('13:01'); }); + + // An OOPIF datalist case is not asserted here because + // webContents.sendInputEvent forwards keyboard events to the main frame's + // RenderWidgetHost only, so a spec test cannot drive keyboard input into an + // out-of-process subframe. });