Skip to content

Commit

Permalink
serial: Expose connection state for Bluetooth serial ports
Browse files Browse the repository at this point in the history
Relevant spec change: WICG/serial#197

This CL adds a connected attribute to the SerialPort interface
that exposes the logical connection state of the serial port.
The behavior for Bluetooth serial ports is changed so that the
connect and disconnect events are dispatched when the connection
state of the Bluetooth device changes. The behavior is unchanged
for wired serial ports.

Intent to Prototype: TODO

Bug: 1488031
Change-Id: I34b88246e62202c24eee08ad4a997aff7eadeebb
  • Loading branch information
nondebug authored and chromium-wpt-export-bot committed Dec 20, 2023
1 parent 67141e8 commit 85c0464
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 5 deletions.
29 changes: 25 additions & 4 deletions resources/chromium/fake-serial.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ class FakeSerialService {
this.selectedPort_ = null;
}

addPort(info) {
addPort(info, connected = true) {
let portInfo = {};
if (info?.usbVendorId !== undefined) {
portInfo.hasUsbVendorId = true;
Expand All @@ -359,15 +359,18 @@ class FakeSerialService {

let token = ++this.nextToken_;
portInfo.token = {high: 0n, low: BigInt(token)};
portInfo.connected = connected;

let record = {
portInfo: portInfo,
fakePort: new FakeSerialPort(),
};
this.ports_.set(token, record);

for (let client of this.clients_) {
client.onPortAdded(portInfo);
if (connected) {
for (let client of this.clients_) {
client.onPortConnectedStateChanged(portInfo);
}
}

return token;
Expand All @@ -381,8 +384,26 @@ class FakeSerialService {

this.ports_.delete(token);

record.portInfo.connected = false;
for (let client of this.clients_) {
client.onPortConnectedStateChanged(record.portInfo);
}
}

setPortConnectedState(token, connected) {
let record = this.ports_.get(token);
if (record === undefined) {
return;
}

let was_connected = record.portInfo.connected;
if (was_connected === connected) {
return;
}

record.portInfo.connected = connected;
for (let client of this.clients_) {
client.onPortRemoved(record.portInfo);
client.onPortConnectedStateChanged(record.portInfo);
}
}

Expand Down
24 changes: 24 additions & 0 deletions serial/serial_onconnect.https.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,27 @@ serial_test(async (t, fake) => {
assert_in_array(event1.target, ports);
assert_in_array(event2.target, ports);
}, 'A "connect" event is fired when ports are added.');

serial_test(async (t, fake) => {
const eventWatcher =
new EventWatcher(t, navigator.serial, ['connect', 'disconnect']);

// Wait for getPorts() to resolve in order to ensure that the Mojo client
// interface has been configured.
let ports = await navigator.serial.getPorts();
assert_equals(ports.length, 0);

// Add a disconnected port.
const token = fake.addPort({}, /*connected=*/false);

// The disconnected port is included in the ports returned by getPorts.
ports = await navigator.serial.getPorts();
assert_equals(ports.length, 1);
assert_false(ports[0].connected);

// Connect the port.
fake.setPortConnectedState(token, true);
const event = await eventWatcher.wait_for(['connect']);
assert_true(event instanceof Event);
assert_true(event.target instanceof SerialPort);
}, 'A "connect" event is fired when a disconnected port becomes connected.');
27 changes: 26 additions & 1 deletion serial/serial_ondisconnect.https.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,29 @@ serial_test(async (t, fake) => {

ports = await navigator.serial.getPorts();
assert_equals(ports.length, 0);
}, 'A "disconnect" event is fired when ports are added.');
}, 'A "disconnect" event is fired when ports are removed.');

serial_test(async (t, fake) => {
const eventWatcher =
new EventWatcher(t, navigator.serial, ['connect', 'disconnect']);

// Wait for getPorts() to resolve in order to ensure that the Mojo client
// interface has been configured.
let ports = await navigator.serial.getPorts();
assert_equals(ports.length, 0);

// Add a connected port.
const token = fake.addPort();
const port = (await eventWatcher.wait_for(['connect'])).target;

// Disconnect the port but do not remove it.
fake.setPortConnectedState(token, false);
const event = await eventWatcher.wait_for(['disconnect']);
assert_true(event instanceof Event);
assert_equals(event.target, port);

// The disconnected port is included in the ports returned by getPorts.
ports = await navigator.serial.getPorts();
assert_equals(ports.length, 1);
assert_false(ports[0].connected);
}, 'A "disconnect" event is fired when a connected port becomes disconnected.');

0 comments on commit 85c0464

Please sign in to comment.