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
worker 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
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
worker 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 Commented yesterday
- @woxxom Sounds like it's worth a try, thanks. – link89 Commented yesterday
2 Answers
Reset to default 1requestDevice()
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.
Thanks to Reilly's answer I have figure 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);
}
});
}