chore: Show FIDO devices in the chooser if allowed (#40216)
* chore: Show FIDO devices in the chooser if allowed * chore: tweak HidChooserContext::IsFidoAllowedForOrigin * chore: feedback from review --------- Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
This commit is contained in:
parent
32a721fa2b
commit
025af3500c
5 changed files with 110 additions and 37 deletions
|
@ -85,12 +85,16 @@ HidChooserController::HidChooserController(
|
|||
filters_(std::move(filters)),
|
||||
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()),
|
||||
frame_tree_node_id_(render_frame_host->GetFrameTreeNodeId()),
|
||||
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(
|
||||
web_contents->GetBrowserContext())
|
||||
->AsWeakPtr();
|
||||
|
@ -129,6 +133,7 @@ void HidChooserController::OnDeviceAdded(
|
|||
const device::mojom::HidDeviceInfo& device) {
|
||||
if (!DisplayDevice(device))
|
||||
return;
|
||||
|
||||
if (AddDeviceInfo(device)) {
|
||||
api::Session* session = GetSession();
|
||||
if (session) {
|
||||
|
@ -142,8 +147,6 @@ void HidChooserController::OnDeviceAdded(
|
|||
session->Emit("hid-device-added", details);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void HidChooserController::OnDeviceRemoved(
|
||||
|
@ -151,7 +154,8 @@ void HidChooserController::OnDeviceRemoved(
|
|||
if (!base::Contains(items_, PhysicalDeviceIdFromDeviceInfo(device)))
|
||||
return;
|
||||
|
||||
if (api::Session* session = GetSession(); session != nullptr) {
|
||||
api::Session* session = GetSession();
|
||||
if (session) {
|
||||
auto* rfh = content::RenderFrameHost::FromID(render_frame_host_id_);
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
@ -223,9 +227,8 @@ void HidChooserController::OnGotDevices(
|
|||
|
||||
for (auto& device : devices) {
|
||||
if (DisplayDevice(*device)) {
|
||||
if (AddDeviceInfo(*device)) {
|
||||
if (AddDeviceInfo(*device))
|
||||
devicesToDisplay.push_back(device->Clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,6 +236,7 @@ void HidChooserController::OnGotDevices(
|
|||
// enumeration.
|
||||
if (chooser_context_)
|
||||
observation_.Observe(chooser_context_.get());
|
||||
|
||||
bool prevent_default = false;
|
||||
api::Session* session = GetSession();
|
||||
if (session) {
|
||||
|
@ -255,26 +259,41 @@ void HidChooserController::OnGotDevices(
|
|||
|
||||
bool HidChooserController::DisplayDevice(
|
||||
const device::mojom::HidDeviceInfo& device) const {
|
||||
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kDisableHidBlocklist)) {
|
||||
// Do not pass the device to the chooser if it is excluded by the blocklist.
|
||||
if (device.is_excluded_by_blocklist)
|
||||
return false;
|
||||
// Check if `device` has a top-level collection with a FIDO usage. FIDO
|
||||
// devices may be displayed if the origin is privileged or the blocklist is
|
||||
// disabled.
|
||||
const bool has_fido_collection =
|
||||
base::Contains(device.collections, device::mojom::kPageFido,
|
||||
[](const auto& c) { return c->usage->usage_page; });
|
||||
|
||||
// Do not pass the device to the chooser if it has a top-level collection
|
||||
// with the FIDO usage page.
|
||||
//
|
||||
// Note: The HID blocklist also blocks top-level collections with the FIDO
|
||||
// usage page, but will not block the device if it has other (non-FIDO)
|
||||
// collections. The check below will exclude the device from the chooser
|
||||
// if it has any top-level FIDO collection.
|
||||
auto find_it =
|
||||
std::find_if(device.collections.begin(), device.collections.end(),
|
||||
[](const device::mojom::HidCollectionInfoPtr& c) {
|
||||
return c->usage->usage_page == device::mojom::kPageFido;
|
||||
});
|
||||
if (find_it != device.collections.end())
|
||||
return false;
|
||||
if (has_fido_collection) {
|
||||
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kDisableHidBlocklist) ||
|
||||
(chooser_context_ &&
|
||||
chooser_context_->IsFidoAllowedForOrigin(origin_))) {
|
||||
return FilterMatchesAny(device) && !IsExcluded(device);
|
||||
}
|
||||
|
||||
AddMessageToConsole(
|
||||
blink::mojom::ConsoleMessageLevel::kInfo,
|
||||
base::StringPrintf(
|
||||
"Chooser dialog is not displaying a FIDO HID device: vendorId=%d, "
|
||||
"productId=%d, name='%s', serial='%s'",
|
||||
device.vendor_id, device.product_id, device.product_name.c_str(),
|
||||
device.serial_number.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (device.is_excluded_by_blocklist) {
|
||||
AddMessageToConsole(
|
||||
blink::mojom::ConsoleMessageLevel::kInfo,
|
||||
base::StringPrintf(
|
||||
"Chooser dialog is not displaying a device excluded by "
|
||||
"the HID blocklist: vendorId=%d, "
|
||||
"productId=%d, name='%s', serial='%s'",
|
||||
device.vendor_id, device.product_id, device.product_name.c_str(),
|
||||
device.serial_number.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return FilterMatchesAny(device) && !IsExcluded(device);
|
||||
|
@ -303,6 +322,15 @@ bool HidChooserController::IsExcluded(
|
|||
return false;
|
||||
}
|
||||
|
||||
void HidChooserController::AddMessageToConsole(
|
||||
blink::mojom::ConsoleMessageLevel level,
|
||||
const std::string& message) const {
|
||||
if (content::RenderFrameHost* rfh =
|
||||
initiator_document_.AsRenderFrameHostIfValid()) {
|
||||
rfh->AddMessageToConsole(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
bool HidChooserController::AddDeviceInfo(
|
||||
const device::mojom::HidDeviceInfo& device) {
|
||||
const auto& id = PhysicalDeviceIdFromDeviceInfo(device);
|
||||
|
@ -340,10 +368,8 @@ void HidChooserController::UpdateDeviceInfo(
|
|||
auto physical_device_it = device_map_.find(id);
|
||||
DCHECK(physical_device_it != device_map_.end());
|
||||
auto& device_infos = physical_device_it->second;
|
||||
auto device_it = base::ranges::find_if(
|
||||
device_infos, [&device](const device::mojom::HidDeviceInfoPtr& d) {
|
||||
return d->guid == device.guid;
|
||||
});
|
||||
auto device_it = base::ranges::find(device_infos, device.guid,
|
||||
&device::mojom::HidDeviceInfo::guid);
|
||||
DCHECK(device_it != device_infos.end());
|
||||
*device_it = device.Clone();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue