drop polyfill for chromimum < v85

This removes the polyfill for using older chrome browsers before the
writeWithResponse and writeWithoutResponse APIs were added.
This commit is contained in:
David Lechner
2020-12-21 13:05:47 -06:00
parent 9071b17637
commit ae996453e8
9 changed files with 37 additions and 153 deletions
+3 -7
View File
@@ -54,14 +54,10 @@ export function connect(): BootloaderConnectionConnectAction {
return { type: BootloaderConnectionActionType.Connect };
}
export type BootloaderConnectionDidConnectAction = Action<BootloaderConnectionActionType.DidConnect> & {
canWriteWithoutResponse: boolean;
};
export type BootloaderConnectionDidConnectAction = Action<BootloaderConnectionActionType.DidConnect>;
export function didConnect(
canWriteWithoutResponse: boolean,
): BootloaderConnectionDidConnectAction {
return { type: BootloaderConnectionActionType.DidConnect, canWriteWithoutResponse };
export function didConnect(): BootloaderConnectionDidConnectAction {
return { type: BootloaderConnectionActionType.DidConnect };
}
/**
-1
View File
@@ -1,6 +1,5 @@
{
"ble": {
"cannotWriteWithoutResponse": "This web browser does not support Web Bluetooth Write Characteristic Without Response. Flashing firmware will take a long time.",
"gattPermission": "The web browser did not give permission to use Bluetooth Low Energy",
"gattServiceNotFound": "Connected to hub but failed to get {serviceName} service. Try removing the \"{hubName}\" device in your OS Bluetooth settings, then try again.",
"noWebBluetooth": "This web browser does not support Web Bluetooth or it is not enabled.",
-1
View File
@@ -4,7 +4,6 @@
// Notification translation keys.
export enum MessageId {
BleCannotWriteWithoutResponse = 'ble.cannotWriteWithoutResponse',
BleConnectFailed = 'ble.connectFailed',
BleGattPermission = 'ble.gattPermission',
BleGattServiceNotFound = 'ble.gattServiceNotFound',
-11
View File
@@ -93,17 +93,6 @@ const list: Reducer<NotificationList, Action> = (state = [], action) => {
return append(state, Level.Error, MessageId.BleConnectFailed);
}
return state;
case BootloaderConnectionActionType.DidConnect:
if (!action.canWriteWithoutResponse) {
return append(
state,
Level.Warning,
MessageId.BleCannotWriteWithoutResponse,
undefined,
'https://github.com/WebBluetoothCG/web-bluetooth/blob/master/implementation-status.md',
);
}
return state;
case BootloaderConnectionActionType.DidFailToConnect:
switch (action.reason) {
case BootloaderConnectionFailureReason.GattServiceNotFound:
+7 -13
View File
@@ -33,10 +33,6 @@ import {
import { ServiceUUID as pybricksServiceUUID } from '../protocols/pybricks';
import { RootState } from '../reducers';
import { BleConnectionState } from '../reducers/ble';
import {
PolyfillBluetoothRemoteGATTCharacteristic,
polyfillBluetoothRemoteGATTCharacteristic,
} from '../utils/web-bluetooth';
function disconnect(
server: BluetoothRemoteGATTServer,
@@ -50,11 +46,11 @@ function* handleValueChanged(data: DataView): Generator {
}
function* write(
rxChar: PolyfillBluetoothRemoteGATTCharacteristic,
rxChar: BluetoothRemoteGATTCharacteristic,
action: BleUartWriteAction,
): Generator {
try {
yield call(() => rxChar.xWriteValueWithoutResponse(action.value.buffer));
yield call(() => rxChar.writeValueWithoutResponse(action.value.buffer));
yield put(didWrite(action.id));
} catch (err) {
yield put(didFailToWrite(action.id, err));
@@ -129,14 +125,12 @@ function* connect(_action: BleDeviceConnectAction): Generator {
return;
}
let rxChar: PolyfillBluetoothRemoteGATTCharacteristic;
let rxChar: BluetoothRemoteGATTCharacteristic;
try {
rxChar = polyfillBluetoothRemoteGATTCharacteristic(
(yield call(
[service, 'getCharacteristic'],
urtRxCharUUID,
)) as BluetoothRemoteGATTCharacteristic,
);
rxChar = (yield call(
[service, 'getCharacteristic'],
urtRxCharUUID,
)) as BluetoothRemoteGATTCharacteristic;
} catch (err) {
server.disconnect();
yield takeMaybe(disconnectChannel);
+18 -35
View File
@@ -236,21 +236,6 @@ function* flashFirmware(action: FlashFirmwareFlashAction): Generator {
}
}
// City hub bootloader is buggy. See note in encodeRequest().
if (info[0].hubType === HubType.CityHub && !connectResult.canWriteWithoutResponse) {
yield put(
notification.add(
'error',
'City Hub bootloader is not compatible with this web browser.',
),
);
const disconnectAction = (yield put(
disconnectRequest(),
)) as BootloaderDisconnectRequestAction;
yield waitForDidSend(disconnectAction.id);
return;
}
const eraseAction = (yield put(eraseRequest())) as BootloaderEraseRequestAction;
const [, erase] = (yield all([
waitForDidSend(eraseAction.id),
@@ -296,26 +281,24 @@ function* flashFirmware(action: FlashFirmwareFlashAction): Generator {
break;
}
if (connectResult.canWriteWithoutResponse) {
// Request checksum every 10 packets to prevent buffer overrun on
// the hub because of sending too much data at once. The actual
// number of packets that can be queued in the Bluetooth chip on
// the hub is not known and could vary by device.
if (++count % 10 === 0) {
const checksumAction = (yield put(
checksumRequest(),
)) as BootloaderChecksumRequestAction;
const [, checksum] = (yield all([
waitForDidSend(checksumAction.id),
waitForResponse(BootloaderResponseActionType.Checksum, 5000),
])) as [
BootloaderDidRequestAction,
WaitResponse<BootloaderChecksumResponseAction>,
];
if (!checksum[0]) {
// TODO: proper error handling
throw Error(`Failed to get checksum: ${checksum}`);
}
// Request checksum every 10 packets to prevent buffer overrun on
// the hub because of sending too much data at once. The actual
// number of packets that can be queued in the Bluetooth chip on
// the hub is not known and could vary by device.
if (++count % 10 === 0) {
const checksumAction = (yield put(
checksumRequest(),
)) as BootloaderChecksumRequestAction;
const [, checksum] = (yield all([
waitForDidSend(checksumAction.id),
waitForResponse(BootloaderResponseActionType.Checksum, 5000),
])) as [
BootloaderDidRequestAction,
WaitResponse<BootloaderChecksumResponseAction>,
];
if (!checksum[0]) {
// TODO: proper error handling
throw Error(`Failed to get checksum: ${checksum}`);
}
}
}
+9 -21
View File
@@ -17,24 +17,20 @@ import {
didSend,
} from '../actions/lwp3-bootloader';
import { CharacteristicUUID, ServiceUUID } from '../protocols/lwp3-bootloader';
import {
PolyfillBluetoothRemoteGATTCharacteristic,
polyfillBluetoothRemoteGATTCharacteristic,
} from '../utils/web-bluetooth';
function* handleNotify(data: DataView): Generator {
yield put(didReceive(data));
}
function* write(
characteristic: PolyfillBluetoothRemoteGATTCharacteristic,
characteristic: BluetoothRemoteGATTCharacteristic,
action: BootloaderConnectionSendAction,
): Generator {
try {
if (action.withResponse) {
yield call(() => characteristic.xWriteValueWithResponse(action.data));
yield call(() => characteristic.writeValueWithResponse(action.data));
} else {
yield call(() => characteristic.xWriteValueWithoutResponse(action.data));
yield call(() => characteristic.writeValueWithoutResponse(action.data));
}
yield put(didSend());
} catch (err) {
@@ -110,14 +106,12 @@ function* connect(_action: BootloaderConnectionAction): Generator {
return;
}
let characteristic: PolyfillBluetoothRemoteGATTCharacteristic;
let characteristic: BluetoothRemoteGATTCharacteristic;
try {
characteristic = polyfillBluetoothRemoteGATTCharacteristic(
(yield call(
[service, 'getCharacteristic'],
CharacteristicUUID,
)) as BluetoothRemoteGATTCharacteristic,
);
characteristic = (yield call(
[service, 'getCharacteristic'],
CharacteristicUUID,
)) as BluetoothRemoteGATTCharacteristic;
} catch (err) {
server.disconnect();
yield takeMaybe(disconnectChannel);
@@ -150,13 +144,7 @@ function* connect(_action: BootloaderConnectionAction): Generator {
yield takeEvery(notificationChannel, handleNotify);
yield takeEvery(BootloaderConnectionActionType.Send, write, characteristic);
// writeValueWithoutResponse() was introduced in Chrome 85.
// Older versions of Chrome for Android will write without response
// by default when using the deprecated writeValue().
const canWriteWithoutResponse =
characteristic.writeValueWithoutResponse !== undefined ||
/Android/i.test(navigator.userAgent);
yield put(didConnect(canWriteWithoutResponse));
yield put(didConnect());
yield takeMaybe(disconnectChannel);
notificationChannel.close();
-29
View File
@@ -1,29 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
import { polyfillBluetoothRemoteGATTCharacteristic } from './web-bluetooth';
describe('polyfillBluetoothRemoteGATTCharacteristic', () => {
test('old browser falls back to writeValue', () => {
const char = {} as BluetoothRemoteGATTCharacteristic;
Object.defineProperty(char, 'writeValue', { value: 'writeValue' });
expect(polyfillBluetoothRemoteGATTCharacteristic(char)).toEqual({
xWriteValueWithResponse: 'writeValue',
xWriteValueWithoutResponse: 'writeValue',
});
});
test('new browser uses writeValueWith(out)Response', () => {
const char = {} as BluetoothRemoteGATTCharacteristic;
Object.defineProperty(char, 'writeValue', { value: 'writeValue' });
Object.defineProperty(char, 'writeValueWithResponse', {
value: 'writeValueWithResponse',
});
Object.defineProperty(char, 'writeValueWithoutResponse', {
value: 'writeValueWithoutResponse',
});
expect(polyfillBluetoothRemoteGATTCharacteristic(char)).toEqual({
xWriteValueWithResponse: 'writeValueWithResponse',
xWriteValueWithoutResponse: 'writeValueWithoutResponse',
});
});
});
-35
View File
@@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2020 The Pybricks Authors
/**
* Current definition of BluetoothRemoteGATTCharacteristic doesn't include
* new Web Bluetooth APIs.
*/
export interface PolyfillBluetoothRemoteGATTCharacteristic
extends BluetoothRemoteGATTCharacteristic {
/**
* Calls writeValueWithResponse() if available otherwise falls back to writeValue()
* @param value data to send
*/
xWriteValueWithResponse(value: BufferSource): Promise<void>;
/**
* Calls writeValueWithoutResponse() if available otherwise falls back to writeValue()
* @param value data to send
*/
xWriteValueWithoutResponse(value: BufferSource): Promise<void>;
}
/**
* Fills in writeValueWithResponse and writeValueWithoutResponse for backward
* compatibility.
* @param char a remote GATT characteristic object
*/
export function polyfillBluetoothRemoteGATTCharacteristic(
char: BluetoothRemoteGATTCharacteristic,
): PolyfillBluetoothRemoteGATTCharacteristic {
const polyfill = (char as unknown) as PolyfillBluetoothRemoteGATTCharacteristic;
polyfill.xWriteValueWithResponse = char.writeValueWithResponse || char.writeValue;
polyfill.xWriteValueWithoutResponse =
char.writeValueWithoutResponse || char.writeValue;
return polyfill;
}