bluetooth: Add BluetoothDevice.forget()
This CL adds the forget method to the BluetoothDevice interface so that
developers can revoke permission access to a paired BluetoothDevice.
It is available behind the WebBluetoothGetDevices blink runtime feature.
Spec: https://github.com/WebBluetoothCG/web-bluetooth/pull/574
Test: https://bluetoothdevice-forget.glitch.me/
Change-Id: I0a562607cc473ecc95fdb269eb40194d81c1b8ed
Bug: 1302328
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3497377
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Dominick Ng <dominickn@chromium.org>
Commit-Queue: Fr <beaufort.francois@gmail.com>
Cr-Commit-Position: refs/heads/main@{#979716}
diff --git a/bluetooth/device/forget/connect-after-forget.https.window.js b/bluetooth/device/forget/connect-after-forget.https.window.js
new file mode 100644
index 0000000..0b15b4d
--- /dev/null
+++ b/bluetooth/device/forget/connect-after-forget.https.window.js
@@ -0,0 +1,11 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/bluetooth/resources/bluetooth-test.js
+// META: script=/bluetooth/resources/bluetooth-fake-devices.js
+
+bluetooth_test(async (t) => {
+ const { device } = await getConnectedHealthThermometerDevice();
+ await device.forget();
+
+ await promise_rejects_dom(t, 'SecurityError', device.gatt.connect());
+}, 'gatt.connect() rejects after forget().');
diff --git a/bluetooth/device/forget/detachedIframe.https.window.js b/bluetooth/device/forget/detachedIframe.https.window.js
new file mode 100644
index 0000000..c34a3c4
--- /dev/null
+++ b/bluetooth/device/forget/detachedIframe.https.window.js
@@ -0,0 +1,26 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/bluetooth/resources/bluetooth-test.js
+// META: script=/bluetooth/resources/bluetooth-fake-devices.js
+
+bluetooth_test(async () => {
+ let iframe = document.createElement('iframe');
+ let error;
+
+ const {device} = await getHealthThermometerDeviceFromIframe(iframe);
+
+ iframe.remove();
+ // Set iframe to null to ensure that the GC cleans up as much as possible.
+ iframe = null;
+ await runGarbageCollection();
+
+ try {
+ await device.forget();
+ } catch (e) {
+ // Cannot use promise_rejects_dom() because |e| is thrown from a different
+ // global.
+ error = e;
+ }
+ assert_not_equals(error, undefined);
+ assert_equals(error.name, 'TypeError');
+}, 'forget() rejects in a detached context');
diff --git a/bluetooth/device/forget/getDevices.https.window.js b/bluetooth/device/forget/getDevices.https.window.js
new file mode 100644
index 0000000..e9ce656
--- /dev/null
+++ b/bluetooth/device/forget/getDevices.https.window.js
@@ -0,0 +1,18 @@
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
+// META: script=/bluetooth/resources/bluetooth-test.js
+// META: script=/bluetooth/resources/bluetooth-fake-devices.js
+
+bluetooth_test(async () => {
+ await getConnectedHealthThermometerDevice();
+ const devicesBeforeForget = await navigator.bluetooth.getDevices();
+ assert_equals(
+ devicesBeforeForget.length, 1, 'getDevices() should return the granted device.');
+
+ const device = devicesBeforeForget[0];
+ await device.forget();
+ const devicesAfterForget = await navigator.bluetooth.getDevices();
+ assert_equals(
+ devicesAfterForget.length, 0,
+ 'getDevices() is empty after device.forget().');
+}, 'forget() removes devices from getDevices().');