also looking at this
fix(chrome): ship NSS's runtime providers and gate on a real render
#246
3 files
+114
-2
| @@ -0,0 +1,35 @@ | ||
| 1 | import { expect, test } from 'bun:test' | |
| 2 | import { readFileSync } from 'node:fs' | |
| 3 | import { resolve } from 'node:path' | |
| 4 | import { NSS_RUNTIME_PROVIDERS, recipe as chrome } from '../src/recipes/google.com/chrome' | |
| 5 | ||
| 6 | /* | |
| 7 | * Chrome loads libnss3 from its own lib directory ($ORIGIN/..), and NSS opens | |
| 8 | * its providers from there with dlopen - outside the DT_NEEDED graph, so no | |
| 9 | * dependency walk finds them. softokn's crypto is libfreeblpriv3 (libfreebl3 is | |
| 10 | * its stub); without it the installed browser aborted at startup with | |
| 11 | * nss_error=-8023 while `--version`, the recipe's only test, still passed. | |
| 12 | */ | |
| 13 | test('Chrome ships every NSS provider that NSS opens at runtime', () => { | |
| 14 | for (const file of ['libsoftokn3.so', 'libfreebl3.so', 'libfreeblpriv3.so', 'libfreeblpriv3.chk', 'libnssckbi.so']) | |
| 15 | expect(NSS_RUNTIME_PROVIDERS).toContain(file) | |
| 16 | ||
| 17 | const script = (chrome.build?.script ?? []).map(step => typeof step === 'string' ? step : '').join('\n') | |
| 18 | for (const file of NSS_RUNTIME_PROVIDERS) | |
| 19 | expect(script).toContain(`/lib/${file}`) | |
| 20 | expect(chrome.dependencies?.['mozilla.org/nss']).toBe('^3') | |
| 21 | }) | |
| 22 | ||
| 23 | test('the Linux release gate renders a page with the installed package, not just --version', () => { | |
| 24 | const gate = readFileSync(resolve(import.meta.dir, '../../../.github/scripts/linux-native-browser.ts'), 'utf8') | |
| 25 | expect(gate).toContain('--dump-dom') | |
| 26 | // A clean environment: only HOME and a PATH without the package, so an | |
| 27 | // inherited LD_LIBRARY_PATH cannot supply the library the package lacks. | |
| 28 | expect(gate).toContain(`env: { HOME: root, PATH: '/usr/bin:/bin', LD_DEBUG: 'files' }`) | |
| 29 | // And a host NSS cannot stand in: the providers must load from the package. | |
| 30 | expect(gate).toContain('calling init:') | |
| 31 | expect(gate).toContain('not the installed package') | |
| 32 | // The sandbox stays on. | |
| 33 | expect(gate).not.toContain("'--no-sandbox'") | |
| 34 | expect(gate).toContain('userns,') | |
| 35 | }) | |