react-native-nitro-storage 0.7.0 → 0.8.0
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/CHANGELOG.md +32 -0
- package/README.md +20 -9
- package/SECURITY.md +2 -2
- package/docs/api-reference.md +11 -1
- package/docs/batch-transactions-migrations.md +8 -2
- package/docs/benchmarks.md +19 -15
- package/docs/web-backends.md +18 -1
- package/ios/IOSStorageAdapterCpp.mm +162 -17
- package/lib/commonjs/capabilities.js +26 -0
- package/lib/commonjs/capabilities.js.map +1 -0
- package/lib/commonjs/core/durability.js +137 -0
- package/lib/commonjs/core/durability.js.map +1 -0
- package/lib/commonjs/core/metrics.js +91 -0
- package/lib/commonjs/core/metrics.js.map +1 -0
- package/lib/commonjs/index.js +47 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +118 -66
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/indexeddb-backend.js +73 -23
- package/lib/commonjs/indexeddb-backend.js.map +1 -1
- package/lib/commonjs/internal.js +27 -4
- package/lib/commonjs/internal.js.map +1 -1
- package/lib/commonjs/shared.js +2 -2
- package/lib/commonjs/shared.js.map +1 -1
- package/lib/commonjs/storage-core.js +217 -233
- package/lib/commonjs/storage-core.js.map +1 -1
- package/lib/commonjs/storage-events.js.map +1 -1
- package/lib/commonjs/storage-platform.js +6 -0
- package/lib/commonjs/storage-platform.js.map +1 -0
- package/lib/commonjs/storage-runtime.js +3 -21
- package/lib/commonjs/storage-runtime.js.map +1 -1
- package/lib/commonjs/testing.js +19 -4
- package/lib/commonjs/testing.js.map +1 -1
- package/lib/commonjs/web-backend-contract.js +27 -0
- package/lib/commonjs/web-backend-contract.js.map +1 -0
- package/lib/module/capabilities.js +21 -0
- package/lib/module/capabilities.js.map +1 -0
- package/lib/module/core/durability.js +133 -0
- package/lib/module/core/durability.js.map +1 -0
- package/lib/module/core/metrics.js +87 -0
- package/lib/module/core/metrics.js.map +1 -0
- package/lib/module/index.js +48 -23
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +103 -64
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/indexeddb-backend.js +73 -23
- package/lib/module/indexeddb-backend.js.map +1 -1
- package/lib/module/internal.js +24 -3
- package/lib/module/internal.js.map +1 -1
- package/lib/module/shared.js +2 -2
- package/lib/module/shared.js.map +1 -1
- package/lib/module/storage-core.js +218 -234
- package/lib/module/storage-core.js.map +1 -1
- package/lib/module/storage-events.js.map +1 -1
- package/lib/module/storage-platform.js +4 -0
- package/lib/module/storage-platform.js.map +1 -0
- package/lib/module/storage-runtime.js +3 -21
- package/lib/module/storage-runtime.js.map +1 -1
- package/lib/module/testing.js +5 -3
- package/lib/module/testing.js.map +1 -1
- package/lib/module/web-backend-contract.js +22 -0
- package/lib/module/web-backend-contract.js.map +1 -0
- package/lib/typescript/capabilities.d.ts +11 -0
- package/lib/typescript/capabilities.d.ts.map +1 -0
- package/lib/typescript/core/durability.d.ts +27 -0
- package/lib/typescript/core/durability.d.ts.map +1 -0
- package/lib/typescript/core/metrics.d.ts +12 -0
- package/lib/typescript/core/metrics.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +8 -4
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/indexeddb-backend.d.ts.map +1 -1
- package/lib/typescript/internal.d.ts +3 -0
- package/lib/typescript/internal.d.ts.map +1 -1
- package/lib/typescript/shared.d.ts +2 -1
- package/lib/typescript/shared.d.ts.map +1 -1
- package/lib/typescript/storage-core.d.ts +3 -3
- package/lib/typescript/storage-core.d.ts.map +1 -1
- package/lib/typescript/storage-events.d.ts +2 -2
- package/lib/typescript/storage-events.d.ts.map +1 -1
- package/lib/typescript/storage-platform.d.ts +12 -0
- package/lib/typescript/storage-platform.d.ts.map +1 -0
- package/lib/typescript/storage-runtime.d.ts.map +1 -1
- package/lib/typescript/testing.d.ts +5 -1
- package/lib/typescript/testing.d.ts.map +1 -1
- package/lib/typescript/web-backend-contract.d.ts +10 -0
- package/lib/typescript/web-backend-contract.d.ts.map +1 -0
- package/lib/typescript/web-storage-backend.d.ts +1 -1
- package/lib/typescript/web-storage-backend.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/capabilities.ts +36 -0
- package/src/core/durability.ts +170 -0
- package/src/core/metrics.ts +133 -0
- package/src/index.ts +66 -40
- package/src/index.web.ts +158 -86
- package/src/indexeddb-backend.ts +91 -20
- package/src/internal.ts +50 -4
- package/src/shared.ts +7 -6
- package/src/storage-core.ts +317 -285
- package/src/storage-events.ts +2 -1
- package/src/storage-platform.ts +16 -0
- package/src/storage-runtime.ts +13 -47
- package/src/testing.ts +14 -7
- package/src/web-backend-contract.ts +34 -0
- package/src/web-storage-backend.ts +1 -1
package/src/index.web.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveWebWriteBuffering } from "./capabilities";
|
|
2
|
+
import { unescapeCollidingRawValue } from "./internal";
|
|
1
3
|
import {
|
|
2
4
|
assertAccessControlLevel,
|
|
3
5
|
assertBiometricLevel,
|
|
@@ -5,7 +7,17 @@ import {
|
|
|
5
7
|
notifyKeyListeners,
|
|
6
8
|
type NonMemoryScope,
|
|
7
9
|
} from "./shared";
|
|
8
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
createStorageCore,
|
|
12
|
+
type StorageCoreAdapter,
|
|
13
|
+
type StorageCoreInternals,
|
|
14
|
+
} from "./storage-core";
|
|
15
|
+
import type {
|
|
16
|
+
SecurityCapabilities,
|
|
17
|
+
StorageCapabilities,
|
|
18
|
+
} from "./storage-runtime";
|
|
19
|
+
import type { AccessControl } from "./Storage.types";
|
|
20
|
+
import { StorageScope, BiometricLevel } from "./Storage.types";
|
|
9
21
|
import {
|
|
10
22
|
createLocalStorageWebBackend,
|
|
11
23
|
type WebDiskStorageBackend,
|
|
@@ -13,15 +25,6 @@ import {
|
|
|
13
25
|
type WebStorageBackend,
|
|
14
26
|
type WebStorageChangeEvent,
|
|
15
27
|
} from "./web-storage-backend";
|
|
16
|
-
import type {
|
|
17
|
-
SecurityCapabilities,
|
|
18
|
-
StorageCapabilities,
|
|
19
|
-
} from "./storage-runtime";
|
|
20
|
-
import {
|
|
21
|
-
createStorageCore,
|
|
22
|
-
type StorageCoreAdapter,
|
|
23
|
-
type StorageCoreInternals,
|
|
24
|
-
} from "./storage-core";
|
|
25
28
|
export type {
|
|
26
29
|
ExpirationConfig,
|
|
27
30
|
Migration,
|
|
@@ -65,6 +68,11 @@ export type {
|
|
|
65
68
|
WebStorageChangeEvent,
|
|
66
69
|
WebStorageScope,
|
|
67
70
|
} from "./web-storage-backend";
|
|
71
|
+
export {
|
|
72
|
+
describeWebBackendCapabilities,
|
|
73
|
+
isIndexedDBWebBackend,
|
|
74
|
+
type WebBackendCapabilities,
|
|
75
|
+
} from "./web-backend-contract";
|
|
68
76
|
export type {
|
|
69
77
|
SetItemConfig,
|
|
70
78
|
SetStorageItem,
|
|
@@ -75,8 +83,9 @@ export type {
|
|
|
75
83
|
StorageKeyRef,
|
|
76
84
|
TransactionContext,
|
|
77
85
|
} from "./storage-core";
|
|
86
|
+
export type { PlatformScope, PlatformStorage } from "./storage-platform";
|
|
78
87
|
|
|
79
|
-
export
|
|
88
|
+
export type Storage = {
|
|
80
89
|
name: string;
|
|
81
90
|
equals: (other: unknown) => boolean;
|
|
82
91
|
dispose: () => void;
|
|
@@ -105,19 +114,26 @@ export interface Storage {
|
|
|
105
114
|
deleteSecureBiometric(key: string): void;
|
|
106
115
|
hasSecureBiometric(key: string): boolean;
|
|
107
116
|
clearSecureBiometric(): void;
|
|
108
|
-
}
|
|
117
|
+
};
|
|
109
118
|
|
|
110
|
-
const webScopeKeyIndex
|
|
111
|
-
[StorageScope.Disk
|
|
112
|
-
[StorageScope.Secure
|
|
113
|
-
|
|
119
|
+
const webScopeKeyIndex: Record<NonMemoryScope, Set<string>> = {
|
|
120
|
+
[StorageScope.Disk]: new Set(),
|
|
121
|
+
[StorageScope.Secure]: new Set(),
|
|
122
|
+
};
|
|
114
123
|
const hydratedWebScopeKeyIndex = new Set<NonMemoryScope>();
|
|
115
124
|
const SECURE_WEB_PREFIX = "__secure_";
|
|
116
125
|
const BIOMETRIC_WEB_PREFIX = "__bio_";
|
|
117
126
|
let hasWarnedAboutWebBiometricFallback = false;
|
|
118
127
|
let hasWindowStorageEventSubscription = false;
|
|
119
128
|
|
|
120
|
-
let internals
|
|
129
|
+
let internals: StorageCoreInternals;
|
|
130
|
+
|
|
131
|
+
function getInternals(): StorageCoreInternals {
|
|
132
|
+
if (internals === undefined) {
|
|
133
|
+
throw new Error("NitroStorage(web): storage core is not initialized.");
|
|
134
|
+
}
|
|
135
|
+
return internals;
|
|
136
|
+
}
|
|
121
137
|
|
|
122
138
|
function createDefaultDiskBackend(): WebDiskStorageBackend {
|
|
123
139
|
return createLocalStorageWebBackend({
|
|
@@ -141,6 +157,7 @@ let webDiskStorageBackend: WebDiskStorageBackend | undefined =
|
|
|
141
157
|
let webSecureStorageBackend: WebSecureStorageBackend | undefined =
|
|
142
158
|
createDefaultSecureBackend();
|
|
143
159
|
const externalSyncUnsubscribers = new Map<NonMemoryScope, () => void>();
|
|
160
|
+
const retiredWebBackends = new Map<WebStorageBackend, NonMemoryScope>();
|
|
144
161
|
|
|
145
162
|
function getBackendName(
|
|
146
163
|
scope: NonMemoryScope,
|
|
@@ -216,7 +233,7 @@ function fromBiometricStorageKey(key: string): string {
|
|
|
216
233
|
}
|
|
217
234
|
|
|
218
235
|
function getWebScopeKeyIndex(scope: NonMemoryScope): Set<string> {
|
|
219
|
-
return webScopeKeyIndex
|
|
236
|
+
return webScopeKeyIndex[scope];
|
|
220
237
|
}
|
|
221
238
|
|
|
222
239
|
function hydrateWebScopeKeyIndex(scope: NonMemoryScope): void {
|
|
@@ -256,34 +273,34 @@ function applyExternalChangeEvent(
|
|
|
256
273
|
newValue: string | null,
|
|
257
274
|
): void {
|
|
258
275
|
if (key === null) {
|
|
259
|
-
|
|
276
|
+
getInternals().clearScopeRawCache(scope);
|
|
260
277
|
ensureWebScopeKeyIndex(scope).clear();
|
|
261
|
-
notifyAllListeners(
|
|
278
|
+
notifyAllListeners(getInternals().getScopedListeners(scope));
|
|
262
279
|
return;
|
|
263
280
|
}
|
|
264
281
|
|
|
265
282
|
if (scope === StorageScope.Secure && key.startsWith(SECURE_WEB_PREFIX)) {
|
|
266
283
|
const plainKey = fromSecureStorageKey(key);
|
|
267
|
-
const oldValue =
|
|
284
|
+
const oldValue = getInternals().readCachedRawValue(
|
|
268
285
|
StorageScope.Secure,
|
|
269
286
|
plainKey,
|
|
270
287
|
);
|
|
271
288
|
if (newValue === null) {
|
|
272
289
|
ensureWebScopeKeyIndex(StorageScope.Secure).delete(plainKey);
|
|
273
|
-
|
|
290
|
+
getInternals().cacheRawValue(StorageScope.Secure, plainKey, undefined);
|
|
274
291
|
} else {
|
|
275
292
|
ensureWebScopeKeyIndex(StorageScope.Secure).add(plainKey);
|
|
276
|
-
|
|
293
|
+
getInternals().cacheRawValue(StorageScope.Secure, plainKey, newValue);
|
|
277
294
|
}
|
|
278
295
|
notifyKeyListeners(
|
|
279
|
-
|
|
296
|
+
getInternals().getScopedListeners(StorageScope.Secure),
|
|
280
297
|
plainKey,
|
|
281
298
|
);
|
|
282
|
-
|
|
299
|
+
getInternals().emitKeyChange(
|
|
283
300
|
StorageScope.Secure,
|
|
284
301
|
plainKey,
|
|
285
|
-
oldValue,
|
|
286
|
-
newValue
|
|
302
|
+
oldValue === undefined ? undefined : unescapeCollidingRawValue(oldValue),
|
|
303
|
+
newValue === null ? undefined : unescapeCollidingRawValue(newValue),
|
|
287
304
|
"external",
|
|
288
305
|
"external",
|
|
289
306
|
);
|
|
@@ -292,7 +309,7 @@ function applyExternalChangeEvent(
|
|
|
292
309
|
|
|
293
310
|
if (scope === StorageScope.Secure && key.startsWith(BIOMETRIC_WEB_PREFIX)) {
|
|
294
311
|
const plainKey = fromBiometricStorageKey(key);
|
|
295
|
-
const oldValue =
|
|
312
|
+
const oldValue = getInternals().readCachedRawValue(
|
|
296
313
|
StorageScope.Secure,
|
|
297
314
|
plainKey,
|
|
298
315
|
);
|
|
@@ -306,40 +323,40 @@ function applyExternalChangeEvent(
|
|
|
306
323
|
) {
|
|
307
324
|
ensureWebScopeKeyIndex(StorageScope.Secure).delete(plainKey);
|
|
308
325
|
}
|
|
309
|
-
|
|
326
|
+
getInternals().cacheRawValue(StorageScope.Secure, plainKey, undefined);
|
|
310
327
|
} else {
|
|
311
328
|
ensureWebScopeKeyIndex(StorageScope.Secure).add(plainKey);
|
|
312
|
-
|
|
329
|
+
getInternals().cacheRawValue(StorageScope.Secure, plainKey, newValue);
|
|
313
330
|
}
|
|
314
331
|
notifyKeyListeners(
|
|
315
|
-
|
|
332
|
+
getInternals().getScopedListeners(StorageScope.Secure),
|
|
316
333
|
plainKey,
|
|
317
334
|
);
|
|
318
|
-
|
|
335
|
+
getInternals().emitKeyChange(
|
|
319
336
|
StorageScope.Secure,
|
|
320
337
|
plainKey,
|
|
321
|
-
oldValue,
|
|
322
|
-
newValue
|
|
338
|
+
oldValue === undefined ? undefined : unescapeCollidingRawValue(oldValue),
|
|
339
|
+
newValue === null ? undefined : unescapeCollidingRawValue(newValue),
|
|
323
340
|
"external",
|
|
324
341
|
"external",
|
|
325
342
|
);
|
|
326
343
|
return;
|
|
327
344
|
}
|
|
328
345
|
|
|
329
|
-
const oldValue =
|
|
346
|
+
const oldValue = getInternals().readCachedRawValue(scope, key);
|
|
330
347
|
if (newValue === null) {
|
|
331
348
|
ensureWebScopeKeyIndex(scope).delete(key);
|
|
332
|
-
|
|
349
|
+
getInternals().cacheRawValue(scope, key, undefined);
|
|
333
350
|
} else {
|
|
334
351
|
ensureWebScopeKeyIndex(scope).add(key);
|
|
335
|
-
|
|
352
|
+
getInternals().cacheRawValue(scope, key, newValue);
|
|
336
353
|
}
|
|
337
|
-
notifyKeyListeners(
|
|
338
|
-
|
|
354
|
+
notifyKeyListeners(getInternals().getScopedListeners(scope), key);
|
|
355
|
+
getInternals().emitKeyChange(
|
|
339
356
|
scope,
|
|
340
357
|
key,
|
|
341
|
-
oldValue,
|
|
342
|
-
newValue
|
|
358
|
+
oldValue === undefined ? undefined : unescapeCollidingRawValue(oldValue),
|
|
359
|
+
newValue === null ? undefined : unescapeCollidingRawValue(newValue),
|
|
343
360
|
"external",
|
|
344
361
|
"external",
|
|
345
362
|
);
|
|
@@ -400,6 +417,21 @@ function closeWebBackend(
|
|
|
400
417
|
}
|
|
401
418
|
}
|
|
402
419
|
|
|
420
|
+
function retireWebBackend(
|
|
421
|
+
scope: NonMemoryScope,
|
|
422
|
+
previousBackend: WebStorageBackend | undefined,
|
|
423
|
+
nextBackend: WebStorageBackend | undefined,
|
|
424
|
+
): void {
|
|
425
|
+
if (!previousBackend || previousBackend === nextBackend) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
if (previousBackend.flush) {
|
|
429
|
+
retiredWebBackends.set(previousBackend, scope);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
closeWebBackend(scope, previousBackend);
|
|
433
|
+
}
|
|
434
|
+
|
|
403
435
|
function ensureExternalSyncSubscriptions(): void {
|
|
404
436
|
if (
|
|
405
437
|
!hasWindowStorageEventSubscription &&
|
|
@@ -428,7 +460,7 @@ const WebStorage: Storage = {
|
|
|
428
460
|
backend.setItem(storageKey, value);
|
|
429
461
|
});
|
|
430
462
|
ensureWebScopeKeyIndex(scope).add(key);
|
|
431
|
-
notifyKeyListeners(
|
|
463
|
+
notifyKeyListeners(getInternals().getScopedListeners(scope), key);
|
|
432
464
|
},
|
|
433
465
|
get: (key: string, scope: number) => {
|
|
434
466
|
if (scope !== StorageScope.Disk && scope !== StorageScope.Secure) {
|
|
@@ -463,7 +495,7 @@ const WebStorage: Storage = {
|
|
|
463
495
|
});
|
|
464
496
|
}
|
|
465
497
|
ensureWebScopeKeyIndex(scope).delete(key);
|
|
466
|
-
notifyKeyListeners(
|
|
498
|
+
notifyKeyListeners(getInternals().getScopedListeners(scope), key);
|
|
467
499
|
},
|
|
468
500
|
clear: (scope: number) => {
|
|
469
501
|
if (scope !== StorageScope.Disk && scope !== StorageScope.Secure) {
|
|
@@ -473,7 +505,7 @@ const WebStorage: Storage = {
|
|
|
473
505
|
backend.clear();
|
|
474
506
|
});
|
|
475
507
|
ensureWebScopeKeyIndex(scope).clear();
|
|
476
|
-
notifyAllListeners(
|
|
508
|
+
notifyAllListeners(getInternals().getScopedListeners(scope));
|
|
477
509
|
},
|
|
478
510
|
setBatch: (keys: string[], values: string[], scope: number) => {
|
|
479
511
|
if (scope !== StorageScope.Disk && scope !== StorageScope.Secure) {
|
|
@@ -513,8 +545,10 @@ const WebStorage: Storage = {
|
|
|
513
545
|
: storageKey,
|
|
514
546
|
),
|
|
515
547
|
);
|
|
516
|
-
const listeners =
|
|
517
|
-
keys.forEach((key) =>
|
|
548
|
+
const listeners = getInternals().getScopedListeners(scope);
|
|
549
|
+
keys.forEach((key) => {
|
|
550
|
+
notifyKeyListeners(listeners, key);
|
|
551
|
+
});
|
|
518
552
|
},
|
|
519
553
|
getBatch: (keys: string[], scope: number) => {
|
|
520
554
|
if (scope !== StorageScope.Disk && scope !== StorageScope.Secure) {
|
|
@@ -564,8 +598,10 @@ const WebStorage: Storage = {
|
|
|
564
598
|
|
|
565
599
|
const keyIndex = ensureWebScopeKeyIndex(scope);
|
|
566
600
|
keys.forEach((key) => keyIndex.delete(key));
|
|
567
|
-
const listeners =
|
|
568
|
-
keys.forEach((key) =>
|
|
601
|
+
const listeners = getInternals().getScopedListeners(scope);
|
|
602
|
+
keys.forEach((key) => {
|
|
603
|
+
notifyKeyListeners(listeners, key);
|
|
604
|
+
});
|
|
569
605
|
},
|
|
570
606
|
removeByPrefix: (prefix: string, scope: number) => {
|
|
571
607
|
if (scope !== StorageScope.Disk && scope !== StorageScope.Secure) {
|
|
@@ -633,7 +669,7 @@ const WebStorage: Storage = {
|
|
|
633
669
|
});
|
|
634
670
|
ensureWebScopeKeyIndex(StorageScope.Secure).add(key);
|
|
635
671
|
notifyKeyListeners(
|
|
636
|
-
|
|
672
|
+
getInternals().getScopedListeners(StorageScope.Secure),
|
|
637
673
|
key,
|
|
638
674
|
);
|
|
639
675
|
return;
|
|
@@ -651,10 +687,16 @@ const WebStorage: Storage = {
|
|
|
651
687
|
withWebBackendOperation(
|
|
652
688
|
StorageScope.Secure,
|
|
653
689
|
"setSecureBiometric",
|
|
654
|
-
(backend) =>
|
|
690
|
+
(backend) => {
|
|
691
|
+
backend.setItem(toBiometricStorageKey(key), value);
|
|
692
|
+
backend.removeItem(toSecureStorageKey(key));
|
|
693
|
+
},
|
|
655
694
|
);
|
|
656
695
|
ensureWebScopeKeyIndex(StorageScope.Secure).add(key);
|
|
657
|
-
notifyKeyListeners(
|
|
696
|
+
notifyKeyListeners(
|
|
697
|
+
getInternals().getScopedListeners(StorageScope.Secure),
|
|
698
|
+
key,
|
|
699
|
+
);
|
|
658
700
|
},
|
|
659
701
|
getSecureBiometric: (key: string) => {
|
|
660
702
|
const value = withWebBackendOperation(
|
|
@@ -668,7 +710,9 @@ const WebStorage: Storage = {
|
|
|
668
710
|
withWebBackendOperation(
|
|
669
711
|
StorageScope.Secure,
|
|
670
712
|
"deleteSecureBiometric",
|
|
671
|
-
(backend) =>
|
|
713
|
+
(backend) => {
|
|
714
|
+
backend.removeItem(toBiometricStorageKey(key));
|
|
715
|
+
},
|
|
672
716
|
);
|
|
673
717
|
if (
|
|
674
718
|
withWebBackendOperation(
|
|
@@ -679,7 +723,10 @@ const WebStorage: Storage = {
|
|
|
679
723
|
) {
|
|
680
724
|
ensureWebScopeKeyIndex(StorageScope.Secure).delete(key);
|
|
681
725
|
}
|
|
682
|
-
notifyKeyListeners(
|
|
726
|
+
notifyKeyListeners(
|
|
727
|
+
getInternals().getScopedListeners(StorageScope.Secure),
|
|
728
|
+
key,
|
|
729
|
+
);
|
|
683
730
|
},
|
|
684
731
|
hasSecureBiometric: (key: string) => {
|
|
685
732
|
return (
|
|
@@ -730,8 +777,10 @@ const WebStorage: Storage = {
|
|
|
730
777
|
keyIndex.delete(key);
|
|
731
778
|
}
|
|
732
779
|
});
|
|
733
|
-
const listeners =
|
|
734
|
-
keysToNotify.forEach((key) =>
|
|
780
|
+
const listeners = getInternals().getScopedListeners(StorageScope.Secure);
|
|
781
|
+
keysToNotify.forEach((key) => {
|
|
782
|
+
notifyKeyListeners(listeners, key);
|
|
783
|
+
});
|
|
735
784
|
},
|
|
736
785
|
};
|
|
737
786
|
|
|
@@ -743,7 +792,6 @@ function buildWebAdapter(
|
|
|
743
792
|
backend: WebStorage,
|
|
744
793
|
changeSource: "web",
|
|
745
794
|
applyAccessControlOnSecureRawWrite: false,
|
|
746
|
-
flushDiskWritesOnImport: true,
|
|
747
795
|
ensureScopeSubscription: () => {
|
|
748
796
|
ensureExternalSyncSubscriptions();
|
|
749
797
|
},
|
|
@@ -763,18 +811,22 @@ export const storage = {
|
|
|
763
811
|
...core.storage,
|
|
764
812
|
setAccessControl: (level: AccessControl) => {
|
|
765
813
|
assertAccessControlLevel(level);
|
|
766
|
-
|
|
767
|
-
|
|
814
|
+
getInternals().setSecureDefaultAccessControl(level);
|
|
815
|
+
getInternals().recordMetric(
|
|
816
|
+
"storage:setAccessControl",
|
|
817
|
+
StorageScope.Secure,
|
|
818
|
+
0,
|
|
819
|
+
);
|
|
768
820
|
},
|
|
769
821
|
setSecureWritesAsync: (_enabled: boolean) => {
|
|
770
|
-
|
|
822
|
+
getInternals().recordMetric(
|
|
771
823
|
"storage:setSecureWritesAsync",
|
|
772
824
|
StorageScope.Secure,
|
|
773
825
|
0,
|
|
774
826
|
);
|
|
775
827
|
},
|
|
776
828
|
setKeychainAccessGroup: (_group: string) => {
|
|
777
|
-
|
|
829
|
+
getInternals().recordMetric(
|
|
778
830
|
"storage:setKeychainAccessGroup",
|
|
779
831
|
StorageScope.Secure,
|
|
780
832
|
0,
|
|
@@ -786,10 +838,10 @@ export const storage = {
|
|
|
786
838
|
disk: getBackendName(StorageScope.Disk, webDiskStorageBackend),
|
|
787
839
|
secure: getBackendName(StorageScope.Secure, webSecureStorageBackend),
|
|
788
840
|
},
|
|
789
|
-
writeBuffering:
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
841
|
+
writeBuffering: resolveWebWriteBuffering(
|
|
842
|
+
webDiskStorageBackend?.name,
|
|
843
|
+
webSecureStorageBackend?.name,
|
|
844
|
+
),
|
|
793
845
|
errorClassification: true,
|
|
794
846
|
}),
|
|
795
847
|
getSecurityCapabilities: (): SecurityCapabilities => {
|
|
@@ -839,15 +891,13 @@ export function setWebSecureStorageBackend(
|
|
|
839
891
|
): void {
|
|
840
892
|
const previousBackend = webSecureStorageBackend;
|
|
841
893
|
const nextBackend = backend ?? createDefaultSecureBackend();
|
|
842
|
-
|
|
894
|
+
getInternals().flushSecureWrites();
|
|
843
895
|
resetBackendChangeSubscription(StorageScope.Secure);
|
|
844
896
|
webSecureStorageBackend = nextBackend;
|
|
845
897
|
hydratedWebScopeKeyIndex.delete(StorageScope.Secure);
|
|
846
|
-
|
|
898
|
+
getInternals().clearScopeRawCache(StorageScope.Secure);
|
|
847
899
|
ensureExternalSyncSubscriptions();
|
|
848
|
-
|
|
849
|
-
closeWebBackend(StorageScope.Secure, previousBackend);
|
|
850
|
-
}
|
|
900
|
+
retireWebBackend(StorageScope.Secure, previousBackend, nextBackend);
|
|
851
901
|
}
|
|
852
902
|
|
|
853
903
|
export function getWebSecureStorageBackend():
|
|
@@ -860,15 +910,13 @@ export function setWebDiskStorageBackend(
|
|
|
860
910
|
): void {
|
|
861
911
|
const previousBackend = webDiskStorageBackend;
|
|
862
912
|
const nextBackend = backend ?? createDefaultDiskBackend();
|
|
863
|
-
|
|
913
|
+
getInternals().flushDiskWrites();
|
|
864
914
|
resetBackendChangeSubscription(StorageScope.Disk);
|
|
865
915
|
webDiskStorageBackend = nextBackend;
|
|
866
916
|
hydratedWebScopeKeyIndex.delete(StorageScope.Disk);
|
|
867
|
-
|
|
917
|
+
getInternals().clearScopeRawCache(StorageScope.Disk);
|
|
868
918
|
ensureExternalSyncSubscriptions();
|
|
869
|
-
|
|
870
|
-
closeWebBackend(StorageScope.Disk, previousBackend);
|
|
871
|
-
}
|
|
919
|
+
retireWebBackend(StorageScope.Disk, previousBackend, nextBackend);
|
|
872
920
|
}
|
|
873
921
|
|
|
874
922
|
export function getWebDiskStorageBackend(): WebDiskStorageBackend | undefined {
|
|
@@ -876,21 +924,45 @@ export function getWebDiskStorageBackend(): WebDiskStorageBackend | undefined {
|
|
|
876
924
|
}
|
|
877
925
|
|
|
878
926
|
export async function flushWebStorageBackends(): Promise<void> {
|
|
879
|
-
|
|
880
|
-
|
|
927
|
+
getInternals().flushDiskWrites();
|
|
928
|
+
getInternals().flushSecureWrites();
|
|
881
929
|
|
|
882
|
-
const
|
|
883
|
-
|
|
884
|
-
|
|
930
|
+
const backends = Array.from(
|
|
931
|
+
new Set([
|
|
932
|
+
webDiskStorageBackend,
|
|
933
|
+
webSecureStorageBackend,
|
|
934
|
+
...retiredWebBackends.keys(),
|
|
935
|
+
]),
|
|
936
|
+
).filter((backend): backend is WebStorageBackend => backend !== undefined);
|
|
937
|
+
|
|
938
|
+
const results = await Promise.allSettled(
|
|
939
|
+
backends.map(async (backend) => {
|
|
940
|
+
if (backend.flush) {
|
|
941
|
+
await backend.flush();
|
|
942
|
+
}
|
|
943
|
+
if (!retiredWebBackends.has(backend)) {
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
if (
|
|
947
|
+
backend === webDiskStorageBackend ||
|
|
948
|
+
backend === webSecureStorageBackend
|
|
949
|
+
) {
|
|
950
|
+
retiredWebBackends.delete(backend);
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
const scope = retiredWebBackends.get(backend);
|
|
954
|
+
if (scope === undefined) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
closeWebBackend(scope, backend);
|
|
958
|
+
retiredWebBackends.delete(backend);
|
|
959
|
+
}),
|
|
960
|
+
);
|
|
885
961
|
|
|
886
|
-
|
|
887
|
-
|
|
962
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
963
|
+
if (failure) {
|
|
964
|
+
throw failure.reason;
|
|
888
965
|
}
|
|
889
|
-
if (secureFlush) {
|
|
890
|
-
flushes.push(secureFlush());
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
await Promise.all(flushes);
|
|
894
966
|
}
|
|
895
967
|
|
|
896
968
|
export {
|