I am working on a Chrome Extension which will save specific resource to my Oculus Quest directly via WebUsb.
The problem is, I find the navigator.usb.requestDevice is not exist in service worker.
My plan is to maintain a adb connection between extension service worker and my Android device, so that when I click to download specific url, the extension will send an event to the service-worker, which will download the content and send it to my Android device.
My question is, how to make requestDevice work in service-worker, or do I have to create adb connection in contentScript instead of running in background?
Update:
I have try chrome.windows.create and it doesn't work. It is supposed to have a choose device show up in the address bar but the window created by service worker doesn't have one, so it is always report No device selected
-
Use the offscreen document.woxxom– woxxom2025年02月09日 09:48:04 +00:00Commented Feb 9, 2025 at 9:48
-
@woxxom Sounds like it's worth a try, thanks.link89– link892025年02月09日 16:10:04 +00:00Commented Feb 9, 2025 at 16:10
2 Answers 2
requestDevice() cannot be called from a Service Worker because it has to show the permissions prompt UI (there are probably solutions to this, but they introduce additional challenges so it's the reason why it's currently disallowed).
For your use case, I think you have two options:
In the Service Worker you can call
navigator.usb.getDevices()to get a list of all the USB devices your extension has permission to access. If the device is already there you can perform the transfer in the background using the Service Worker. If not you need to callchrome.windows.create()to open a pop-up and request permission before the Service Worker can continue.Always call
chrome.windows.create()to open a pop-up as part of transferring the file to the device, and use the pop-up to display progress in addition to needing it for the occasional permission prompt.
While an offscreen document, as suggested by one of the comments, can call requestDevice(), it will always throw an exception because the document is not visible.
Comments
Thanks to Reilly's answer I have figured out a solution.
The key point is to create a normal window and handle the WebUSB in it, either offscreen, popup or panel window won't work as device selected menu won't be displayed and end up with No device selected.
And here is the key snippet of this solution
function createPopupAndSend(message: DownloadEvent) {
chrome.windows.create({
url: chrome.runtime.getURL(new URL("popup.html", import.meta.url).pathname),
type: "normal",
width: 600,
height: 500,
}, (newWindow) => {
if (newWindow && newWindow.id !== undefined) {
popupWindowId = newWindow.id;
// Delay sending the message to give the popup time to load.
setTimeout(() => {
chrome.runtime.sendMessage(message);
}, 500);
}
});
}
1 Comment
chrome.windows.create with type: popup doesn't work, it has to be type normal.Explore related questions
See similar questions with these tags.