79 lines · 3.0 KB · TypeScript
RawDownload
export type LinuxPasswordStorePreference =  | "auto"  | "gnome-libsecret"  | "kwallet"  | "kwallet5"  | "kwallet6";export type LinuxPasswordStoreSwitch = Exclude<LinuxPasswordStorePreference, "auto">; export const DEFAULT_LINUX_PASSWORD_STORE: LinuxPasswordStorePreference = "auto"; // Chromium matches XDG_CURRENT_DESKTOP values case-sensitively and returns on the first value it// recognizes, so these stay exact literals and are scanned in order. Omitting a real desktop fails// safe: we force gnome-libsecret, which is the backend Chromium selects for all of these anyway.const ELECTRON_LIBSECRET_DESKTOPS = new Set([  "Deepin",  "GNOME",  "Pantheon",  "UKUI",  "Unity",  "X-Cinnamon",  "XFCE",]);// Chromium selects a KWallet generation for KDE from KDE_SESSION_VERSION, so it needs no help.const ELECTRON_KDE_DESKTOP = "KDE";// Chromium recognizes LXQt and still selects basic text for it, so it does need a forced backend.const ELECTRON_UNPROTECTED_DESKTOPS = new Set(["LXQt"]); export function normalizeLinuxPasswordStorePreference(  value: unknown,): LinuxPasswordStorePreference {  return value === "gnome-libsecret" ||    value === "kwallet" ||    value === "kwallet5" ||    value === "kwallet6"    ? value    : DEFAULT_LINUX_PASSWORD_STORE;} // Auto mode asks one question: will Electron select a real keyring on its own? If so, stay out of// the way, which is how canonical KDE sessions keep the KWallet generation Chromium picks for them.// Otherwise force gnome-libsecret, because the alternative is basic text, which is barely// encryption at all. Forcing never guesses a KWallet generation; a KDE session that needs a// specific one sets linuxPasswordStore explicitly.export function resolveLinuxPasswordStoreSwitch(input: {  readonly preference: LinuxPasswordStorePreference;  readonly env: NodeJS.ProcessEnv;}): LinuxPasswordStoreSwitch | null {  if (input.preference !== "auto") {    return input.preference;  }   return electronSelectsProtectedBackend(input.env) ? null : "gnome-libsecret";} // Only an exact XDG_CURRENT_DESKTOP literal proves Electron will protect the session. Chromium can// also reach a real backend through DESKTOP_SESSION and the legacy KDE markers, but those are the// variables a previous session leaves behind, and trusting them is what let stale hints suppress// the forced backend before. Forcing where Chromium would have chosen libsecret is harmless, since// it lands on the same backend.function electronSelectsProtectedBackend(env: NodeJS.ProcessEnv): boolean {  for (const name of splitDesktopNameList(env.XDG_CURRENT_DESKTOP)) {    const trimmed = name.trim();    if (trimmed.length === 0) {      continue;    }    if (trimmed === ELECTRON_KDE_DESKTOP || ELECTRON_LIBSECRET_DESKTOPS.has(trimmed)) {      return true;    }    if (ELECTRON_UNPROTECTED_DESKTOPS.has(trimmed)) {      return false;    }  }   return false;} function splitDesktopNameList(value: string | undefined): string[] {  return value?.split(":") ?? [];}