mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
fix(browser)!: keep the Chromium sandbox for REA-launched browsers (#8738)
* fix(browser)!: keep the Chromium sandbox for REA-launched browsers Playwright appends --no-sandbox unless a launch passes chromiumSandbox: true. Neither the browser scenario launch nor the native module resolver passed it, so every REA-launched Chromium ran without its sandbox and REA_BROWSER_NO_SANDBOX had no effect. Both launch sites now take the sandbox decision from ChromiumSandbox.ts: off on Android or when REA_BROWSER_NO_SANDBOX=true, on otherwise. When Chromium reports that it cannot start its sandbox, the launch failure's remediation names the opt-out. Fixes #8722 BREAKING CHANGE: hosts where Chromium cannot create its sandbox, such as root users and Linux containers without user namespaces or a setuid sandbox, now fail to launch until REA_BROWSER_NO_SANDBOX=true is set. * fix(browser): name the sandbox opt-out on any sandboxed launch failure Chromium reports an unusable sandbox through several unrelated startup messages, including a misconfigured setuid helper and a refused namespace move, and Playwright recognizes only some of them. Matching individual messages missed real failures, so a sandboxed launch failure now always names REA_BROWSER_NO_SANDBOX=true as a conditional remediation and the retained startup diagnostics show whether the sandbox was the cause. * fix(browser): keep default recovery for resolver failures after launch The module resolver's outer catch also covers context, navigation and evaluation failures after the browser launched. Attaching the sandbox remediation there replaced their default recovery guidance. Attach the shared launch remediation only when a sandboxed launch itself fails. * docs(browser): note the Android sandbox exception for module traces
This commit is contained in:
7 files changed
+185
-22
No files matched your search
@@ -1,4 +1,8 @@
|
||||
import { snapshotEnvironment } from "../../process/snapshotEnvironment.js";
|
||||
import {
|
||||
chromiumLaunchRemediation,
|
||||
chromiumSandboxEnabled,
|
||||
} from "../ChromiumSandbox.js";
|
||||
import { isAbsolute } from "node:path";
|
||||
import { z } from "zod";
|
||||
import type {
|
||||
@@ -73,6 +77,20 @@ export type ModuleResolverLauncher = (
|
||||
const launch: ModuleResolverLauncher = async (options) =>
|
||||
(await import("playwright-core")).chromium.launch(options);
|
||||
|
||||
const moduleResolverFailure = (
|
||||
cause: unknown,
|
||||
executable: string,
|
||||
remediationAction: string | undefined,
|
||||
): ProviderAdapterError =>
|
||||
new ProviderAdapterError("native-module-resolver", OPERATION, {
|
||||
cause,
|
||||
...(remediationAction === undefined ? {} : { remediationAction }),
|
||||
diagnostics: {
|
||||
executable,
|
||||
error_message: cause instanceof Error ? cause.message : String(cause),
|
||||
},
|
||||
});
|
||||
|
||||
/** Use native import.meta.resolve in an owned context with locally fulfilled requests. */
|
||||
export class NativeModuleResolver implements WebModuleResolutionPort {
|
||||
#tail: Promise<void> = Promise.resolve();
|
||||
@@ -132,6 +150,7 @@ export class NativeModuleResolver implements WebModuleResolutionPort {
|
||||
},
|
||||
),
|
||||
);
|
||||
const chromiumSandbox = chromiumSandboxEnabled(this.environment);
|
||||
const deadline = new ProviderStartupDeadline(TIMEOUT_MS, options?.signal);
|
||||
let activeCall:
|
||||
| { settled: boolean; interruption?: AnalysisError }
|
||||
@@ -166,6 +185,7 @@ export class NativeModuleResolver implements WebModuleResolutionPort {
|
||||
);
|
||||
};
|
||||
let lease: AnalysisCleanupLease | undefined;
|
||||
let launched = false;
|
||||
let cleanup: Promise<void> | undefined;
|
||||
const close = (): Promise<void> => {
|
||||
if (cleanup === undefined && lease !== undefined) {
|
||||
@@ -197,17 +217,16 @@ export class NativeModuleResolver implements WebModuleResolutionPort {
|
||||
handleSIGINT: false,
|
||||
handleSIGTERM: false,
|
||||
handleSIGHUP: false,
|
||||
chromiumSandbox,
|
||||
args: [
|
||||
"--disable-dev-shm-usage",
|
||||
"--disable-background-networking",
|
||||
"--renderer-process-limit=1",
|
||||
"--js-flags=--max-old-space-size=128",
|
||||
...(this.environment.REA_BROWSER_NO_SANDBOX === "true"
|
||||
? ["--no-sandbox"]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
);
|
||||
launched = true;
|
||||
lease = new AnalysisCleanupLease(async () => {
|
||||
if (
|
||||
deadline.signal.aborted &&
|
||||
@@ -239,14 +258,15 @@ export class NativeModuleResolver implements WebModuleResolutionPort {
|
||||
cause instanceof AnalysisCapabilityUnavailableError ||
|
||||
cause instanceof BrowserObservationError
|
||||
? cause
|
||||
: new ProviderAdapterError("native-module-resolver", OPERATION, {
|
||||
: moduleResolverFailure(
|
||||
cause,
|
||||
diagnostics: {
|
||||
executable,
|
||||
error_message:
|
||||
cause instanceof Error ? cause.message : String(cause),
|
||||
},
|
||||
}),
|
||||
executable,
|
||||
// Only an unresolved sandboxed launch can be a sandbox failure;
|
||||
// later engine failures keep the default recovery guidance.
|
||||
launched || !chromiumSandbox
|
||||
? undefined
|
||||
: chromiumLaunchRemediation(true),
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
deadline.signal.removeEventListener("abort", onAbort);
|
||||
|
||||
Reference in new issue
Block a user