Skip to content

Commit d9d970e

Browse files
Handle Chrome OS 105 WebUSB error (#1000)
Temporary workaround for ChromeOS 105 bug. See https://bugs.chromium.org/p/chromium/issues/detail?id=1363712&q=usb&can=2 Co-authored-by: Matt Hillsdon <[email protected]> Co-authored-by: Matt Hillsdon <[email protected]>
1 parent a4d25d6 commit d9d970e

File tree

3 files changed

+72
-18
lines changed

3 files changed

+72
-18
lines changed

src/device/webusb.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,24 @@ import {
2626
WebUSBError,
2727
} from "./device";
2828

29+
// Temporary workaround for ChromeOS 105 bug.
30+
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1363712&q=usb&can=2
31+
export const isChromeOS105 = (): boolean => {
32+
const userAgent = navigator.userAgent;
33+
return /CrOS/.test(userAgent) && /Chrome\/105\b/.test(userAgent);
34+
};
35+
2936
/**
3037
* A WebUSB connection to a micro:bit device.
3138
*/
3239
export class MicrobitWebUSBConnection
3340
extends EventEmitter
3441
implements DeviceConnection
3542
{
36-
status: ConnectionStatus = navigator.usb
37-
? ConnectionStatus.NO_AUTHORIZED_DEVICE
38-
: ConnectionStatus.NOT_SUPPORTED;
43+
status: ConnectionStatus =
44+
navigator.usb && !isChromeOS105()
45+
? ConnectionStatus.NO_AUTHORIZED_DEVICE
46+
: ConnectionStatus.NOT_SUPPORTED;
3947

4048
/**
4149
* The USB device we last connected to.

src/workbench/connect-dialogs/WebUSBDialog.tsx

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
* SPDX-License-Identifier: MIT
55
*/
66
import { Button } from "@chakra-ui/button";
7-
import { HStack, Text, VStack } from "@chakra-ui/react";
8-
import { useCallback } from "react";
7+
import { Flex, HStack, Image, Stack, Text, VStack } from "@chakra-ui/react";
8+
import { ReactNode, useCallback } from "react";
99
import { FormattedMessage } from "react-intl";
1010
import { GenericDialog } from "../../common/GenericDialog";
11+
import { isChromeOS105 } from "../../device/webusb";
12+
import chromeOSErrorImage from "./chrome-os-105-error.png";
1113

1214
interface WebUSBDialogProps {
1315
callback: () => void;
@@ -25,24 +27,32 @@ export const WebUSBDialog = ({
2527
<GenericDialog
2628
finalFocusRef={finalFocusRef}
2729
onClose={handleClose}
28-
body={<WebUSBDialogBody />}
30+
body={
31+
isChromeOS105() ? <Chrome105ErrorBody /> : <NotSupportedErrorBody />
32+
}
2933
footer={<WebUSBDialogFooter onCancel={handleClose} />}
3034
size="3xl"
3135
/>
3236
);
3337
};
3438

35-
const WebUSBDialogBody = () => {
39+
const DialogBodyWrapper = ({ children }: { children: ReactNode }) => (
40+
<VStack
41+
width="auto"
42+
ml="auto"
43+
mr="auto"
44+
p={8}
45+
pb={0}
46+
spacing={5}
47+
alignItems="flex-start"
48+
>
49+
{children}
50+
</VStack>
51+
);
52+
53+
const NotSupportedErrorBody = () => {
3654
return (
37-
<VStack
38-
width="auto"
39-
ml="auto"
40-
mr="auto"
41-
p={8}
42-
pb={0}
43-
spacing={5}
44-
alignItems="flex-start"
45-
>
55+
<DialogBodyWrapper>
4656
<Text as="h2" fontSize="xl" fontWeight="semibold">
4757
<FormattedMessage id="webusb-not-supported-title" />
4858
</Text>
@@ -52,7 +62,43 @@ const WebUSBDialogBody = () => {
5262
<Text>
5363
<FormattedMessage id="webusb-why-use" />
5464
</Text>
55-
</VStack>
65+
</DialogBodyWrapper>
66+
);
67+
};
68+
69+
const Chrome105ErrorBody = () => {
70+
return (
71+
<DialogBodyWrapper>
72+
<Text as="h2" fontSize="xl" fontWeight="semibold">
73+
There is an issue with Chrome OS version 105 and WebUSB*
74+
</Text>
75+
<HStack spacing={5}>
76+
<Stack>
77+
<Text>
78+
Unfortunately “Send to micro:bit” does not work in this particular
79+
Chrome OS version due to a bug in the operating system. The next
80+
version of Chrome OS, version 106, expected October 2022, should
81+
contain a fix for this.
82+
</Text>
83+
<Text fontSize="md">
84+
Your program will be saved to your computer instead. Follow the
85+
steps on the next screen to transfer it to your micro:bit.
86+
</Text>
87+
<Text fontSize="sm">
88+
*<FormattedMessage id="webusb-why-use" />
89+
</Text>
90+
</Stack>
91+
<Flex justifyContent="center" width="100%">
92+
<Image
93+
width="100%"
94+
height="100%"
95+
src={chromeOSErrorImage}
96+
alt=""
97+
pb={3}
98+
/>
99+
</Flex>
100+
</HStack>
101+
</DialogBodyWrapper>
56102
);
57103
};
58104

@@ -63,7 +109,7 @@ interface WebUSBDialogFooterProps {
63109
const WebUSBDialogFooter = ({ onCancel }: WebUSBDialogFooterProps) => {
64110
return (
65111
<HStack spacing={2.5}>
66-
<Button onClick={onCancel} size="lg">
112+
<Button onClick={onCancel} size="lg" variant="solid">
67113
<FormattedMessage id="close-action" />
68114
</Button>
69115
</HStack>
Loading

0 commit comments

Comments
 (0)