fix: use requesting frame origin in permission helper and device choosers (#50052)

* fix: use requesting frame origin instead of top-level URL for permissions

`WebContentsPermissionHelper::RequestPermission` passes
`web_contents_->GetLastCommittedURL()` as the origin to the permission
manager instead of the actual requesting frame's origin. This enables
origin confusion when granting permissions to embedded third-party iframes,
since app permission handlers see the top-level origin instead of the
iframe's. The same pattern exists in the HID, USB, and Serial device
choosers, where grants are keyed to the primary main frame's origin rather
than the requesting frame's.

Fix this by using `requesting_frame->GetLastCommittedOrigin()` in all
affected code paths, renaming `details.requestingUrl` to
`details.requestingOrigin`, and populating it with the serialized
origin only.

* chore: keep requestingUrl name in permission handler details

The previous commit changed the details.requestingUrl field to
details.requestingOrigin in permission request/check handlers. That
field was already populated from the requesting frame's RFH, so the
rename was unnecessary and would break apps that read the existing
property. Revert to requestingUrl to preserve the existing API shape.

The functional changes to use the requesting frame in
WebContentsPermissionHelper and the HID/USB/Serial choosers remain.

---------

Co-authored-by: Samuel Attard <sattard@anthropic.com>
This commit is contained in:
Shelley Vohr
2026-03-09 17:20:22 +01:00
committed by GitHub
parent eacec9a47e
commit 2c6dd1156c
5 changed files with 7 additions and 15 deletions

View File

@@ -87,13 +87,9 @@ HidChooserController::HidChooserController(
exclusion_filters_(std::move(exclusion_filters)),
callback_(std::move(callback)),
initiator_document_(render_frame_host->GetWeakDocumentPtr()),
origin_(content::WebContents::FromRenderFrameHost(render_frame_host)
->GetPrimaryMainFrame()
->GetLastCommittedOrigin()),
origin_(render_frame_host->GetLastCommittedOrigin()),
hid_delegate_(hid_delegate),
render_frame_host_id_(render_frame_host->GetGlobalId()) {
// The use above of GetMainFrame is safe as content::HidService instances are
// not created for fenced frames.
DCHECK(!render_frame_host->IsNestedWithinFencedFrame());
chooser_context_ = HidChooserContextFactory::GetForBrowserContext(

View File

@@ -52,25 +52,21 @@ bool ElectronSerialDelegate::CanRequestPortPermission(
auto* permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
return permission_helper->CheckSerialAccessPermission(
web_contents->GetPrimaryMainFrame()->GetLastCommittedOrigin());
frame->GetLastCommittedOrigin());
}
bool ElectronSerialDelegate::HasPortPermission(
content::RenderFrameHost* frame,
const device::mojom::SerialPortInfo& port) {
auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
return GetChooserContext(frame)->HasPortPermission(
web_contents->GetPrimaryMainFrame()->GetLastCommittedOrigin(), port,
frame);
frame->GetLastCommittedOrigin(), port, frame);
}
void ElectronSerialDelegate::RevokePortPermissionWebInitiated(
content::RenderFrameHost* frame,
const base::UnguessableToken& token) {
auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
return GetChooserContext(frame)->RevokePortPermissionWebInitiated(
web_contents->GetPrimaryMainFrame()->GetLastCommittedOrigin(), token,
frame);
frame->GetLastCommittedOrigin(), token, frame);
}
const device::mojom::SerialPortInfo* ElectronSerialDelegate::GetPortInfo(

View File

@@ -125,7 +125,7 @@ SerialChooserController::SerialChooserController(
std::move(allowed_bluetooth_service_class_ids)),
callback_(std::move(callback)),
initiator_document_(render_frame_host->GetWeakDocumentPtr()) {
origin_ = web_contents_->GetPrimaryMainFrame()->GetLastCommittedOrigin();
origin_ = render_frame_host->GetLastCommittedOrigin();
chooser_context_ = SerialChooserContextFactory::GetForBrowserContext(
web_contents_->GetBrowserContext())

View File

@@ -43,7 +43,7 @@ UsbChooserController::UsbChooserController(
: WebContentsObserver(web_contents),
options_(std::move(options)),
callback_(std::move(callback)),
origin_(render_frame_host->GetMainFrame()->GetLastCommittedOrigin()),
origin_(render_frame_host->GetLastCommittedOrigin()),
usb_delegate_(usb_delegate),
render_frame_host_id_(render_frame_host->GetGlobalId()) {
chooser_context_ = UsbChooserContextFactory::GetForBrowserContext(

View File

@@ -219,7 +219,7 @@ void WebContentsPermissionHelper::RequestPermission(
base::DictValue details) {
auto* permission_manager = static_cast<ElectronPermissionManager*>(
web_contents_->GetBrowserContext()->GetPermissionControllerDelegate());
auto origin = web_contents_->GetLastCommittedURL();
auto origin = requesting_frame->GetLastCommittedOrigin().GetURL();
permission_manager->RequestPermissionWithDetails(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(permission),