Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 111 additions & 6 deletions apps/desktop/electron/bootstrap-platform.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import assert from 'node:assert/strict'
import fs from 'node:fs'

import { test } from 'vitest'
import { test, vi } from 'vitest'

import {
bundledRuntimeImportCheck,
detectRemoteDisplay,
isVirtualizedGpuEnvironment,
isWindowsBinaryPathInWsl,
isWslEnvironment,
resolveLinuxPasswordStore
Expand All @@ -18,6 +20,30 @@ test('isWslEnvironment detects WSL2 env vars on linux', () => {
assert.equal(isWslEnvironment({ WSL_DISTRO_NAME: 'Ubuntu' }, 'darwin'), false)
})

test('isVirtualizedGpuEnvironment detects QEMU via injected DMI vendor', () => {
assert.match(String(isVirtualizedGpuEnvironment('linux', 'QEMU', '')), /QEMU detected/)
assert.equal(isVirtualizedGpuEnvironment('linux', 'LENOVO', ''), null)
assert.equal(isVirtualizedGpuEnvironment('darwin', 'QEMU', ''), null)
})

test('isVirtualizedGpuEnvironment detects Apple Virtualization.framework via injected product name', () => {
assert.match(
String(isVirtualizedGpuEnvironment('linux', 'Apple Inc.', 'Apple Virtualization Generic Platform')),
/Apple Virtualization\.framework detected/
)
assert.equal(isVirtualizedGpuEnvironment('linux', 'Apple Inc.', 'MacBookPro18,3'), null)
})

test('isVirtualizedGpuEnvironment returns null when the sysfs read fails', () => {
const spy = vi.spyOn(fs, 'readFileSync').mockImplementation(() => {
throw new Error('ENOENT')
})

assert.equal(isVirtualizedGpuEnvironment('linux'), null)

spy.mockRestore()
})

test('isWindowsBinaryPathInWsl blocks Windows binary types on WSL', () => {
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/hermes.exe', { isWsl: true }), true)
assert.equal(isWindowsBinaryPathInWsl('/mnt/c/Tools/hermes.cmd', { isWsl: true }), true)
Expand All @@ -35,18 +61,40 @@ test('bundledRuntimeImportCheck selects platform-specific import checks', () =>

test('detectRemoteDisplay keeps GPU on for local sessions', () => {
// Plain local X11, Wayland, native Windows, native macOS — no remote signal.
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux' }), null)
assert.equal(detectRemoteDisplay({ env: { WAYLAND_DISPLAY: 'wayland-0' }, platform: 'linux' }), null)
// sysVendor/productName are explicitly injected as empty so this test is
// isolated from whatever real hardware/VM it happens to run on.
assert.equal(
detectRemoteDisplay({ env: { DISPLAY: ':0' }, platform: 'linux', sysVendor: '', productName: '' }),
null
)
assert.equal(
detectRemoteDisplay({ env: { WAYLAND_DISPLAY: 'wayland-0' }, platform: 'linux', sysVendor: '', productName: '' }),
null
)
assert.equal(detectRemoteDisplay({ env: { SESSIONNAME: 'Console' }, platform: 'win32' }), null)
assert.equal(detectRemoteDisplay({ env: {}, platform: 'darwin' }), null)
})

test('detectRemoteDisplay does not treat WSLg as remote', () => {
// WSLg renders locally via vGPU and doesn't show the flicker, so a WSL
// session with a local DISPLAY keeps hardware acceleration on.
assert.equal(detectRemoteDisplay({ env: { WSL_DISTRO_NAME: 'Ubuntu', DISPLAY: ':0' }, platform: 'linux' }), null)
// sysVendor/productName injected as empty to isolate from real host hardware.
assert.equal(
detectRemoteDisplay({ env: { WSL_INTEROP: '/run/WSL/1_interop', DISPLAY: ':0' }, platform: 'linux' }),
detectRemoteDisplay({
env: { WSL_DISTRO_NAME: 'Ubuntu', DISPLAY: ':0' },
platform: 'linux',
sysVendor: '',
productName: ''
}),
null
)
assert.equal(
detectRemoteDisplay({
env: { WSL_INTEROP: '/run/WSL/1_interop', DISPLAY: ':0' },
platform: 'linux',
sysVendor: '',
productName: ''
}),
null
)
})
Expand All @@ -63,7 +111,10 @@ test('detectRemoteDisplay flags SSH sessions on any platform', () => {
test('detectRemoteDisplay flags forwarded X11 displays but not local ones', () => {
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: 'localhost:10.0' }, platform: 'linux' })), /x11-forwarding/)
assert.match(String(detectRemoteDisplay({ env: { DISPLAY: '192.168.1.5:0' }, platform: 'linux' })), /x11-forwarding/)
assert.equal(detectRemoteDisplay({ env: { DISPLAY: ':1' }, platform: 'linux' }), null)
assert.equal(
detectRemoteDisplay({ env: { DISPLAY: ':1' }, platform: 'linux', sysVendor: '', productName: '' }),
null
)
})

test('detectRemoteDisplay flags RDP sessions', () => {
Expand All @@ -86,6 +137,60 @@ test('detectRemoteDisplay honors the HERMES_DESKTOP_DISABLE_GPU override both wa
)
})

test('detectRemoteDisplay flags virtualized GPU environments via injected sysVendor', () => {
assert.match(
String(detectRemoteDisplay({ env: {}, platform: 'linux', sysVendor: 'QEMU', productName: '' })),
/virtualized-gpu \(QEMU detected/
)
assert.equal(
detectRemoteDisplay({ env: {}, platform: 'linux', sysVendor: 'LENOVO', productName: '' }),
null
)
})

test('detectRemoteDisplay flags Apple Virtualization.framework (UTM on Apple Silicon) via injected productName', () => {
assert.match(
String(
detectRemoteDisplay({
env: {},
platform: 'linux',
sysVendor: 'Apple Inc.',
productName: 'Apple Virtualization Generic Platform'
})
),
/virtualized-gpu \(Apple Virtualization\.framework detected/
)
assert.equal(
detectRemoteDisplay({
env: {},
platform: 'linux',
sysVendor: 'Apple Inc.',
productName: 'MacBookPro18,3'
}),
null
)
})

test('detectRemoteDisplay honors HERMES_DESKTOP_DISABLE_GPU override over virtualized GPU', () => {
assert.equal(
detectRemoteDisplay({
env: { HERMES_DESKTOP_DISABLE_GPU: 'false' },
platform: 'linux',
sysVendor: 'QEMU',
productName: ''
}),
null
)
assert.equal(
detectRemoteDisplay({
env: { HERMES_DESKTOP_DISABLE_GPU: 'false' },
platform: 'linux',
sysVendor: 'Apple Inc.',
productName: 'Apple Virtualization Generic Platform'
}),
null
)
})
test('resolveLinuxPasswordStore applies known backends on linux', () => {
for (const store of ['gnome-libsecret', 'kwallet', 'kwallet5', 'kwallet6', 'basic']) {
assert.deepEqual(resolveLinuxPasswordStore({ env: { HERMES_DESKTOP_PASSWORD_STORE: store }, platform: 'linux' }), {
Expand Down
46 changes: 43 additions & 3 deletions apps/desktop/electron/bootstrap-platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,38 @@ function isWslEnvironment(env = process.env, platform = process.platform, kernel
}
}

function readDmiFieldSafe(field) {
try {
return fs.readFileSync(`/sys/class/dmi/id/${field}`, 'utf8').trim()
} catch {
return null
}
}

function isVirtualizedGpuEnvironment(platform = process.platform, sysVendor = null, productName = null) {
if (platform !== 'linux') {
return null
}

const vendor = sysVendor ?? readDmiFieldSafe('sys_vendor') ?? ''

if (/qemu/i.test(vendor)) {
return `QEMU detected via DMI sys_vendor (${vendor})`
}

// UTM on Apple Silicon defaults to Apple's Virtualization.framework backend
// instead of QEMU emulation — sys_vendor there just reflects the host
// ("Apple Inc."), so it's indistinguishable from real Mac hardware. The
// guest's product_name is the reliable signal for this backend instead.
const product = productName ?? readDmiFieldSafe('product_name') ?? ''

if (/apple virtualization/i.test(product)) {
return `Apple Virtualization.framework detected via DMI product_name (${product})`
}

return null
}

function isWindowsBinaryPathInWsl(
filePath,
options: { isWsl?: boolean; env?: NodeJS.ProcessEnv; platform?: NodeJS.Platform } = {}
Expand Down Expand Up @@ -60,7 +92,9 @@ const GPU_OVERRIDE_OFF = new Set(['0', 'false', 'no', 'off'])
*
* Pure + dependency-free so it can be unit-tested and called before app ready.
*/
function detectRemoteDisplay(options: { env?: NodeJS.ProcessEnv; platform?: NodeJS.Platform } = {}) {
function detectRemoteDisplay(
options: { env?: NodeJS.ProcessEnv; platform?: NodeJS.Platform; sysVendor?: string; productName?: string } = {}
) {
const env = options.env ?? process.env
const platform = options.platform ?? process.platform

Expand Down Expand Up @@ -88,10 +122,15 @@ function detectRemoteDisplay(options: { env?: NodeJS.ProcessEnv; platform?: Node
// NB: WSLg deliberately isn't treated as remote — it reports
// GPU-accelerated vGPU surfaces locally and doesn't show the flicker.
const display = String(env.DISPLAY || '')

if (display.includes(':') && display.split(':')[0]) {
return `x11-forwarding (DISPLAY=${display})`
}

const virtualizedGpuReason = isVirtualizedGpuEnvironment(platform, options.sysVendor, options.productName)

if (virtualizedGpuReason) {
return `virtualized-gpu (${virtualizedGpuReason})`
}
}

if (platform === 'win32') {
Expand Down Expand Up @@ -144,7 +183,8 @@ function resolveLinuxPasswordStore(options: { env?: NodeJS.ProcessEnv; platform?
export {
bundledRuntimeImportCheck,
detectRemoteDisplay,
isVirtualizedGpuEnvironment,
isWindowsBinaryPathInWsl,
isWslEnvironment,
resolveLinuxPasswordStore
}
}