diff --git a/extensions/browser/src/browser/chrome.profile-decoration.ts b/extensions/browser/src/browser/chrome.profile-decoration.ts index 8739860e2a4..dd15dca9d5d 100644 --- a/extensions/browser/src/browser/chrome.profile-decoration.ts +++ b/extensions/browser/src/browser/chrome.profile-decoration.ts @@ -30,6 +30,16 @@ function safeWriteJson(filePath: string, data: Record) { fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); } +function asRecord(value: unknown): Record | null { + return typeof value === "object" && value !== null && !Array.isArray(value) + ? (value as Record) + : null; +} + +function readNestedRecord(root: unknown, key: string): Record | null { + return asRecord(asRecord(root)?.[key]); +} + function setDeep(obj: Record, keys: string[], value: unknown) { let node: Record = obj; for (const key of keys.slice(0, -1)) { @@ -65,42 +75,11 @@ export function isProfileDecorated( const localState = safeReadJson(localStatePath); const profile = localState?.profile; - const infoCache = - typeof profile === "object" && profile !== null && !Array.isArray(profile) - ? (profile as Record).info_cache - : null; - const info = - typeof infoCache === "object" && - infoCache !== null && - !Array.isArray(infoCache) && - typeof (infoCache as Record).Default === "object" && - (infoCache as Record).Default !== null && - !Array.isArray((infoCache as Record).Default) - ? ((infoCache as Record).Default as Record) - : null; + const info = readNestedRecord(readNestedRecord(profile, "info_cache"), "Default"); const prefs = safeReadJson(preferencesPath); - const browserTheme = (() => { - const browser = prefs?.browser; - const theme = - typeof browser === "object" && browser !== null && !Array.isArray(browser) - ? (browser as Record).theme - : null; - return typeof theme === "object" && theme !== null && !Array.isArray(theme) - ? (theme as Record) - : null; - })(); - - const autogeneratedTheme = (() => { - const autogenerated = prefs?.autogenerated; - const theme = - typeof autogenerated === "object" && autogenerated !== null && !Array.isArray(autogenerated) - ? (autogenerated as Record).theme - : null; - return typeof theme === "object" && theme !== null && !Array.isArray(theme) - ? (theme as Record) - : null; - })(); + const browserTheme = readNestedRecord(prefs?.browser, "theme"); + const autogeneratedTheme = readNestedRecord(prefs?.autogenerated, "theme"); const nameOk = typeof info?.name === "string" ? info.name === desiredName : true; diff --git a/extensions/browser/src/browser/paths.ts b/extensions/browser/src/browser/paths.ts index 2652161f1cc..135ac283c11 100644 --- a/extensions/browser/src/browser/paths.ts +++ b/extensions/browser/src/browser/paths.ts @@ -30,6 +30,12 @@ export const DEFAULT_DOWNLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "download export const DEFAULT_UPLOAD_DIR = path.join(DEFAULT_BROWSER_TMP_DIR, "uploads"); type InvalidPathResult = { ok: false; error: string }; +type ResolvePathsWithinRootParams = { + rootDir: string; + requestedPaths: string[]; + scopeLabel: string; +}; +type ResolvePathsWithinRootResult = { ok: true; paths: string[] } | InvalidPathResult; function invalidPath(scopeLabel: string): InvalidPathResult { return { @@ -146,11 +152,9 @@ export async function resolveWritablePathWithinRoot(params: { return lexical; } -export function resolvePathsWithinRoot(params: { - rootDir: string; - requestedPaths: string[]; - scopeLabel: string; -}): { ok: true; paths: string[] } | { ok: false; error: string } { +export function resolvePathsWithinRoot( + params: ResolvePathsWithinRootParams, +): ResolvePathsWithinRootResult { const resolvedPaths: string[] = []; for (const raw of params.requestedPaths) { const pathResult = resolvePathWithinRoot({ @@ -166,34 +170,22 @@ export function resolvePathsWithinRoot(params: { return { ok: true, paths: resolvedPaths }; } -export async function resolveExistingPathsWithinRoot(params: { - rootDir: string; - requestedPaths: string[]; - scopeLabel: string; -}): Promise<{ ok: true; paths: string[] } | { ok: false; error: string }> { - return await resolveCheckedPathsWithinRoot({ - ...params, - allowMissingFallback: true, - }); +export async function resolveExistingPathsWithinRoot( + params: ResolvePathsWithinRootParams, +): Promise { + return await resolveCheckedPathsWithinRoot(params, true); } -export async function resolveStrictExistingPathsWithinRoot(params: { - rootDir: string; - requestedPaths: string[]; - scopeLabel: string; -}): Promise<{ ok: true; paths: string[] } | { ok: false; error: string }> { - return await resolveCheckedPathsWithinRoot({ - ...params, - allowMissingFallback: false, - }); +export async function resolveStrictExistingPathsWithinRoot( + params: ResolvePathsWithinRootParams, +): Promise { + return await resolveCheckedPathsWithinRoot(params, false); } -async function resolveCheckedPathsWithinRoot(params: { - rootDir: string; - requestedPaths: string[]; - scopeLabel: string; - allowMissingFallback: boolean; -}): Promise<{ ok: true; paths: string[] } | { ok: false; error: string }> { +async function resolveCheckedPathsWithinRoot( + params: ResolvePathsWithinRootParams, + allowMissingFallback: boolean, +): Promise { const rootDir = path.resolve(params.rootDir); // Keep historical behavior for missing roots and rely on openFileWithinRoot for final checks. const rootRealPath = await resolveRealPathIfExists(rootDir); @@ -253,7 +245,7 @@ async function resolveCheckedPathsWithinRoot(params: { }); resolvedPaths.push(opened.realPath); } catch (err) { - if (params.allowMissingFallback && err instanceof SafeOpenError && err.code === "not-found") { + if (allowMissingFallback && err instanceof SafeOpenError && err.code === "not-found") { // Preserve historical behavior for paths that do not exist yet. resolvedPaths.push(pathResult.fallbackPath); continue;