Skip to content

Commit dc30825

Browse files
Fix macOS detection in desktop app and Chromium
This commit addresses an issue where macOS was incorrectly identified as iPadOS in Chromium-based browsers. The root cause was related to touch support detection being inaccurately triggered on Chromium browsers, leading to misidentification. The bug caused two issues: 1. Desktop version: Script execution on macOS did not work as the desktop app wrongly assumed that it was running on iPadOS. 2. Web and desktop version: The UI didn't default to macOS, presuming an iPadOS environment. This bug was exclusive to Chromium browsers on macOS. Firefox and Safari didn't exhibit this behavior, as they handle touch event browser API as differently and initially expected. Key changes: - Improve touch support detection to accurately differentiate between macOS and iPadOS by removing an identification method used that is not reliable for Chromium-based browsers. - Update user agent detection to correctly identify Electron-based applications as macOS even without needing the information from the preloader context.
1 parent 40f5eb8 commit dc30825

File tree

5 files changed

+33
-22
lines changed

5 files changed

+33
-22
lines changed

src/infrastructure/RuntimeEnvironment/BrowserOs/BrowserConditions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const BrowserConditions: readonly BrowserCondition[] = [
5757
{
5858
operatingSystem: OperatingSystem.iPadOS,
5959
existingPartsInSameUserAgent: ['Macintosh'], // Reported by Safari on iPads running ≥ iPadOS 13
60+
notExistingPartsInUserAgent: ['Electron'], // Electron supports only macOS, not iPadOS
6061
touchSupport: TouchSupportExpectation.MustExist, // Safari same user agent as desktop macOS
6162
},
6263
{

src/infrastructure/RuntimeEnvironment/TouchSupportDetection.ts

+21-16
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,48 @@ export interface BrowserTouchSupportAccessor {
1010
navigatorMaxTouchPoints: () => number | undefined;
1111
windowMatchMediaMatches: (query: string) => boolean;
1212
documentOntouchend: () => undefined | unknown;
13-
windowTouchEvent: () => undefined | unknown;
1413
}
1514

15+
/*
16+
Touch support checks are inconsistent across different browsers and OS.
17+
`✅` and `❌` indicate correct and incorrect detections, respectively.
18+
*/
1619
const TouchSupportChecks: ReadonlyArray<(accessor: BrowserTouchSupportAccessor) => boolean> = [
1720
/*
18-
Mobile: Chrome, Safari, Firefox on iOS and Android
19-
Touch-enabled Windows laptop: Chrome
20-
(Chromium has removed ontouch* events on desktop since Chrome 70+.)
21-
❌ Touch-enabled Windows laptop: Firefox
21+
Mobile (iOS & Android): ✅ Chrome, Safari, ✅ Firefox
22+
Touch-enabled Windows laptop: Chrome (reports no touch), ❌ Firefox (reports no touch)
23+
Chromium has removed ontouch* events on desktop since Chrome 70+
24+
Non-touch macOS: ✅ Firefox, ✅ Safari, ✅ Chromium
2225
*/
2326
(accessor) => accessor.documentOntouchend() !== undefined,
2427
/*
25-
Mobile: Chrome, Safari, Firefox on iOS and Android
26-
Touch-enabled Windows laptop: Chrome
27-
❌ Touch-enabled Windows laptop: Firefox
28+
Mobile (iOS & Android): ✅ Chrome, Safari, ✅ Firefox
29+
Touch-enabled Windows laptop: Chrome, ❌ Firefox (reports no touch)
30+
Non-touch macOS: ✅ Firefox, ✅ Safari, ✅ Chromium
2831
*/
2932
(accessor) => {
3033
const maxTouchPoints = accessor.navigatorMaxTouchPoints();
3134
return maxTouchPoints !== undefined && maxTouchPoints > 0;
3235
},
3336
/*
34-
Mobile: Chrome, Safari, Firefox on iOS and Android
35-
Touch-enabled Windows laptop: Chrome
36-
❌ Touch-enabled Windows laptop: Firefox
37+
Mobile (iOS & Android): ✅ Chrome, Safari, ✅ Firefox
38+
Touch-enabled Windows laptop: Chrome, ❌ Firefox (reports no touch)
39+
Non-touch macOS: ✅ Firefox, ✅ Safari, ✅ Chromium
3740
*/
3841
(accessor) => accessor.windowMatchMediaMatches('(any-pointer: coarse)'),
42+
3943
/*
40-
✅ Mobile: Chrome, Safari, Firefox on iOS and Android
41-
✅ Touch-enabled Windows laptop: Chrome
42-
❌ Touch-enabled Windows laptop: Firefox
44+
Do not check window.TouchEvent === undefined, as it incorrectly
45+
reports touch support on Chromium macOS even though there is no
46+
touch support.
47+
Mobile (iOS & Android): ✅ Chrome, ✅ Safari, ✅ Firefox
48+
Touch-enabled Windows laptop: ✅ Chrome, ❌ Firefox (reports no touch)
49+
Non-touch macOS: ✅ Firefox, ✅ Safari, ❌ Chromium (reports touch)
4350
*/
44-
(accessor) => accessor.windowTouchEvent() !== undefined,
4551
];
4652

4753
const GlobalTouchSupportAccessor: BrowserTouchSupportAccessor = {
4854
navigatorMaxTouchPoints: () => navigator.maxTouchPoints,
4955
windowMatchMediaMatches: (query: string) => window.matchMedia(query)?.matches,
5056
documentOntouchend: () => document.ontouchend,
51-
windowTouchEvent: () => window.TouchEvent,
5257
} as const;

tests/integration/infrastructure/RuntimeEnvironment/BrowserOs/BrowserOsTestCases.ts

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ export const BrowserOsTestCases: ReadonlyArray<BrowserOsTestCase> = [
3737
'Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1',
3838
// UC Browser:
3939
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.0.1308.1016 Safari/537.36',
40+
// Electron:
41+
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.54 Electron/27.0.0 Safari/537.36',
4042
],
4143
}),
4244
...createTests({
@@ -56,6 +58,8 @@ export const BrowserOsTestCases: ReadonlyArray<BrowserOsTestCase> = [
5658
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.82 Safari/537.36 OPR/29.0.1795.41 (Edition beta)',
5759
// Edge:
5860
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0',
61+
// Electron:
62+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.54 Electron/27.0.0 Safari/537.36',
5963
],
6064
}),
6165
...createTests({
@@ -68,6 +72,8 @@ export const BrowserOsTestCases: ReadonlyArray<BrowserOsTestCase> = [
6872
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
6973
// Edge:
7074
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188',
75+
// Electron:
76+
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.54 Electron/27.0.0 Safari/537.36',
7177
],
7278
}),
7379
...createTests({

tests/integration/presentation/bootstrapping/Modules/MobileSafariDetectionTestCases.ts

+5
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ export const MobileSafariDetectionTestCases: ReadonlyArray<PlatformTestCase> = [
5858
operatingSystem: OperatingSystem.macOS,
5959
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
6060
},
61+
{
62+
deviceInfo: 'macOS (Electron)',
63+
operatingSystem: OperatingSystem.macOS,
64+
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.54 Electron/27.0.0 Safari/537.36',
65+
},
6166
{
6267
deviceInfo: 'iPad (iPadOS 17)',
6368
operatingSystem: OperatingSystem.iPadOS,

tests/unit/infrastructure/RuntimeEnvironment/TouchSupportDetection.spec.ts

-6
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ describe('TouchSupportDetection', () => {
3232
}),
3333
expectedTouch: true,
3434
},
35-
{
36-
description: 'detects touch capability with defined window.TouchEvent',
37-
expectedTouch: true,
38-
accessor: createMockAccessor({ windowTouchEvent: () => class {} }),
39-
},
4035
];
4136
testScenarios.forEach(({ description, accessor, expectedTouch }) => {
4237
it(`${description} - returns ${expectedTouch}`, () => {
@@ -56,7 +51,6 @@ function createMockAccessor(
5651
navigatorMaxTouchPoints: () => undefined,
5752
windowMatchMediaMatches: () => false,
5853
documentOntouchend: () => undefined,
59-
windowTouchEvent: () => undefined,
6054
};
6155
return {
6256
...defaultTouchSupport,

0 commit comments

Comments
 (0)