Files
Suzu008 a58a5b8917 refactor(sw): bidirectional SW status sync with IndexedDB persistence
Replace fire-and-forget key delivery with a sync-status protocol that
verifies key consistency between main thread and Service Worker using
SHA-256 fingerprints via MessageChannel request-response.

- SW (ts/sw.ts): persist keys in IndexedDB, auto-restore on activate;
  respond to sync-status queries with loaded keys + fingerprints;
  support cryptio-clear-keys to wipe memory + DB.
- New ts/utils/swSync.ts: single entry point for SW registration,
  key sync, and status verification. Controller change listener
  re-syncs on SW restart. Deduplicates concurrent sync calls.
- Deleted ts/utils/swKeySender.ts (replaced by swSync.ts).
- Remove SW registration (~55 lines) from cryptioSaveImage.ts;
  setup() now calls syncSWStatus().
- uploadUtils.ts: drop 5-retry preview loop (~6.4s worst case);
  single attempt with syncSWStatus fallback on failure.
- cryptioSettings.ts: sync after key changes; clearSWKeys() on
  Clear All.
- cryptioUploadImage/Video.ts: syncSWStatus in setup + preview
  fallback.
- types.ts: add SWStatus interface.
2026-05-30 22:29:45 +08:00

88 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 图片加载模块
* 负责从服务器加载并解密图片用于预览
*/
import type { ComfyApi } from "@comfyorg/comfyui-frontend-types";
import { decryptDataWithServerKey, decryptFileWithClientKey } from "./cryptoUtils.js";
import { getMimeTypeFromFilename, downloadDecryptedFile } from "./fileUtils.js";
export interface ImageLoadParams {
filename: string;
subfolder?: string;
type: string;
}
/**
* 从简单文件名加载加密图片(用于UploadImage场景,使用服务端私钥解密)
* @param filename 文件名
* @returns Blob URL
*/
export async function loadEncryptedImageFromFilename(filename: string): Promise<string> {
// 从服务器获取加密数据(二进制格式)
const response = await fetch(
`/cryptio/view_encrypted?filename=${encodeURIComponent(filename)}`
);
if (!response.ok) {
throw new Error(`Failed to load encrypted image: ${response.statusText}`);
}
// 直接读取二进制数据
const encryptedArrayBuffer = await response.arrayBuffer();
const encryptedData = new Uint8Array(encryptedArrayBuffer);
// 使用服务端私钥解密(UploadImage场景)
const decryptedData = await decryptDataWithServerKey(encryptedData);
// 转换为Blob URL
const blob = new Blob([decryptedData as BlobPart], {
type: getMimeTypeFromFilename(filename),
});
return URL.createObjectURL(blob);
}
/**
* 从参数加载加密图片(用于SaveImage/PreviewImage场景,使用客户端私钥解密)
* @param api ComfyUI API实例
* @param params 图片参数(包含filename, subfolder, type)
* @returns Blob URL
*/
export async function loadEncryptedImageFromParams(api: ComfyApi, params: ImageLoadParams): Promise<string> {
// 构建URL
const url = api.apiURL(
`/view?filename=${encodeURIComponent(params.filename)}&type=${params.type}${
params.subfolder ? `&subfolder=${encodeURIComponent(params.subfolder)}` : ""
}`
);
// 从服务器获取加密数据(二进制格式)
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to load encrypted image: ${response.statusText}`);
}
// 直接读取二进制数据
let decryptedData: Uint8Array;
const encryptedArrayBuffer = await response.arrayBuffer();
const encryptedData = new Uint8Array(encryptedArrayBuffer);
// If the Service Worker already decrypted the response, skip re-decryption
if (response.headers.get("X-CryptIO-Decrypted") === "1") {
decryptedData = encryptedData;
} else {
// 使用客户端私钥解密(SaveImage/PreviewImage场景)
decryptedData = await decryptFileWithClientKey(encryptedData);
}
// 转换为Blob URL
const blob = new Blob([decryptedData as BlobPart], {
type: getMimeTypeFromFilename(params.filename),
});
return URL.createObjectURL(blob);
}
/** @deprecated Use downloadDecryptedFile from fileUtils.ts instead */
export const downloadDecryptedImage = downloadDecryptedFile;