probeWebStorageCapabilities function
Probes OPFS, worker sync handles, quota and optional Chromium-only APIs.
The worker handshake starts the page-wide OPFS worker (a Blob-URL
dedicated worker); its result is cached for later file opens. requestPersist
calls navigator.storage.persist() (Firefox shows a prompt, Chrome silently
grants/denies).
Implementation
Future<WebStorageCapabilities> probeWebStorageCapabilities({
bool requestPersist = false,
}) async {
final filePrototype = _prototypeOfGlobal('FileSystemFileHandle');
final syncHere = _hasFunction(filePrototype, 'createSyncAccessHandle');
final createWritable = _hasFunction(filePrototype, 'createWritable');
var opfs = false;
int? quota;
int? usage;
var persisted = false;
String? workerError;
var syncInWorker = false;
final storage = jsStorageManager;
opfs = _hasFunction(storage, 'getDirectory');
if (storage != null && opfs) {
try {
final estimate = await jsAwait(jsCall(storage, 'estimate'));
if (estimate != null) {
final object = estimate as JSObject;
quota = jsInt(object['quota']);
usage = jsInt(object['usage']);
}
} catch (_) {
// estimate() is advisory; ignore failures.
}
try {
persisted = jsBool(await jsAwait(jsCall(storage, 'persisted')));
} catch (_) {
// persisted() can be missing/blocked in exotic contexts.
}
if (requestPersist) {
try {
persisted = jsBool(await jsAwait(jsCall(storage, 'persist')));
} catch (_) {
// Not granted; keep the previous value.
}
}
try {
final pool = await OpfsWorkerPool.instance();
final client = pool.manifest;
final caps = client.capabilities ?? await client.hello();
syncInWorker = caps.syncAccessHandle;
if (!caps.opfs) {
workerError = 'worker reports OPFS unavailable';
}
} catch (error) {
workerError = '$error';
}
} else {
workerError = 'navigator.storage.getDirectory is not available';
}
final navigator = jsNavigator;
return WebStorageCapabilities(
opfs: opfs,
syncAccessHandleInWorker: syncInWorker,
syncAccessHandleOnCurrentThread: syncHere,
createWritable: createWritable,
fileSystemPickers:
_hasGlobal('showOpenFilePicker') && _hasGlobal('showSaveFilePicker'),
fileSystemObserver: _hasGlobal('FileSystemObserver'),
storageBuckets:
navigator != null && navigator['storageBuckets'].isDefinedAndNotNull,
sharedArrayBuffer: _hasGlobal('SharedArrayBuffer'),
crossOriginIsolated: _protoBool(globalContext['crossOriginIsolated']),
quotaBytes: quota,
usageBytes: usage,
persisted: persisted,
workerError: workerError,
);
}