Repository: electron/electron (language: cpp)

Issue:
[Bug]: WebUSB API device list is always empty (attached devices are ignored).
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

23.0.0-alpha.1

### What operating system are you using?

macOS

### Operating System Version

Ventura 13.0.1

### What arch are you using?

arm64 (including Apple Silicon)

### Last Known Working Electron version

_No response_

### Expected Behavior

Electron should detect my Novation Launchpad X (a class-compliant, USB MIDI device).

### Actual Behavior

The device shows up in `chrome://usb-internals` (in stock Chrome), but when I call `navigator.usb.getDevices` in Electron, the device does not appear in the device list.

The device list is always empty.

### Testcase Gist URL

_No response_

### Additional Information

Codewise, I basically have this in my `index.js` file:

``` js
const { app, BrowserWindow } = require("electron");

app.whenReady().then(function() {

    const selectDevice = function(event, details, callback) {
        console.log("device list:", details.deviceList); // this array is always empty
        event.preventDefault();
    };

    const renderer = new BrowserWindow(options); // note: `options` is defined IRL
    renderer.webContents.session.setPermissionCheckHandler(() => true);
    renderer.webContents.session.on("select-usb-device", selectDevice);
});
```

In the renderer process, I just have a call to `navigator.usb.requestDevice` (inside a `keydown` event listener that only exists to ensure that the call is in response to a user gesture).

Note: The filters I'm passing to the WebUSB API are empty (though I tried Novation's ID (`0x1235`) too).


Discussion / hints:
Even with the list being empty, do you still get the popup? Trying to test https://yume-chan.github.io/ya-webadb/ on v23 alpha 3 on Linux and not getting any dialog when clicking Add > USB
@parkerlreed - Nope. There's no popup. However, I was under the impression that Electron doesn't use the popup (the permission/device-selection dialog that Chrome uses on the Web). Electron has its own API that we can use to implement a dialog, or we can just go ahead a talk to the device.

I'm not sure how that's supposed to work when Electron is rendering standards-compliant webapps (not Electron apps), but IIUC, Electron use the same approach for the WebHID, WebBlueTooth, WebUSB and WebSerial APIs.
Thanks. That's about what I figured. Once the list being empty gets cleared up, I may poke the webadb developer and see if there can be some special handling for Electron. 


Cool cool.

It *might be* worth trying to push for a change to Electron. Electron is used for creating custom browsers, and they need to render the Web correctly, so Electron must provide some means for ensuring that standards-compliant webapps render as is.

I feel like this should have come up already, and so there may be a discussion or feature I'm just not aware of.

They're all away for Christmas, so the community have to fend for themselves till the new year.
@parkerlreed - On reflection, I'm thinking it may just be the responsibility of whoever uses Electron to make a Web browser to polyfill standards-compliant JavaScript APIs, using the corresponding Electron APIs, as required.

If that's correct, you'd need to write some code in Electron to provide the missing functions that the webapp you're trying to use expects to be there.

Again, I may be wrong about this.
@7ombie  I have the same issue. But I accidentally found solution( on Linux): 
the problem was with permissions to  /dev/bus/usb/
So after change access rights to 777 it is works(wrong way, of course)
@bochenev - Thanks. I'll look into it. I'm on Mac, but it's hopefully related. Much appreciated.
I too am experiencing the same issue (on MacOS)
I've had another look at it, but cannot get it to work on Mac `:(`

I'd be grateful if @jkleinsc could give us some idea what the situation is, please?
@7ombie can you test with this fiddle and see if it works for you? https://gist.github.com/231437c733f6a5ba187c64d53a08cda2

Also, have you tested with any other devices?

When I test locally with that Fiddle with 23.0.0-alpha.1, I get back a device list.   I am on Monterey 12.6.2, so it is possible there's an issue with Ventura.

Also, given the nature of the device you are using you could also try using [WebHID](https://www.electronjs.org/docs/latest/tutorial/devices#webhid-api)
@jkleinsc - Sorry. Just saw this. I'll look into it, and let you know (I don't currently have Electron Fiddle installed).

It's not something I actively need. I was just trying it out. Thanks for the tip still (re. WebHID).
@jkleinsc - Sorry I haven't got back to this yet. I have a new laptop that only has Type-C ports, and all my devices and cables are for my old set up (which didn't use Type-C). I have one adapter, so need to get a couple more. Long story short, I haven't forgotten - just haven't had time.
@jkleinsc Is python's http.server suitable for trying that out?

I tried with that and electron 23 beta8 on Linux and it says no device selected. 

![image](https://user-images.githubusercontent.com/841440/216849966-7d2278f0-0c51-4356-b12a-352e1f61bacb.png)

Oh Im stupid I didnt reailize I just had to pass the folder to electron 

![image](https://user-images.githubusercontent.com/841440/216850041-7a30ef91-e11e-4c14-b971-2f643ea54950.png)

I experience the same issue on macOS Monterey. It works fine on both Fedora Linux and Windows 10, but I can'n make it work on my mac.
 ~~@desyatirikov @7ombie can you verify if Electron/Fiddle has access to Bluetooth on your macOS System Preferences -> Security & Privacy -> Bluetooth, eg: 
<img width="616" alt="Screen Shot 2023-02-07 at 4 29 00 PM" src="https://user-images.githubusercontent.com/609052/217370583-e2e2015d-f0a6-482a-b75c-3713c702e339.png">~~

@jkleinsc I just tried to give Fiddle app access to Bluetooth, restarted the app and tried again, and nothing changed. I still receive an empty list when I try to list usb devices but when I use [webadb](https://app.webadb.com/) I can see my android phone in the list.
@desyatirikov Not quite on topic but to let you know the webadb you are using is a freebooted github version with no changes and advertisements added. You can use the straight upstream version here https://yume-chan.github.io/ya-webadb/
@desyatirikov @7ombie ignore my comment above... I was also looking at a Bluetooth issue and forgot this was a WebUSB issue.
@jkleinsc I tested the same code on my another MacBook Pro with an Intel processor and macOS Big Sur and it works as expected. So, the issue can be related to arm64 MacBooks, newer macOS versions (Monterey/Ventura), or maybe USB-C vs USB2/3.
@desyatirikov thanks for the update.  I'll check on an arm64 mac to see if its specific to that platform.
I just verified that it is an arm64 specific issue.  On my Intel mac, it works fine; but does not work on an arm64 mac.
I agree, Windows works fine but arm64 Mac failing with same and modified code.
I found the underlying issue and am going to try and find a fix.
> I found the underlying issue and am going to try and find a fix.

Nice! Sorry I wasn't more help with this.

I'm on an M1 too. Thanks to everyone who helped out with this.

Fix patch:
diff --git a/patches/chromium/.patches b/patches/chromium/.patches
index 34fe0d83254c8..150dacaf66da5 100644
--- a/patches/chromium/.patches
+++ b/patches/chromium/.patches
@@ -126,3 +126,4 @@ chore_patch_out_partition_attribute_dcheck_for_webviews.patch
 expose_v8initializer_codegenerationcheckcallbackinmainthread.patch
 chore_patch_out_profile_methods_in_profile_selections_cc.patch
 fix_x11_window_restore_minimized_maximized_window.patch
+chore_defer_usb_service_getdevices_request_until_usb_service_is.patch
diff --git a/patches/chromium/chore_defer_usb_service_getdevices_request_until_usb_service_is.patch b/patches/chromium/chore_defer_usb_service_getdevices_request_until_usb_service_is.patch
new file mode 100644
index 0000000000000..616a1e956d479
--- /dev/null
+++ b/patches/chromium/chore_defer_usb_service_getdevices_request_until_usb_service_is.patch
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: John Kleinschmidt <jkleinsc@electronjs.org>
+Date: Thu, 2 Mar 2023 15:26:46 -0500
+Subject: chore: defer USB service GetDevices request until USB service is
+ ready.
+
+On macOS we need to wait until the USB service is ready before the list of
+devices is available. This should no longer be necessary if/when
+https://crbug.com/1096743 is completed.
+
+diff --git a/services/device/usb/usb_service_impl.cc b/services/device/usb/usb_service_impl.cc
+index 99456d1baa098e8a48b4a31cc8f5661586f7fc82..11d98208c85093598813897a144812c76bc67bea 100644
+--- a/services/device/usb/usb_service_impl.cc
++++ b/services/device/usb/usb_service_impl.cc
+@@ -198,7 +198,7 @@ void UsbServiceImpl::GetDevices(GetDevicesCallback callback) {
+     return;
+   }
+ 
+-  if (enumeration_in_progress_) {
++  if (enumeration_in_progress_ || !enumeration_ready_) {
+     pending_enumeration_callbacks_.push_back(std::move(callback));
+     return;
+   }
diff --git a/shell/browser/feature_list.cc b/shell/browser/feature_list.cc
index 0cf9374876bcd..ea4c74c52c253 100644
--- a/shell/browser/feature_list.cc
+++ b/shell/browser/feature_list.cc
@@ -36,11 +36,6 @@ void InitializeFeatureList() {
   disable_features +=
       std::string(",") + features::kSpareRendererForSitePerProcess.name;
 
-#if BUILDFLAG(IS_MAC)
-  // Needed for WebUSB implementation
-  enable_features += std::string(",") + device::kNewUsbBackend.name;
-#endif
-
 #if !BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
   disable_features += std::string(",") + media::kPictureInPicture.name;
 #endif


Test patch: