54 lines
2.7 KiB
TypeScript
54 lines
2.7 KiB
TypeScript
/**
|
|||
|
|
* What a container has to have before anything can be opened *inside* it.
|
||
|
|
*
|
||
|
|
* The Browser tab asks this to decide what to offer; the terminal's URL toast
|
||
|
|
* asks it to decide which of its two buttons should lead. Both need the same
|
||
|
|
* answer, so the predicates live here rather than beside either caller — the
|
||
|
|
* failure this avoids is the toast steering a user at a container-side browser
|
||
|
|
* that the Browser tab is, on the very same screen, offering to install.
|
||
|
|
*
|
||
|
|
* The important thing to know about `PlaywrightDetection` is that browsers are
|
||
|
|
* deliberately **not** baked into the image: the libraries they link against
|
||
|
|
* are, the binaries are a user-pressed install. So "Playwright is present" and
|
||
|
|
* "a page can actually be opened" are two different questions, and a fresh
|
||
|
|
* project answers yes to neither.
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { PlaywrightDetection } from "./types";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Mirrors Rust `PlaywrightDetection::is_usable` — the packages the live
|
||
|
|
* dashboard needs. Says nothing about whether a browser exists to show in it.
|
||
|
|
*/
|
||
|
|
export function isBrowserViewUsable(d: PlaywrightDetection | null): boolean {
|
||
|
|
return d !== null && d.playwright_version !== null && d.has_bind && d.cli_entry !== null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Whether `openPageInContainerBrowser` has a browser to launch.
|
||
|
|
*
|
||
|
|
* Stricter than {@link isBrowserViewUsable} on purpose: the packages can be
|
||
|
|
* installed with `~/.cache/ms-playwright` still empty, which is exactly the
|
||
|
|
* state a `playwright install` step exists to leave behind, and launching into
|
||
|
|
* it fails several seconds after the click.
|
||
|
|
*
|
||
|
|
* Unknown reads as "no". A probe that could not run (stopped container, an
|
||
|
|
* image predating these fields) leaves the executable fields absent, and the
|
||
|
|
* caller's fallback — the host browser — is the one that at least reports its
|
||
|
|
* own failure. Over-refusing costs a user one extra click on a button that is
|
||
|
|
* still right there; over-accepting costs them a sign-in that goes nowhere.
|
||
|
|
*/
|
||
|
|
export function canOpenPageInContainerBrowser(d: PlaywrightDetection | null): boolean {
|
||
|
|
if (!isBrowserViewUsable(d) || !d) return false;
|
||
|
|
// The viewer's own Chromium, confirmed on disk by the probe.
|
||
|
|
if (d.chromium_executable_exists) return true;
|
||
|
|
// Google Chrome is an apt package, so it is never in `browsers` and has no
|
||
|
|
// revision to skew against.
|
||
|
|
if (d.chrome_channel !== null) return true;
|
||
|
|
// `== null`, not `=== null`: a probe from a container predating the
|
||
|
|
// executable fields omits them entirely, and `undefined` there means "didn't
|
||
|
|
// answer", not "missing". In that case a non-empty bundle list is the only
|
||
|
|
// evidence available, and it is better than nothing.
|
||
|
|
return d.chromium_executable == null && d.browsers.length > 0;
|
||
|
|
}
|