【问题标题】:Is there a way to get Chrome to “forget” a device to test navigator.usb.requestDevice, navigator.serial.requestPort?有没有办法让 Chrome “忘记”一个设备来测试 navigator.usb.requestDevice、navigator.serial.requestPort?
【发布时间】:2020-12-05 00:00:00
【问题描述】:

我希望从使用 WebUSB 迁移到 SerialAPI(很好地解释了 here)。

当前代码:

try {
    let device = await navigator.usb.requestDevice({
    filters: [{
            usbVendorId: RECEIVER_VENDOR_ID
        }]
    })
    this.connect(device)
} catch (error) {
    console.log(DEVICE_NAME + ': Permission Denied')
}

新代码:

try {
    let device = await navigator.serial.requestPort({
    filters: [{
            usbVendorId: RECEIVER_VENDOR_ID
        }]
    })
    this.connect(device)
} catch (error) {
    console.log(DEVICE_NAME + ': Permission Denied')
}

新代码似乎可以工作,但我认为这是因为浏览器已经通过旧代码请求了设备。

我已尝试重新启动 Chrome 并清除所有浏览历史记录。甚至关闭了 USB 声明页面并使用另一个应用程序声明了该设备(在此期间它返回 DOMException: Unable to claim interface 错误),但 Chrome 似乎不想再次询问。它只是愉快地使用先前的连接流式传输数据。

我希望使用 SerialAPI 可以避免与其他进程争夺 USB,或者至少输给他们。

更新

我忘记了:

Failed to execute 'requestPort' on 'Serial': "Must be handling a user gesture to show a permission request"

这是否意味着用户需要使用按钮通过 SerialUSB 连接到设备?我认为使用 WebUSB 可以让连接窗口自动弹出。

【问题讨论】:

  • 您收到的消息确切意味着您应该从事件中发出请求,通过用户手势实例化(点击即可)。
  • 谢谢@Kaiido。在更新中,我想知道是否有必要通过用户手势实例化请求,我认为 WebUSB 不是这种情况。
  • 来自您自己的链接:web.dev/usb/#user-gesture-required
  • 哎呀。我猜 SerialAPI 是一种不同的动物(来自 WebUSB)。我还认为手势要求使 OP 如何“忘记”设备静音。我可以继续删除这个问题。

标签: javascript webusb serialapi


【解决方案1】:

对于这两个 API,如更新中所述,需要用户手势才能调用 requestDevice()requestPort() 方法。无法自动弹出此提示。 (如果存在错误,请告知 Chrome 团队,以便我们修复它。)

通过 WebUSB API 和 Web Serial API 授予网站的权限目前是分开跟踪的,因此通过其中一个设备访问设备的权限不会自动转换为另一个。

目前没有一种以编程方式忘记设备权限的方法。这将需要已被放弃的navigator.permissions.revoke() 方法。但是,您可以通过在访问站点时单击地址栏中的“锁定”图标或转到 chrome://settings/content/usbDevices(对于 USB 设备)和 chrome://settings/ 来手动撤销访问设备的权限content/serialPorts(用于串行端口)。

【讨论】:

    【解决方案2】:

    要让 Chrome “忘记”之前通过 navigator.usb.requestDevice API 配对的 WebUSB 设备:

    1. 打开与您想忘记的设备配对的页面
    2. 点击地址栏中的图标
    3. 单击设备旁边的 x。如果未列出任何内容,则该网页没有配对设备。

    【讨论】:

      【解决方案3】:

      新代码不起作用。这似乎是因为 Chrome 已经通过旧代码与端口配对。 “新代码”不可能起作用,因为正如 Kalido 的评论中所指出的,SerialAPI(由于其强大的功能)需要用户手势才能连接。

      我用来实际连接和获取数据的代码基本上是由 OP 中上述链接的几部分组成的:

      navigator.serial.addEventListener('connect', e => {
        // Add |e.target| to the UI or automatically connect.
        console.log("connected");
      });
      
      navigator.serial.addEventListener('disconnect', e => {
        // Remove |e.target| from the UI. If the device was open the disconnection can
        // also be observed as a stream error.
        console.log("disconnected");
      });
      
      console.log(navigator.serial);
      
      document.addEventListener('DOMContentLoaded', async () => {
      
          const connectButton = document.querySelector('#connect') as HTMLInputElement;
      
          if (connectButton) {
              connectButton.addEventListener('click', async () => {
                  try {
              
                      // Request Keiser Receiver from the user.
                      const port = await navigator.serial.requestPort({
                          filters: [{ usbVendorId: 0x2341, usbProductId: not_required }]
                      });
                  
                      try {
                          // Open and begin reading.
                          await port.open({ baudRate: 115200 });
                      
                      } catch (e) {
                          console.log(e);
                      }
                      while (port.readable) {
                        const reader = port.readable.getReader();
      
                        try {
                          while (true) {
                            const { value, done } = await reader.read();
                            if (done) {
                              // Allow the serial port to be closed later.
                              reader.releaseLock();
                              break;
                            }
                            if (value) {
                              console.log(value);
                            }
                          }
                        } catch (error) {
                          // TODO: Handle non-fatal read error.
                          console.log(error);
                        }
                      }
                  } catch (e) {
                    console.log("Permission to access a device was denied implicitly or explicitly by the user.");
                    console.log(e);
                    console.log(port);
                  }
              }
      }
      

      设备特定的供应商和产品 ID 显然会因设备而异。在上面的示例中,我插入了一个 Arduino 供应商 ID。

      它没有回答如何让 Chrome “忘记”的问题,但由于需要手势,我不确定在使用 SerialAPI 时这是否相关。

      希望有更多经验的人能够发布更丰富的答案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-05
        • 2020-05-12
        • 1970-01-01
        • 1970-01-01
        • 2020-04-28
        • 1970-01-01
        • 1970-01-01
        • 2017-06-26
        相关资源
        最近更新 更多