forked from dart-lang/webdev
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstorage.dart
149 lines (134 loc) · 4.26 KB
/
storage.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@JS()
library storage;
import 'dart:async';
import 'dart:convert';
import 'dart:js_util';
import 'package:js/js.dart';
import 'chrome_api.dart';
import 'data_serializers.dart';
import 'logger.dart';
import 'utils.dart';
enum StorageObject {
debugInfo,
devToolsOpener,
devToolsUri,
encodedUri,
isAuthenticated;
Persistance get persistance {
switch (this) {
case StorageObject.debugInfo:
return Persistance.sessionOnly;
case StorageObject.devToolsOpener:
return Persistance.acrossSessions;
case StorageObject.devToolsUri:
return Persistance.sessionOnly;
case StorageObject.encodedUri:
return Persistance.sessionOnly;
case StorageObject.isAuthenticated:
return Persistance.sessionOnly;
}
}
}
enum Persistance {
sessionOnly,
acrossSessions;
}
Future<bool> setStorageObject<T>({
required StorageObject type,
required T value,
int? tabId,
void Function()? callback,
}) {
final storageKey = _createStorageKey(type, tabId);
final json =
value is String ? value : jsonEncode(serializers.serialize(value));
final storageObj = <String, String>{storageKey: json};
final completer = Completer<bool>();
final storageArea = _getStorageArea(type.persistance);
storageArea.set(jsify(storageObj), allowInterop(() {
if (callback != null) {
callback();
}
debugLog('Set: $json', prefix: storageKey);
completer.complete(true);
}));
return completer.future;
}
Future<T?> fetchStorageObject<T>({required StorageObject type, int? tabId}) {
final storageKey = _createStorageKey(type, tabId);
final completer = Completer<T?>();
final storageArea = _getStorageArea(type.persistance);
storageArea.get([storageKey], allowInterop((Object? storageObj) {
if (storageObj == null) {
debugWarn('Does not exist.', prefix: storageKey);
completer.complete(null);
return;
}
final json = getProperty(storageObj, storageKey) as String?;
if (json == null) {
debugWarn('Does not exist.', prefix: storageKey);
completer.complete(null);
} else {
debugLog('Fetched: $json', prefix: storageKey);
if (T == String) {
completer.complete(json as T);
} else {
final value = serializers.deserialize(jsonDecode(json)) as T;
completer.complete(value);
}
}
}));
return completer.future;
}
Future<bool> removeStorageObject<T>({required StorageObject type, int? tabId}) {
final storageKey = _createStorageKey(type, tabId);
final completer = Completer<bool>();
final storageArea = _getStorageArea(type.persistance);
storageArea.remove([storageKey], allowInterop(() {
debugLog('Removed object.', prefix: storageKey);
completer.complete(true);
}));
return completer.future;
}
void interceptStorageChange<T>({
required Object storageObj,
required StorageObject expectedType,
required void Function(T? storageObj) changeHandler,
int? tabId,
}) {
try {
final expectedStorageKey = _createStorageKey(expectedType, tabId);
final isExpected = hasProperty(storageObj, expectedStorageKey);
if (!isExpected) return;
final objProp = getProperty(storageObj, expectedStorageKey);
final json = getProperty(objProp, 'newValue') as String?;
T? decodedObj;
if (json == null || T == String) {
decodedObj = json as T?;
} else {
decodedObj = serializers.deserialize(jsonDecode(json)) as T?;
}
debugLog('Intercepted $expectedStorageKey change: $json');
return changeHandler(decodedObj);
} catch (error) {
debugError(
'Error intercepting storage object with type $expectedType: $error');
}
}
StorageArea _getStorageArea(Persistance persistance) {
// MV2 extensions don't have access to session storage:
if (!isMV3) return chrome.storage.local;
switch (persistance) {
case Persistance.acrossSessions:
return chrome.storage.local;
case Persistance.sessionOnly:
return chrome.storage.session;
}
}
String _createStorageKey(StorageObject type, int? tabId) {
if (tabId == null) return type.name;
return '$tabId-${type.name}';
}