aboutsummaryrefslogtreecommitdiff
path: root/src/profile/list.ts
diff options
context:
space:
mode:
authoramankumarsingh77 <amankumarsingh7702@gmail.com>2026-07-28 20:29:29 +0530
committerAman Kumar <145339995+amankumarsingh77@users.noreply.github.com>2026-08-02 19:12:46 +0530
commita6ec1d0915106b127affbd6b5fcc9efec48ef712 (patch)
tree120b16ede45c1c8863291d3c7f139449c5638b28 /src/profile/list.ts
parenta2588bb315a56a8dfcd3aa8a261cdc19b160d079 (diff)
refactor(profile): strip comment noise
Removes module banners and comments restating the code. Keeps one-line notes for the ProcessSingleton user-data-dir rule, the sentinel-URL and async-spawn-error quirks, the replicated getAgentDir, pi's tilde-expansion mirroring, the Windows wmic removal, the macOS/Linux process-identification quirks, the picker's undefined-means-cancel contract, and the deliberately unpersisted browserContextId. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'src/profile/list.ts')
-rw-r--r--src/profile/list.ts48
1 files changed, 2 insertions, 46 deletions
diff --git a/src/profile/list.ts b/src/profile/list.ts
index 3915a98..6429b91 100644
--- a/src/profile/list.ts
+++ b/src/profile/list.ts
@@ -1,23 +1,3 @@
-/**
- * Browser profile enumeration.
- *
- * A Chromium user-data-dir registers its profiles in `Local State` under the
- * JSON key `profile.info_cache`, with `profile.profiles_order` giving the
- * user's own ordering and `profile.last_used` naming the active one. Those
- * keys are declared in Chromium's pref_names.h with no platform BUILDFLAG, so
- * the layout is identical on Linux, macOS, and Windows (the C++ constant is
- * now `kProfileAttributes`; the on-disk key never changed).
- *
- * Enumeration is two-tier so a Chromium fork or a future schema change cannot
- * blank the list:
- * tier 1 — `Local State` → `profile.info_cache` (authoritative: display
- * names, accounts, ordering)
- * tier 2 — scan subdirectories holding a `Preferences` file and read
- * `profile.name` + `account_info[0].email`
- *
- * Nothing here throws: an unreadable or malformed file yields an empty list so
- * callers degrade to the harness's pre-existing behavior.
- */
import { readdir, readFile } from "node:fs/promises";
import { join } from "node:path";
@@ -26,28 +6,18 @@ import { Compile } from "typebox/compile";
import { parseJson } from "../schemas/parse";
export type BrowserProfile = {
- /** Profile subdirectory name, e.g. "Default" or "Profile 1". */
readonly dir: string;
- /** Display name as shown in the browser's profile menu. */
readonly name: string;
- /** Signed-in account address, when the profile has one. */
readonly email?: string;
- /** Picker label — "Name (email)", or "Name (dir)" with no account. */
readonly label: string;
- /** True for the profile the browser reports as last used. */
readonly lastUsed: boolean;
};
-/** Directories inside a user-data-dir that are not user profiles. */
const NON_PROFILE_DIRS: ReadonlySet<string> = new Set([
"System Profile",
"Guest Profile",
]);
-/**
- * Picker label. The bracketed half is the account address when there is one,
- * and the profile directory otherwise, so every row keeps the same shape.
- */
export const formatProfileLabel = (name: string, email: string | undefined, dir: string): string =>
`${name} (${email && email.length > 0 ? email : dir})`;
@@ -72,10 +42,6 @@ const asRecord = (v: unknown): Record<string, unknown> | null =>
const asString = (v: unknown): string | undefined =>
typeof v === "string" && v.length > 0 ? v : undefined;
-/**
- * Order profiles the way the browser does: `profiles_order` first (in its own
- * sequence), then anything unlisted, alphabetically.
- */
const orderDirs = (dirs: ReadonlyArray<string>, order: ReadonlyArray<string>): ReadonlyArray<string> => {
const known = order.filter((d) => dirs.includes(d));
const rest = dirs.filter((d) => !known.includes(d)).sort((a, b) => a.localeCompare(b));
@@ -98,7 +64,6 @@ const buildProfile = (
};
};
-/** Tier 1 — `Local State` → `profile.info_cache`. */
const listFromLocalState = async (userDataDir: string): Promise<ReadonlyArray<BrowserProfile>> => {
const localState = await readJsonFile(join(userDataDir, "Local State"));
if (!localState) return [];
@@ -116,8 +81,7 @@ const listFromLocalState = async (userDataDir: string): Promise<ReadonlyArray<Br
if (NON_PROFILE_DIRS.has(dir)) continue;
const entry = asRecord(value);
if (!entry) continue;
- // Ephemeral (guest-like) profiles vanish when their window closes — never
- // offer one as a durable pin.
+ // Ephemeral (guest-like) profiles vanish when their window closes, so they can never be a durable pin.
if (entry["is_ephemeral"] === true) continue;
entries.push({ dir, entry });
}
@@ -128,16 +92,12 @@ const listFromLocalState = async (userDataDir: string): Promise<ReadonlyArray<Br
return ordered.flatMap((dir) => {
const entry = byDir.get(dir);
if (!entry) return [];
- // `name` is the user-visible profile name; `gaia_name` is the Google
- // account's own display name and is the better fallback when a profile
- // still carries an auto-generated name like "Person 1".
const name = asString(entry["name"]) ?? asString(entry["gaia_name"]);
const email = asString(entry["user_name"]);
return [buildProfile(dir, name, email, dir === lastUsed)];
});
};
-/** Tier 2 — directory scan, reading each profile's own `Preferences`. */
const listFromPreferencesScan = async (userDataDir: string): Promise<ReadonlyArray<BrowserProfile>> => {
let dirents;
try {
@@ -154,7 +114,7 @@ const listFromPreferencesScan = async (userDataDir: string): Promise<ReadonlyArr
const profiles: BrowserProfile[] = [];
for (const dir of candidates) {
const prefs = await readJsonFile(join(userDataDir, dir, "Preferences"));
- if (!prefs) continue; // not a profile directory
+ if (!prefs) continue;
const profileNode = asRecord(prefs["profile"]);
const name = profileNode ? asString(profileNode["name"]) : undefined;
const accounts = prefs["account_info"];
@@ -165,10 +125,6 @@ const listFromPreferencesScan = async (userDataDir: string): Promise<ReadonlyArr
return profiles;
};
-/**
- * Every selectable profile in a user-data-dir, best-effort. Returns an empty
- * array when the directory is unreadable or holds no profiles.
- */
export const listProfiles = async (userDataDir: string): Promise<ReadonlyArray<BrowserProfile>> => {
const fromLocalState = await listFromLocalState(userDataDir);
if (fromLocalState.length > 0) return fromLocalState;