chrome-tools 1.1.9 → 1.1.10
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/src/core/db.js +8 -1
- package/dist/src/modules/passwords.js +16 -9
- package/package.json +1 -1
package/dist/src/core/db.js
CHANGED
|
@@ -47,7 +47,14 @@ export function queryDatabase(dbFilePath, sql, params = []) {
|
|
|
47
47
|
sourceDb = new Database(dbFilePath, {
|
|
48
48
|
readonly: true,
|
|
49
49
|
fileMustExist: true,
|
|
50
|
-
|
|
50
|
+
// No wait. A running Chrome holds these stores in `locking_mode =
|
|
51
|
+
// EXCLUSIVE` for as long as it is open, so a busy timeout here buys
|
|
52
|
+
// nothing that waiting longer would win — the lock is not transient, and
|
|
53
|
+
// the copy below is the answer to it either way. Five seconds *per store*
|
|
54
|
+
// was the whole cost of reading a saved login while the browser was up:
|
|
55
|
+
// two stores, ten seconds, spent to arrive at the fallback that then
|
|
56
|
+
// succeeded instantly.
|
|
57
|
+
timeout: 0,
|
|
51
58
|
});
|
|
52
59
|
sourceDb.prepare("VACUUM INTO ?").run(tmpDb);
|
|
53
60
|
}
|
|
@@ -160,7 +160,21 @@ export function getPasswords({ chromeDir, profilePath, profile, search, browser,
|
|
|
160
160
|
const rows = queryDatabase(dbPath, `SELECT origin_url, username_value, password_value, date_last_used
|
|
161
161
|
FROM logins ORDER BY origin_url`);
|
|
162
162
|
for (const row of rows) {
|
|
163
|
-
|
|
163
|
+
// Matched before anything is decrypted. Both columns the search
|
|
164
|
+
// looks at — the origin and the username — are stored in the clear,
|
|
165
|
+
// so a row that cannot match never needs its password read at all.
|
|
166
|
+
//
|
|
167
|
+
// Decrypting first cost one platform decryption per stored login on
|
|
168
|
+
// the way to finding one: a store with a few hundred entries spent
|
|
169
|
+
// upwards of ten seconds answering "what is the password for this
|
|
170
|
+
// one site", and every one of those decryptions was thrown away by
|
|
171
|
+
// the filter immediately below.
|
|
172
|
+
if (term &&
|
|
173
|
+
!(row.origin_url && row.origin_url.toLowerCase().includes(term)) &&
|
|
174
|
+
!(row.username_value && row.username_value.toLowerCase().includes(term))) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
results.push({
|
|
164
178
|
profile: p.name,
|
|
165
179
|
source: store.source,
|
|
166
180
|
url: row.origin_url,
|
|
@@ -169,14 +183,7 @@ export function getPasswords({ chromeDir, profilePath, profile, search, browser,
|
|
|
169
183
|
? decryptValue(row.password_value, derivedKey ??= deriveEncryptionKey(root, browser))
|
|
170
184
|
: "",
|
|
171
185
|
lastUsed: chromeTimeToDate(row.date_last_used || 0),
|
|
172
|
-
};
|
|
173
|
-
if (term) {
|
|
174
|
-
if (!(entry.url && entry.url.toLowerCase().includes(term)) &&
|
|
175
|
-
!(entry.username && entry.username.toLowerCase().includes(term))) {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
results.push(entry);
|
|
186
|
+
});
|
|
180
187
|
}
|
|
181
188
|
}
|
|
182
189
|
catch {
|