chrome-tools 1.1.11 → 1.1.12
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.
|
@@ -1,4 +1,13 @@
|
|
|
1
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;
|
|
2
11
|
export interface DiscoveredProfile {
|
|
3
12
|
name: string;
|
|
4
13
|
path: string;
|
package/dist/src/core/chrome.js
CHANGED
|
@@ -12,9 +12,22 @@ const PROFILE_INDICATORS = [
|
|
|
12
12
|
"Local Storage",
|
|
13
13
|
"Preferences",
|
|
14
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
|
+
}
|
|
15
27
|
/** True when `dir` looks like a Chromium profile (has at least one indicator). */
|
|
16
28
|
function isProfileDirectory(dir) {
|
|
17
|
-
return PROFILE_INDICATORS.some((file) => existsSync(join(dir, file)))
|
|
29
|
+
return PROFILE_INDICATORS.some((file) => existsSync(join(dir, file))) ||
|
|
30
|
+
existsSync(resolveCookiesDatabasePath(dir));
|
|
18
31
|
}
|
|
19
32
|
/**
|
|
20
33
|
* Returns the default Chrome User Data directory for the current OS.
|
|
@@ -70,6 +83,11 @@ export function discoverProfiles(chromeDir) {
|
|
|
70
83
|
for (const entry of entries) {
|
|
71
84
|
if (!entry.isDirectory())
|
|
72
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;
|
|
73
91
|
const profilePath = join(dir, entry.name);
|
|
74
92
|
if (isProfileDirectory(profilePath)) {
|
|
75
93
|
profiles.push({ name: entry.name, path: profilePath });
|
|
@@ -149,6 +167,7 @@ export function getProfileStates(chromeDir) {
|
|
|
149
167
|
for (const file of PROFILE_INDICATORS) {
|
|
150
168
|
dataFiles[file.replace(/\s+/g, "_").toLowerCase()] = existsSync(join(profilePath, file));
|
|
151
169
|
}
|
|
170
|
+
dataFiles.cookies = existsSync(resolveCookiesDatabasePath(profilePath));
|
|
152
171
|
// Additional files
|
|
153
172
|
dataFiles.top_sites = existsSync(join(profilePath, "Top Sites"));
|
|
154
173
|
dataFiles.extensions = existsSync(join(profilePath, "Extensions"));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { resolveTargetProfiles } from "../core/chrome.js";
|
|
3
|
+
import { resolveCookiesDatabasePath, resolveTargetProfiles, } from "../core/chrome.js";
|
|
4
4
|
import { deriveEncryptionKey, decryptValueBuffer } from "../core/platform/index.js";
|
|
5
5
|
import { chromeTimeToDate } from "../core/crypto.js";
|
|
6
6
|
import { queryDatabase } from "../core/db.js";
|
|
@@ -88,8 +88,11 @@ export function getCookies({ chromeDir, profilePath, profile, browser, domain, u
|
|
|
88
88
|
const results = [];
|
|
89
89
|
const parsedUrl = parseURL(url);
|
|
90
90
|
const rowLimit = normalizeLimit(limit);
|
|
91
|
+
let firstReadError;
|
|
91
92
|
for (const p of profiles) {
|
|
92
|
-
const dbPath =
|
|
93
|
+
const dbPath = resolveCookiesDatabasePath(p.path);
|
|
94
|
+
if (!existsSync(dbPath))
|
|
95
|
+
continue;
|
|
93
96
|
try {
|
|
94
97
|
let sql = `SELECT host_key, name, value, encrypted_value, path,
|
|
95
98
|
expires_utc, is_secure, is_httponly, samesite,
|
|
@@ -143,10 +146,13 @@ export function getCookies({ chromeDir, profilePath, profile, browser, domain, u
|
|
|
143
146
|
});
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
|
-
catch {
|
|
147
|
-
|
|
149
|
+
catch (error) {
|
|
150
|
+
firstReadError ??= new Error(`Could not read cookies for profile "${p.name}" at ${dbPath}: ` +
|
|
151
|
+
(error instanceof Error ? error.message : String(error)));
|
|
148
152
|
}
|
|
149
153
|
}
|
|
154
|
+
if (results.length === 0 && firstReadError)
|
|
155
|
+
throw firstReadError;
|
|
150
156
|
return limitResults(results, limit);
|
|
151
157
|
}
|
|
152
158
|
export const _test = {
|