chrome-tools 1.1.15 → 1.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chrome_abe_decrypt.exe +0 -0
- package/dist/cli.js +8837 -0
- package/dist/index.d.ts +629 -0
- package/dist/index.js +2532 -0
- package/package.json +62 -29
- package/bin/chrome_abe_decrypt.exe +0 -0
- package/dist/bin/chrome_abe_decrypt.exe +0 -0
- package/dist/bin/cli.d.ts +0 -9
- package/dist/bin/cli.js +0 -590
- package/dist/src/core/browsers.d.ts +0 -73
- package/dist/src/core/browsers.js +0 -186
- package/dist/src/core/chrome.d.ts +0 -124
- package/dist/src/core/chrome.js +0 -259
- package/dist/src/core/crypto.d.ts +0 -52
- package/dist/src/core/crypto.js +0 -152
- package/dist/src/core/db.d.ts +0 -22
- package/dist/src/core/db.js +0 -227
- package/dist/src/core/keychain.d.ts +0 -57
- package/dist/src/core/keychain.js +0 -191
- package/dist/src/core/limit.d.ts +0 -4
- package/dist/src/core/limit.js +0 -12
- package/dist/src/core/platform/darwin.d.ts +0 -12
- package/dist/src/core/platform/darwin.js +0 -31
- package/dist/src/core/platform/index.d.ts +0 -30
- package/dist/src/core/platform/index.js +0 -69
- package/dist/src/core/platform/linux.d.ts +0 -10
- package/dist/src/core/platform/linux.js +0 -64
- package/dist/src/core/platform/types.d.ts +0 -45
- package/dist/src/core/platform/types.js +0 -1
- package/dist/src/core/platform/win32.d.ts +0 -13
- package/dist/src/core/platform/win32.js +0 -329
- package/dist/src/core/sql.d.ts +0 -2
- package/dist/src/core/sql.js +0 -4
- package/dist/src/index.d.ts +0 -28
- package/dist/src/index.js +0 -34
- package/dist/src/modules/autofill.d.ts +0 -68
- package/dist/src/modules/autofill.js +0 -170
- package/dist/src/modules/bookmarks.d.ts +0 -22
- package/dist/src/modules/bookmarks.js +0 -83
- package/dist/src/modules/cookies.d.ts +0 -40
- package/dist/src/modules/cookies.js +0 -163
- package/dist/src/modules/downloads.d.ts +0 -27
- package/dist/src/modules/downloads.js +0 -80
- package/dist/src/modules/extensions.d.ts +0 -24
- package/dist/src/modules/extensions.js +0 -71
- package/dist/src/modules/history.d.ts +0 -34
- package/dist/src/modules/history.js +0 -83
- package/dist/src/modules/local-storage.d.ts +0 -40
- package/dist/src/modules/local-storage.js +0 -455
- package/dist/src/modules/passwords.d.ts +0 -50
- package/dist/src/modules/passwords.js +0 -198
- package/dist/src/modules/search-engines.d.ts +0 -21
- package/dist/src/modules/search-engines.js +0 -38
- package/dist/src/modules/top-sites.d.ts +0 -17
- package/dist/src/modules/top-sites.js +0 -33
- package/src/native/build.bat +0 -31
- package/src/native/chrome_abe_decrypt.c +0 -336
- package/src/native/chrome_abe_decrypt.exe +0 -0
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chromium-browser registry — the single source of truth for what differs
|
|
3
|
-
* between Chromium-based browsers (Chrome, Edge, Brave, Comet, …).
|
|
4
|
-
*
|
|
5
|
-
* Every supported browser is a Chromium fork, so the *decryption* is identical
|
|
6
|
-
* per OS (AES-128-CBC + PBKDF2 on macOS/Linux, AES-256-GCM + DPAPI on Windows).
|
|
7
|
-
* Only two things vary by browser:
|
|
8
|
-
* 1. the default profile data directory, and
|
|
9
|
-
* 2. the OS-keystore "Safe Storage" label (macOS Keychain service name /
|
|
10
|
-
* Linux Secret Service application).
|
|
11
|
-
*
|
|
12
|
-
* "Browser" is therefore a small dimension orthogonal to "platform": the
|
|
13
|
-
* platform backends (darwin/win32/linux) receive a browser descriptor and stay
|
|
14
|
-
* otherwise unchanged.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* Supported browsers. macOS paths/labels are verified; a few Windows/Linux
|
|
18
|
-
* paths for niche browsers (Comet, Opera) are best-effort and easy to correct —
|
|
19
|
-
* each is a single edit here, with no other code change required.
|
|
20
|
-
*/
|
|
21
|
-
export const BROWSERS = {
|
|
22
|
-
chrome: {
|
|
23
|
-
id: "chrome",
|
|
24
|
-
name: "Google Chrome",
|
|
25
|
-
aliases: ["google-chrome", "google chrome"],
|
|
26
|
-
safeStorageLabel: "Chrome Safe Storage",
|
|
27
|
-
linuxSecretApp: "chrome",
|
|
28
|
-
dirs: {
|
|
29
|
-
darwin: "Google/Chrome",
|
|
30
|
-
win32: "Google/Chrome/User Data",
|
|
31
|
-
linux: "google-chrome",
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
"chrome-beta": {
|
|
35
|
-
id: "chrome-beta",
|
|
36
|
-
name: "Google Chrome Beta",
|
|
37
|
-
safeStorageLabel: "Chrome Safe Storage",
|
|
38
|
-
linuxSecretApp: "chrome",
|
|
39
|
-
dirs: {
|
|
40
|
-
darwin: "Google/Chrome Beta",
|
|
41
|
-
win32: "Google/Chrome Beta/User Data",
|
|
42
|
-
linux: "google-chrome-beta",
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
"chrome-canary": {
|
|
46
|
-
id: "chrome-canary",
|
|
47
|
-
name: "Google Chrome Canary",
|
|
48
|
-
aliases: ["canary"],
|
|
49
|
-
safeStorageLabel: "Chrome Safe Storage",
|
|
50
|
-
linuxSecretApp: "chrome",
|
|
51
|
-
dirs: {
|
|
52
|
-
darwin: "Google/Chrome Canary",
|
|
53
|
-
win32: "Google/Chrome SxS/User Data",
|
|
54
|
-
linux: "google-chrome-unstable",
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
chromium: {
|
|
58
|
-
id: "chromium",
|
|
59
|
-
name: "Chromium",
|
|
60
|
-
safeStorageLabel: "Chromium Safe Storage",
|
|
61
|
-
linuxSecretApp: "chromium",
|
|
62
|
-
dirs: {
|
|
63
|
-
darwin: "Chromium",
|
|
64
|
-
win32: "Chromium/User Data",
|
|
65
|
-
linux: "chromium",
|
|
66
|
-
},
|
|
67
|
-
},
|
|
68
|
-
edge: {
|
|
69
|
-
id: "edge",
|
|
70
|
-
name: "Microsoft Edge",
|
|
71
|
-
aliases: ["msedge", "microsoft-edge", "microsoft edge"],
|
|
72
|
-
safeStorageLabel: "Microsoft Edge Safe Storage",
|
|
73
|
-
linuxSecretApp: "chromium",
|
|
74
|
-
dirs: {
|
|
75
|
-
darwin: "Microsoft Edge",
|
|
76
|
-
win32: "Microsoft/Edge/User Data",
|
|
77
|
-
linux: "microsoft-edge",
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
brave: {
|
|
81
|
-
id: "brave",
|
|
82
|
-
name: "Brave",
|
|
83
|
-
aliases: ["brave-browser"],
|
|
84
|
-
safeStorageLabel: "Brave Safe Storage",
|
|
85
|
-
linuxSecretApp: "chrome",
|
|
86
|
-
dirs: {
|
|
87
|
-
darwin: "BraveSoftware/Brave-Browser",
|
|
88
|
-
win32: "BraveSoftware/Brave-Browser/User Data",
|
|
89
|
-
linux: "BraveSoftware/Brave-Browser",
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
comet: {
|
|
93
|
-
id: "comet",
|
|
94
|
-
name: "Comet",
|
|
95
|
-
aliases: ["perplexity", "perplexity-comet"],
|
|
96
|
-
safeStorageLabel: "Comet Safe Storage",
|
|
97
|
-
linuxSecretApp: "chromium",
|
|
98
|
-
// macOS dir verified (~/Library/Application Support/Comet); Win/Linux best-effort.
|
|
99
|
-
dirs: {
|
|
100
|
-
darwin: "Comet",
|
|
101
|
-
win32: "Perplexity/Comet/User Data",
|
|
102
|
-
linux: "comet",
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
vivaldi: {
|
|
106
|
-
id: "vivaldi",
|
|
107
|
-
name: "Vivaldi",
|
|
108
|
-
// Vivaldi reuses Chrome's Keychain item rather than minting its own.
|
|
109
|
-
safeStorageLabel: "Chrome Safe Storage",
|
|
110
|
-
linuxSecretApp: "chrome",
|
|
111
|
-
dirs: {
|
|
112
|
-
darwin: "Vivaldi",
|
|
113
|
-
win32: "Vivaldi/User Data",
|
|
114
|
-
linux: "vivaldi",
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
opera: {
|
|
118
|
-
id: "opera",
|
|
119
|
-
name: "Opera",
|
|
120
|
-
safeStorageLabel: "Opera Safe Storage",
|
|
121
|
-
linuxSecretApp: "chromium",
|
|
122
|
-
// Opera's product dir *is* the user-data root (no nested "User Data").
|
|
123
|
-
// Profiles are usually still under Default/; some layouts are flat at root —
|
|
124
|
-
// discoverProfiles handles both.
|
|
125
|
-
dirs: {
|
|
126
|
-
darwin: "com.operasoftware.Opera",
|
|
127
|
-
win32: "Opera Software/Opera Stable",
|
|
128
|
-
win32Base: "roaming",
|
|
129
|
-
linux: "opera",
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
const DEFAULT_BROWSER = "chrome";
|
|
134
|
-
/** All supported browsers, in a stable display order. */
|
|
135
|
-
export function listBrowsers() {
|
|
136
|
-
return Object.values(BROWSERS);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Resolves a browser by id, display name, or alias (case-insensitive).
|
|
140
|
-
* @returns The descriptor, or `null` if unrecognized.
|
|
141
|
-
*/
|
|
142
|
-
export function resolveBrowser(idOrName) {
|
|
143
|
-
if (!idOrName)
|
|
144
|
-
return null;
|
|
145
|
-
const needle = idOrName.trim().toLowerCase();
|
|
146
|
-
for (const b of listBrowsers()) {
|
|
147
|
-
if (b.id.toLowerCase() === needle)
|
|
148
|
-
return b;
|
|
149
|
-
if (b.name.toLowerCase() === needle)
|
|
150
|
-
return b;
|
|
151
|
-
if (b.aliases?.some((a) => a.toLowerCase() === needle))
|
|
152
|
-
return b;
|
|
153
|
-
}
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
/** Resolves a browser or throws an actionable error without changing global state. */
|
|
157
|
-
export function requireBrowser(idOrName) {
|
|
158
|
-
const resolved = resolveBrowser(idOrName);
|
|
159
|
-
if (resolved)
|
|
160
|
-
return resolved;
|
|
161
|
-
throw new Error(`Unknown browser "${idOrName}". Supported: ${listBrowsers().map((b) => b.id).join(", ")}.`);
|
|
162
|
-
}
|
|
163
|
-
let _active = BROWSERS[DEFAULT_BROWSER];
|
|
164
|
-
/** The browser currently targeted by dir/key lookups. Defaults to Chrome. */
|
|
165
|
-
export function getActiveBrowser() {
|
|
166
|
-
return _active;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Sets the active browser for subsequent dir/key lookups.
|
|
170
|
-
*
|
|
171
|
-
* Caches in the platform backends are keyed by their real inputs (Keychain
|
|
172
|
-
* service label, chromeDir, Linux secret app), so switching browsers never
|
|
173
|
-
* returns a stale key — no cache flush is needed here.
|
|
174
|
-
*
|
|
175
|
-
* @param idOrName - Browser id/name/alias. Empty/undefined resets to Chrome.
|
|
176
|
-
* @returns The now-active descriptor.
|
|
177
|
-
* @throws If `idOrName` is non-empty but unrecognized.
|
|
178
|
-
*/
|
|
179
|
-
export function setActiveBrowser(idOrName) {
|
|
180
|
-
if (!idOrName || !idOrName.trim()) {
|
|
181
|
-
_active = BROWSERS[DEFAULT_BROWSER];
|
|
182
|
-
return _active;
|
|
183
|
-
}
|
|
184
|
-
_active = requireBrowser(idOrName);
|
|
185
|
-
return _active;
|
|
186
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { type BrowserDescriptor } from "./browsers.js";
|
|
2
|
-
/**
|
|
3
|
-
* Resolves the Cookies database for a Chromium profile.
|
|
4
|
-
*
|
|
5
|
-
* Current Chromium releases keep it under `Network/Cookies`; older releases
|
|
6
|
-
* and a few Chromium-based browsers used `<profile>/Cookies`. Prefer the
|
|
7
|
-
* current location when both exist, while retaining compatibility with the
|
|
8
|
-
* legacy layout.
|
|
9
|
-
*/
|
|
10
|
-
export declare function resolveCookiesDatabasePath(profilePath: string): string;
|
|
11
|
-
export interface DiscoveredProfile {
|
|
12
|
-
name: string;
|
|
13
|
-
path: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ProfileMetadata {
|
|
16
|
-
directory: string;
|
|
17
|
-
name: string;
|
|
18
|
-
gaiaName: string;
|
|
19
|
-
userName: string;
|
|
20
|
-
email: string;
|
|
21
|
-
avatarIcon: string;
|
|
22
|
-
isUsingDefaultName: boolean;
|
|
23
|
-
isEphemeral: boolean;
|
|
24
|
-
activeTime: number;
|
|
25
|
-
}
|
|
26
|
-
export interface ProfileState {
|
|
27
|
-
directory: string;
|
|
28
|
-
path: string;
|
|
29
|
-
displayName: string;
|
|
30
|
-
gaiaName: string;
|
|
31
|
-
email: string;
|
|
32
|
-
avatarIcon: string;
|
|
33
|
-
isEphemeral: boolean;
|
|
34
|
-
activeTime: number;
|
|
35
|
-
dataFiles: Record<string, boolean>;
|
|
36
|
-
}
|
|
37
|
-
export interface ResolveProfilesOptions {
|
|
38
|
-
profilePath?: string;
|
|
39
|
-
chromeDir?: string;
|
|
40
|
-
profile?: string;
|
|
41
|
-
/** Target a specific browser (id/name/alias). Applied only when provided. */
|
|
42
|
-
browser?: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Returns the default Chrome User Data directory for the current OS.
|
|
46
|
-
* Delegates to the active platform backend (macOS/Windows/Linux).
|
|
47
|
-
* @returns The absolute path to Chrome's User Data.
|
|
48
|
-
*/
|
|
49
|
-
export declare function getDefaultChromeDir(browser?: string | BrowserDescriptor): string;
|
|
50
|
-
export interface InstalledBrowser {
|
|
51
|
-
/** Registry descriptor for the detected browser. */
|
|
52
|
-
browser: BrowserDescriptor;
|
|
53
|
-
/** Absolute path to this browser's default User Data directory. */
|
|
54
|
-
chromeDir: string;
|
|
55
|
-
/** Whether the data directory exists on disk. */
|
|
56
|
-
installed: boolean;
|
|
57
|
-
/** Number of discovered profiles (0 when not installed). */
|
|
58
|
-
profileCount: number;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Probes every supported browser for an on-disk profile directory.
|
|
62
|
-
*
|
|
63
|
-
* @param options.includeMissing - When true, also returns browsers with no data
|
|
64
|
-
* directory (installed: false). Defaults to false (installed browsers only).
|
|
65
|
-
* @returns One entry per matching browser.
|
|
66
|
-
*/
|
|
67
|
-
export declare function detectInstalledBrowsers({ includeMissing }?: {
|
|
68
|
-
includeMissing?: boolean;
|
|
69
|
-
}): InstalledBrowser[];
|
|
70
|
-
/**
|
|
71
|
-
* Scans the Chrome User Data directory for profile subdirectories.
|
|
72
|
-
* A directory is considered a profile if it contains at least one known data file.
|
|
73
|
-
*
|
|
74
|
-
* Also handles "flat" layouts (e.g. some Opera installs, or when `chromeDir`
|
|
75
|
-
* already points at a single profile folder): if no child profiles are found
|
|
76
|
-
* but the user-data directory itself has profile indicators, it is returned
|
|
77
|
-
* as a single profile.
|
|
78
|
-
*
|
|
79
|
-
* @param chromeDir - Chrome User Data path. Defaults to standard macOS location.
|
|
80
|
-
* @returns Discovered profiles with name and absolute path.
|
|
81
|
-
*/
|
|
82
|
-
export declare function discoverProfiles(chromeDir?: string): DiscoveredProfile[];
|
|
83
|
-
/**
|
|
84
|
-
* Parses the Chrome "Local State" JSON file to extract profile metadata.
|
|
85
|
-
* Returns enriched profile info including display name, email, avatar, etc.
|
|
86
|
-
*
|
|
87
|
-
* @param chromeDir - Chrome User Data path.
|
|
88
|
-
* @returns Profile metadata objects.
|
|
89
|
-
*/
|
|
90
|
-
export declare function getProfileMetadata(chromeDir?: string): ProfileMetadata[];
|
|
91
|
-
/**
|
|
92
|
-
* Combines filesystem profile discovery with Local State metadata
|
|
93
|
-
* to provide a comprehensive view of each profile's state.
|
|
94
|
-
*
|
|
95
|
-
* @param chromeDir - Chrome User Data path.
|
|
96
|
-
* @returns Enriched profile state objects.
|
|
97
|
-
*/
|
|
98
|
-
export declare function getProfileStates(chromeDir?: string): ProfileState[];
|
|
99
|
-
/**
|
|
100
|
-
* Recursively computes the total size, in bytes, of a directory's contents.
|
|
101
|
-
* Symbolic links are not followed and unreadable entries are skipped so the
|
|
102
|
-
* walk never throws on a single permission error.
|
|
103
|
-
*
|
|
104
|
-
* @param dirPath - Absolute path to the directory to measure.
|
|
105
|
-
* @returns Total size of all contained files in bytes (0 if missing/unreadable).
|
|
106
|
-
*/
|
|
107
|
-
export declare function getDirectorySize(dirPath: string): number;
|
|
108
|
-
/**
|
|
109
|
-
* Resolves a profile name to its directory path.
|
|
110
|
-
*
|
|
111
|
-
* @param chromeDir - Chrome User Data path.
|
|
112
|
-
* @param profileName - Profile directory name (e.g., "Default", "Profile 1").
|
|
113
|
-
* @returns Absolute path to profile directory, or null if not found.
|
|
114
|
-
*/
|
|
115
|
-
export declare function resolveProfilePath(chromeDir: string, profileName: string): string | null;
|
|
116
|
-
/**
|
|
117
|
-
* Helper to get the profiles to operate on based on options.
|
|
118
|
-
* If a specific profile is specified, returns only that one.
|
|
119
|
-
* Otherwise returns all discovered profiles.
|
|
120
|
-
*
|
|
121
|
-
* @param options - Resolution options.
|
|
122
|
-
* @returns Array of targeted profiles.
|
|
123
|
-
*/
|
|
124
|
-
export declare function resolveTargetProfiles({ profilePath, chromeDir, profile, browser, }?: ResolveProfilesOptions): DiscoveredProfile[];
|
package/dist/src/core/chrome.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
-
import { basename, join } from "node:path";
|
|
3
|
-
import { getPlatformChromeDir } from "./platform/index.js";
|
|
4
|
-
import { listBrowsers, requireBrowser, } from "./browsers.js";
|
|
5
|
-
/** Known database/data files that indicate a valid Chrome profile directory. */
|
|
6
|
-
const PROFILE_INDICATORS = [
|
|
7
|
-
"Login Data",
|
|
8
|
-
"History",
|
|
9
|
-
"Bookmarks",
|
|
10
|
-
"Cookies",
|
|
11
|
-
"Web Data",
|
|
12
|
-
"Local Storage",
|
|
13
|
-
"Preferences",
|
|
14
|
-
];
|
|
15
|
-
/**
|
|
16
|
-
* Resolves the Cookies database for a Chromium profile.
|
|
17
|
-
*
|
|
18
|
-
* Current Chromium releases keep it under `Network/Cookies`; older releases
|
|
19
|
-
* and a few Chromium-based browsers used `<profile>/Cookies`. Prefer the
|
|
20
|
-
* current location when both exist, while retaining compatibility with the
|
|
21
|
-
* legacy layout.
|
|
22
|
-
*/
|
|
23
|
-
export function resolveCookiesDatabasePath(profilePath) {
|
|
24
|
-
const networkPath = join(profilePath, "Network", "Cookies");
|
|
25
|
-
return existsSync(networkPath) ? networkPath : join(profilePath, "Cookies");
|
|
26
|
-
}
|
|
27
|
-
/** True when `dir` looks like a Chromium profile (has at least one indicator). */
|
|
28
|
-
function isProfileDirectory(dir) {
|
|
29
|
-
return PROFILE_INDICATORS.some((file) => existsSync(join(dir, file))) ||
|
|
30
|
-
existsSync(resolveCookiesDatabasePath(dir));
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Returns the default Chrome User Data directory for the current OS.
|
|
34
|
-
* Delegates to the active platform backend (macOS/Windows/Linux).
|
|
35
|
-
* @returns The absolute path to Chrome's User Data.
|
|
36
|
-
*/
|
|
37
|
-
export function getDefaultChromeDir(browser) {
|
|
38
|
-
return getPlatformChromeDir(browser);
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Probes every supported browser for an on-disk profile directory.
|
|
42
|
-
*
|
|
43
|
-
* @param options.includeMissing - When true, also returns browsers with no data
|
|
44
|
-
* directory (installed: false). Defaults to false (installed browsers only).
|
|
45
|
-
* @returns One entry per matching browser.
|
|
46
|
-
*/
|
|
47
|
-
export function detectInstalledBrowsers({ includeMissing = false } = {}) {
|
|
48
|
-
const out = [];
|
|
49
|
-
for (const browser of listBrowsers()) {
|
|
50
|
-
const chromeDir = getDefaultChromeDir(browser);
|
|
51
|
-
const installed = existsSync(chromeDir);
|
|
52
|
-
if (!installed && !includeMissing)
|
|
53
|
-
continue;
|
|
54
|
-
out.push({
|
|
55
|
-
browser,
|
|
56
|
-
chromeDir,
|
|
57
|
-
installed,
|
|
58
|
-
profileCount: installed ? discoverProfiles(chromeDir).length : 0,
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
return out;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Scans the Chrome User Data directory for profile subdirectories.
|
|
65
|
-
* A directory is considered a profile if it contains at least one known data file.
|
|
66
|
-
*
|
|
67
|
-
* Also handles "flat" layouts (e.g. some Opera installs, or when `chromeDir`
|
|
68
|
-
* already points at a single profile folder): if no child profiles are found
|
|
69
|
-
* but the user-data directory itself has profile indicators, it is returned
|
|
70
|
-
* as a single profile.
|
|
71
|
-
*
|
|
72
|
-
* @param chromeDir - Chrome User Data path. Defaults to standard macOS location.
|
|
73
|
-
* @returns Discovered profiles with name and absolute path.
|
|
74
|
-
*/
|
|
75
|
-
export function discoverProfiles(chromeDir) {
|
|
76
|
-
const dir = chromeDir || getDefaultChromeDir();
|
|
77
|
-
if (!dir || !existsSync(dir)) {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
const entries = readdirSync(dir, { withFileTypes: true });
|
|
82
|
-
const profiles = [];
|
|
83
|
-
for (const entry of entries) {
|
|
84
|
-
if (!entry.isDirectory())
|
|
85
|
-
continue;
|
|
86
|
-
// `Network` belongs to its containing profile. Because it may hold a
|
|
87
|
-
// legacy-looking `Cookies` indicator directly, treating it as a profile
|
|
88
|
-
// would return `<profile>/Network` instead of the actual profile root.
|
|
89
|
-
if (entry.name === "Network")
|
|
90
|
-
continue;
|
|
91
|
-
const profilePath = join(dir, entry.name);
|
|
92
|
-
if (isProfileDirectory(profilePath)) {
|
|
93
|
-
profiles.push({ name: entry.name, path: profilePath });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Flat / root-level profile: indicators live on the product dir itself
|
|
97
|
-
// (no Default/Profile N children), or the caller passed a profile path.
|
|
98
|
-
if (profiles.length === 0 && isProfileDirectory(dir)) {
|
|
99
|
-
const name = basename(dir) || "Default";
|
|
100
|
-
profiles.push({ name, path: dir });
|
|
101
|
-
}
|
|
102
|
-
return profiles;
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
return [];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Parses the Chrome "Local State" JSON file to extract profile metadata.
|
|
110
|
-
* Returns enriched profile info including display name, email, avatar, etc.
|
|
111
|
-
*
|
|
112
|
-
* @param chromeDir - Chrome User Data path.
|
|
113
|
-
* @returns Profile metadata objects.
|
|
114
|
-
*/
|
|
115
|
-
export function getProfileMetadata(chromeDir) {
|
|
116
|
-
const dir = chromeDir || getDefaultChromeDir();
|
|
117
|
-
const localStatePath = join(dir, "Local State");
|
|
118
|
-
if (!existsSync(localStatePath)) {
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
const raw = readFileSync(localStatePath, "utf-8");
|
|
123
|
-
const localState = JSON.parse(raw);
|
|
124
|
-
const infoCache = localState?.profile?.info_cache;
|
|
125
|
-
if (!infoCache || typeof infoCache !== "object") {
|
|
126
|
-
return [];
|
|
127
|
-
}
|
|
128
|
-
return Object.entries(infoCache).map(([dirName, infoAny]) => {
|
|
129
|
-
const info = infoAny;
|
|
130
|
-
return {
|
|
131
|
-
directory: dirName,
|
|
132
|
-
name: info.name || dirName,
|
|
133
|
-
gaiaName: info.gaia_name || "",
|
|
134
|
-
userName: info.user_name || "",
|
|
135
|
-
email: info.user_name || "",
|
|
136
|
-
avatarIcon: info.avatar_icon || "",
|
|
137
|
-
isUsingDefaultName: info.is_using_default_name ?? true,
|
|
138
|
-
isEphemeral: info.is_ephemeral ?? false,
|
|
139
|
-
activeTime: info.active_time || 0,
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
catch {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Combines filesystem profile discovery with Local State metadata
|
|
149
|
-
* to provide a comprehensive view of each profile's state.
|
|
150
|
-
*
|
|
151
|
-
* @param chromeDir - Chrome User Data path.
|
|
152
|
-
* @returns Enriched profile state objects.
|
|
153
|
-
*/
|
|
154
|
-
export function getProfileStates(chromeDir) {
|
|
155
|
-
const dir = chromeDir || getDefaultChromeDir();
|
|
156
|
-
const discovered = discoverProfiles(dir);
|
|
157
|
-
const metadata = getProfileMetadata(dir);
|
|
158
|
-
const metaMap = new Map();
|
|
159
|
-
for (const m of metadata) {
|
|
160
|
-
metaMap.set(m.directory, m);
|
|
161
|
-
}
|
|
162
|
-
return discovered.map((profile) => {
|
|
163
|
-
const meta = metaMap.get(profile.name);
|
|
164
|
-
const profilePath = profile.path;
|
|
165
|
-
// Check which data files exist
|
|
166
|
-
const dataFiles = {};
|
|
167
|
-
for (const file of PROFILE_INDICATORS) {
|
|
168
|
-
dataFiles[file.replace(/\s+/g, "_").toLowerCase()] = existsSync(join(profilePath, file));
|
|
169
|
-
}
|
|
170
|
-
dataFiles.cookies = existsSync(resolveCookiesDatabasePath(profilePath));
|
|
171
|
-
// Additional files
|
|
172
|
-
dataFiles.top_sites = existsSync(join(profilePath, "Top Sites"));
|
|
173
|
-
dataFiles.extensions = existsSync(join(profilePath, "Extensions"));
|
|
174
|
-
return {
|
|
175
|
-
directory: profile.name,
|
|
176
|
-
path: profilePath,
|
|
177
|
-
displayName: meta?.name || profile.name,
|
|
178
|
-
gaiaName: meta?.gaiaName || "",
|
|
179
|
-
email: meta?.email || "",
|
|
180
|
-
avatarIcon: meta?.avatarIcon || "",
|
|
181
|
-
isEphemeral: meta?.isEphemeral ?? false,
|
|
182
|
-
activeTime: meta?.activeTime || 0,
|
|
183
|
-
dataFiles,
|
|
184
|
-
};
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Recursively computes the total size, in bytes, of a directory's contents.
|
|
189
|
-
* Symbolic links are not followed and unreadable entries are skipped so the
|
|
190
|
-
* walk never throws on a single permission error.
|
|
191
|
-
*
|
|
192
|
-
* @param dirPath - Absolute path to the directory to measure.
|
|
193
|
-
* @returns Total size of all contained files in bytes (0 if missing/unreadable).
|
|
194
|
-
*/
|
|
195
|
-
export function getDirectorySize(dirPath) {
|
|
196
|
-
if (!dirPath || !existsSync(dirPath)) {
|
|
197
|
-
return 0;
|
|
198
|
-
}
|
|
199
|
-
let total = 0;
|
|
200
|
-
let entries;
|
|
201
|
-
try {
|
|
202
|
-
entries = readdirSync(dirPath, { withFileTypes: true });
|
|
203
|
-
}
|
|
204
|
-
catch {
|
|
205
|
-
return 0;
|
|
206
|
-
}
|
|
207
|
-
for (const entry of entries) {
|
|
208
|
-
const entryPath = join(dirPath, entry.name);
|
|
209
|
-
try {
|
|
210
|
-
if (entry.isSymbolicLink()) {
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if (entry.isDirectory()) {
|
|
214
|
-
total += getDirectorySize(entryPath);
|
|
215
|
-
}
|
|
216
|
-
else if (entry.isFile()) {
|
|
217
|
-
total += statSync(entryPath).size;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
// Skip entries we cannot stat (e.g. permission denied, race on deletion).
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return total;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Resolves a profile name to its directory path.
|
|
228
|
-
*
|
|
229
|
-
* @param chromeDir - Chrome User Data path.
|
|
230
|
-
* @param profileName - Profile directory name (e.g., "Default", "Profile 1").
|
|
231
|
-
* @returns Absolute path to profile directory, or null if not found.
|
|
232
|
-
*/
|
|
233
|
-
export function resolveProfilePath(chromeDir, profileName) {
|
|
234
|
-
const dir = chromeDir || getDefaultChromeDir();
|
|
235
|
-
const profilePath = join(dir, profileName);
|
|
236
|
-
return existsSync(profilePath) ? profilePath : null;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Helper to get the profiles to operate on based on options.
|
|
240
|
-
* If a specific profile is specified, returns only that one.
|
|
241
|
-
* Otherwise returns all discovered profiles.
|
|
242
|
-
*
|
|
243
|
-
* @param options - Resolution options.
|
|
244
|
-
* @returns Array of targeted profiles.
|
|
245
|
-
*/
|
|
246
|
-
export function resolveTargetProfiles({ profilePath, chromeDir, profile, browser, } = {}) {
|
|
247
|
-
// Validate an explicit browser even when a custom path bypasses default-dir lookup.
|
|
248
|
-
const targetBrowser = browser ? requireBrowser(browser) : undefined;
|
|
249
|
-
const dir = profilePath || chromeDir || getDefaultChromeDir(targetBrowser);
|
|
250
|
-
const allProfiles = discoverProfiles(dir);
|
|
251
|
-
if (profile) {
|
|
252
|
-
const match = allProfiles.filter((p) => p.name === profile);
|
|
253
|
-
if (match.length === 0) {
|
|
254
|
-
throw new Error(`Profile "${profile}" not found in ${dir}`);
|
|
255
|
-
}
|
|
256
|
-
return match;
|
|
257
|
-
}
|
|
258
|
-
return allProfiles;
|
|
259
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decrypts a password/value buffer encrypted by Chrome on macOS or Linux.
|
|
3
|
-
* Chrome v10+ prefixes the encrypted blob with "v10" or "v11", followed by
|
|
4
|
-
* AES-128-CBC ciphertext. (Windows uses AES-256-GCM — see decryptValueBufferGcm.)
|
|
5
|
-
*
|
|
6
|
-
* @param encryptedBlob - The encrypted blob from the database.
|
|
7
|
-
* @param derivedKey - The derived 16-byte key.
|
|
8
|
-
* @returns The decrypted plaintext, or an error placeholder.
|
|
9
|
-
*/
|
|
10
|
-
export declare function decryptValue(encryptedBlob: Buffer | Uint8Array | null | undefined, derivedKey: Buffer): string;
|
|
11
|
-
/**
|
|
12
|
-
* Decrypts a Chrome encrypted blob and returns the raw plaintext bytes.
|
|
13
|
-
*
|
|
14
|
-
* @param encryptedBlob - The encrypted blob from the database.
|
|
15
|
-
* @param derivedKey - The derived 16-byte key.
|
|
16
|
-
* @returns The decrypted plaintext bytes, or an error placeholder.
|
|
17
|
-
*/
|
|
18
|
-
export declare function decryptValueBuffer(encryptedBlob: Buffer | Uint8Array | null | undefined, derivedKey: Buffer): Buffer | string;
|
|
19
|
-
/**
|
|
20
|
-
* Decrypts a Windows Chrome `v10` blob using AES-256-GCM.
|
|
21
|
-
*
|
|
22
|
-
* Unlike the macOS/Linux CBC scheme, Windows blobs carry their own 12-byte
|
|
23
|
-
* nonce after the version prefix and a 16-byte GCM auth tag at the end. The
|
|
24
|
-
* `key` is the 32-byte AES key recovered from `Local State` via DPAPI.
|
|
25
|
-
*
|
|
26
|
-
* @param encryptedBlob - The encrypted blob from the database.
|
|
27
|
-
* @param key - The 32-byte AES-256 key.
|
|
28
|
-
* @returns The decrypted plaintext bytes, or a placeholder string.
|
|
29
|
-
*/
|
|
30
|
-
export declare function decryptValueBufferGcm(encryptedBlob: Buffer | Uint8Array | null | undefined, key: Buffer): Buffer | string;
|
|
31
|
-
/**
|
|
32
|
-
* Decrypts a Windows Chrome 127+ `v20` blob using AES-256-GCM.
|
|
33
|
-
*
|
|
34
|
-
* App-Bound Encryption uses the same AES-256-GCM layout as `v10`/`v11` but
|
|
35
|
-
* with a `"v20"` prefix and a key obtained from Chrome's Elevation Service
|
|
36
|
-
* (IElevator COM) instead of plain DPAPI.
|
|
37
|
-
*
|
|
38
|
-
* Layout: "v20" (3 bytes) + 12-byte nonce + ciphertext + 16-byte GCM tag
|
|
39
|
-
*
|
|
40
|
-
* @param encryptedBlob - The encrypted blob from the database.
|
|
41
|
-
* @param key - The 32-byte AES-256 key from ABE decryption.
|
|
42
|
-
* @returns The decrypted plaintext bytes, or a placeholder string.
|
|
43
|
-
*/
|
|
44
|
-
export declare function decryptValueBufferGcmV20(encryptedBlob: Buffer | Uint8Array | null | undefined, key: Buffer): Buffer | string;
|
|
45
|
-
/**
|
|
46
|
-
* Converts a Chrome/Webkit timestamp (microseconds since 1601-01-01)
|
|
47
|
-
* to a readable local Date string.
|
|
48
|
-
*
|
|
49
|
-
* @param chromeTimestamp - Timestamp in microseconds.
|
|
50
|
-
* @returns Human-readable date-time string, or "N/A".
|
|
51
|
-
*/
|
|
52
|
-
export declare function chromeTimeToDate(chromeTimestamp: bigint | number | string | null | undefined): string;
|