authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-05 00:12:39-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-05 00:12:39-07:00
log14da634577773d291c494635c1a4bcdb0e70f9ee
tree6854451d0837ac9584f0cd4bd3a0f5274cbc7b9e
parent1550f1b742138df8b31b24e34ddea58c80afb3cc
signature Signed by PGP key B5690EEEBB952194

refactor(desktop): remove unused keyring remediation text (#9981)


2 files changed, 0 insertions(+), 176 deletions(-)

apps/desktop/src/linuxSecretStorage.test.ts-77
......@@ -3,7 +3,6 @@ import { describe, expect, it } from "vite-plus/test";
33import {
44 normalizeLinuxPasswordStorePreference,
55 resolveLinuxPasswordStoreSwitch,
6 resolveLinuxSecretStorageUnavailableMessage,
76} from "./linuxSecretStorage.ts";
87
98const autoSwitch = (env: NodeJS.ProcessEnv) =>
......@@ -124,80 +123,4 @@ describe("linuxSecretStorage", () => {
124123 }),
125124 ).toBe("gnome-libsecret");
126125 });
127
128 it("uses GNOME Keyring remediation for libsecret and unknown backends", () => {
129 expect(
130 resolveLinuxSecretStorageUnavailableMessage({
131 configuredPreference: "auto",
132 selectedBackend: "gnome_libsecret",
133 env: { XDG_CURRENT_DESKTOP: "niri" },
134 }),
135 ).toContain("GNOME Keyring");
136 });
137
138 it("prefers explicit libsecret selection over KDE desktop heuristics", () => {
139 expect(
140 resolveLinuxSecretStorageUnavailableMessage({
141 configuredPreference: "gnome-libsecret",
142 selectedBackend: "unknown",
143 env: { XDG_CURRENT_DESKTOP: "KDE" },
144 }),
145 ).toContain("GNOME Keyring");
146 expect(
147 resolveLinuxSecretStorageUnavailableMessage({
148 configuredPreference: "auto",
149 selectedBackend: "gnome_libsecret",
150 env: { XDG_CURRENT_DESKTOP: "KDE" },
151 }),
152 ).toContain("GNOME Keyring");
153 });
154
155 it("prefers explicit KWallet preference over selected gnome-libsecret backend", () => {
156 expect(
157 resolveLinuxSecretStorageUnavailableMessage({
158 configuredPreference: "kwallet6",
159 selectedBackend: "gnome_libsecret",
160 env: { XDG_CURRENT_DESKTOP: "niri" },
161 }),
162 ).toContain("KWallet");
163 expect(
164 resolveLinuxSecretStorageUnavailableMessage({
165 configuredPreference: "kwallet",
166 selectedBackend: "gnome-libsecret",
167 env: {},
168 }),
169 ).toContain("KWallet");
170 });
171
172 it("uses KWallet remediation wording for KDE-looking sessions", () => {
173 expect(
174 resolveLinuxSecretStorageUnavailableMessage({
175 configuredPreference: "auto",
176 selectedBackend: "kwallet6",
177 env: {},
178 }),
179 ).toContain("KWallet");
180 expect(
181 resolveLinuxSecretStorageUnavailableMessage({
182 configuredPreference: "auto",
183 selectedBackend: "unknown",
184 env: { XDG_CURRENT_DESKTOP: "KDE" },
185 }),
186 ).toContain("KWallet");
187 expect(
188 resolveLinuxSecretStorageUnavailableMessage({
189 configuredPreference: "auto",
190 selectedBackend: "unknown",
191 env: { DESKTOP_SESSION: "plasmawayland" },
192 }),
193 ).toContain("KWallet");
194 // A desktop name outranks a bare KDE marker when choosing the wording.
195 expect(
196 resolveLinuxSecretStorageUnavailableMessage({
197 configuredPreference: "auto",
198 selectedBackend: "unknown",
199 env: { GDMSESSION: "gnome", KDE_FULL_SESSION: "true" },
200 }),
201 ).toContain("GNOME Keyring");
202 });
203126});
apps/desktop/src/linuxSecretStorage.ts-99
......@@ -25,9 +25,6 @@ const ELECTRON_KDE_DESKTOP = "KDE";
2525// Chromium recognizes LXQt and still selects basic text for it, so it does need a forced backend.
2626const ELECTRON_UNPROTECTED_DESKTOPS = new Set(["LXQt"]);
2727
28const KDE_NAME_PREFIXES = ["kde", "plasma"];
29const NEGATIVE_FLAG_VALUES = new Set(["0", "false", "no", "off"]);
30
3128export function normalizeLinuxPasswordStorePreference(
3229 value: unknown,
3330): LinuxPasswordStorePreference {
......@@ -77,102 +74,6 @@ function electronSelectsProtectedBackend(env: NodeJS.ProcessEnv): boolean {
7774 return false;
7875}
7976
80export function resolveLinuxSecretStorageUnavailableMessage(input: {
81 readonly configuredPreference: LinuxPasswordStorePreference;
82 readonly selectedBackend: string | null;
83 readonly env: NodeJS.ProcessEnv;
84}): string {
85 if (input.configuredPreference === "gnome-libsecret") {
86 return getGnomeKeyringRemediationMessage();
87 }
88
89 if (
90 input.configuredPreference === "kwallet" ||
91 input.configuredPreference === "kwallet5" ||
92 input.configuredPreference === "kwallet6"
93 ) {
94 return getKWalletRemediationMessage();
95 }
96
97 const backend = normalizeSelectedStorageBackend(input.selectedBackend);
98 if (backend === "gnome-libsecret") {
99 return getGnomeKeyringRemediationMessage();
100 }
101
102 if (
103 backend === "kwallet" ||
104 backend === "kwallet5" ||
105 backend === "kwallet6" ||
106 looksLikeKdeSession(input.env)
107 ) {
108 return getKWalletRemediationMessage();
109 }
110
111 return getGnomeKeyringRemediationMessage();
112}
113
114function getGnomeKeyringRemediationMessage(): string {
115 return "T3 Code could not access GNOME Keyring to save this environment credential. Install and start GNOME Keyring, then restart T3 Code.";
116}
117
118function getKWalletRemediationMessage(): string {
119 return "T3 Code could not access KWallet to save this environment credential. Enable the KDE wallet subsystem in System Settings, then restart T3 Code.";
120}
121
122// Advisory only: this picks between the GNOME Keyring and KWallet wording in the failure notice. It
123// never decides which backend to select, so a loose match costs a user slightly wrong instructions
124// rather than an unprotected credential store.
125function looksLikeKdeSession(env: NodeJS.ProcessEnv): boolean {
126 const currentDesktopNames = nonEmptyDesktopNames(env.XDG_CURRENT_DESKTOP);
127 if (currentDesktopNames.length > 0) {
128 return currentDesktopNames.some(isKdeDesktopName);
129 }
130
131 const legacyNames = legacyDesktopNames(env);
132 if (legacyNames.length > 0) {
133 return legacyNames.some(isKdeDesktopName);
134 }
135
136 return isSet(env.KDE_SESSION_VERSION) || isAffirmativeFlag(env.KDE_FULL_SESSION);
137}
138
139function isKdeDesktopName(name: string): boolean {
140 return KDE_NAME_PREFIXES.some((prefix) => name.startsWith(prefix));
141}
142
143function legacyDesktopNames(env: NodeJS.ProcessEnv): string[] {
144 return [env.XDG_SESSION_DESKTOP, env.DESKTOP_SESSION, env.GDMSESSION].flatMap((entry) => {
145 const normalized = normalizeDesktopName(entry);
146 return normalized ? [normalized] : [];
147 });
148}
149
150function nonEmptyDesktopNames(value: string | undefined): string[] {
151 return splitDesktopNameList(value).flatMap((entry) => {
152 const normalized = normalizeDesktopName(entry);
153 return normalized ? [normalized] : [];
154 });
155}
156
157function isSet(value: string | undefined): boolean {
158 return Boolean(value?.trim());
159}
160
161function isAffirmativeFlag(value: string | undefined): boolean {
162 const normalized = value?.trim().toLowerCase();
163 return normalized ? !NEGATIVE_FLAG_VALUES.has(normalized) : false;
164}
165
16677function splitDesktopNameList(value: string | undefined): string[] {
16778 return value?.split(":") ?? [];
16879}
169
170function normalizeDesktopName(value: string | undefined): string | null {
171 const normalized = value?.trim().toLowerCase();
172 return normalized && normalized.length > 0 ? normalized : null;
173}
174
175function normalizeSelectedStorageBackend(value: string | null): string | null {
176 const normalized = value?.trim().toLowerCase().replace(/_/gu, "-");
177 return normalized && normalized.length > 0 ? normalized : null;
178}