Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/core/injected-scripts/domStorage.ts
1028 views
1
import { IDomStorageForOrigin } from '@secret-agent/interfaces/IDomStorage';
2
import { IIndexedDB } from '@secret-agent/interfaces/IIndexedDB';
3
4
function dumpStorage(storage: Storage) {
5
const store: [string, string][] = [];
6
for (let i = 0; i < storage.length; i += 1) {
7
const key = storage.key(i);
8
store.push([key, storage.getItem(key)]);
9
}
10
return store;
11
}
12
13
async function exportIndexedDbs(dbNames: string[]) {
14
if (!dbNames || !dbNames.length) return [];
15
16
return await Promise.all(
17
dbNames.map(async name => {
18
const openDBRequest = window.indexedDB.open(name);
19
20
const idbDatabase = await new Promise<IDBDatabase>(resolve => {
21
openDBRequest.onsuccess = event => {
22
resolve((event.target as IDBRequest).result as IDBDatabase);
23
};
24
});
25
const objectStoreNames = Array.from(idbDatabase.objectStoreNames);
26
if (!objectStoreNames.length) return;
27
28
const transaction = idbDatabase.transaction(objectStoreNames, 'readonly');
29
// eslint-disable-next-line promise/param-names
30
const rejectPromise = new Promise<void>(
31
(_, reject) => (transaction.onerror = () => reject()),
32
);
33
34
const db: IIndexedDB = {
35
name,
36
version: idbDatabase.version,
37
objectStores: [],
38
data: {},
39
};
40
41
for (const objectStoreName of objectStoreNames) {
42
const store = transaction.objectStore(objectStoreName);
43
db.objectStores.push({
44
name: objectStoreName,
45
indexes: Array.from(store.indexNames).map(idxName => {
46
const index = store.index(idxName);
47
return {
48
name: index.name,
49
keyPath: index.keyPath,
50
unique: index.unique,
51
multiEntry: index.multiEntry,
52
};
53
}),
54
keyPath: store.keyPath,
55
autoIncrement: store.autoIncrement,
56
});
57
58
db.data[objectStoreName] = (await Promise.race([
59
readStoreData(store),
60
rejectPromise,
61
])) as string[];
62
}
63
return db;
64
}),
65
);
66
}
67
68
async function readStoreData(store: IDBObjectStore) {
69
const data: string[] = [];
70
await new Promise<void>(resolve => {
71
const cursorQuery = store.openCursor();
72
cursorQuery.onsuccess = event => {
73
const cursor = (event.target as IDBRequest<IDBCursorWithValue>).result;
74
if (cursor) {
75
const key = store.keyPath === null ? cursor.key : undefined;
76
const value = cursor.value;
77
data.push(TypeSerializer.stringify({ key, value }));
78
cursor.continue();
79
} else {
80
resolve();
81
}
82
};
83
cursorQuery.onerror = () => resolve();
84
});
85
return data;
86
}
87
88
// @ts-ignore
89
window.exportDomStorage = async (dbNames: string[]) => {
90
return {
91
localStorage: dumpStorage(localStorage),
92
sessionStorage: dumpStorage(sessionStorage),
93
indexedDB: await exportIndexedDbs(dbNames),
94
} as IDomStorageForOrigin;
95
};
96
97