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.
88 lines
3.0 KiB
TypeScript
88 lines
3.0 KiB
TypeScript
/**
|
||
* 图片加载模块
|
||
* 负责从服务器加载并解密图片用于预览
|
||
*/
|
||
|
||
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;
|