@contentauth/c2pa-web 0.1.1 → 0.2.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/LICENSE +21 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -41
- package/dist/lib/reader.d.ts +16 -3
- package/dist/lib/reader.d.ts.map +1 -1
- package/dist/lib/settings.d.ts +1 -0
- package/dist/lib/settings.d.ts.map +1 -1
- package/dist/lib/worker.d.ts +3 -1
- package/dist/lib/worker.d.ts.map +1 -1
- package/dist/resources/c2pa_bg.wasm +0 -0
- package/package.json +8 -3
- package/CHANGELOG.md +0 -20
- package/eslint.config.mjs +0 -30
- package/project.json +0 -7
- package/src/index.ts +0 -15
- package/src/lib/c2pa.spec.ts +0 -166
- package/src/lib/c2pa.ts +0 -65
- package/src/lib/error.ts +0 -26
- package/src/lib/reader.ts +0 -150
- package/src/lib/settings.ts +0 -52
- package/src/lib/supportedFormats.ts +0 -72
- package/src/lib/worker/setupWorker.ts +0 -53
- package/src/lib/worker/workerManager.ts +0 -64
- package/src/lib/worker/workerObjectMap.ts +0 -35
- package/src/lib/worker/workerResponse.ts +0 -50
- package/src/lib/worker.ts +0 -77
- package/test/fixtures/assets/C_with_CAWG_data.jpg +0 -0
- package/test/fixtures/assets/C_with_CAWG_data.json +0 -144
- package/test/fixtures/assets/C_with_CAWG_data_thumbnail.jpg +0 -0
- package/test/fixtures/assets/C_with_CAWG_data_trusted.json +0 -149
- package/test/fixtures/assets/C_with_CAWG_data_untrusted.json +0 -157
- package/test/fixtures/assets/dash1.m4s +0 -0
- package/test/fixtures/assets/dashinit.json +0 -184
- package/test/fixtures/assets/dashinit.mp4 +0 -0
- package/test/fixtures/assets/no_alg.jpg +0 -0
- package/test/fixtures/trust/anchor-correct.pem +0 -15
- package/test/fixtures/trust/anchor-incorrect.pem +0 -16
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -29
- package/tsconfig.spec.json +0 -36
- package/vite.config.ts +0 -91
package/src/lib/c2pa.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
import { createWorkerManager } from './worker/workerManager.js';
|
|
10
|
-
import { createReaderFactory, ReaderFactory } from './reader.js';
|
|
11
|
-
import { WASM_SRI } from '@contentauth/c2pa-wasm';
|
|
12
|
-
import { Settings, settingsToWasmJson } from './settings.js';
|
|
13
|
-
|
|
14
|
-
export interface Config {
|
|
15
|
-
/**
|
|
16
|
-
* URL to fetch the WASM binary or an already-instantiated WASM module.
|
|
17
|
-
*/
|
|
18
|
-
wasmSrc: string | WebAssembly.Module;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Settings for the SDK.
|
|
22
|
-
*/
|
|
23
|
-
settings?: Settings;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface C2paSdk {
|
|
27
|
-
reader: ReaderFactory;
|
|
28
|
-
dispose: () => void;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Creates a new instance of c2pa-web by setting up a web worker and preparing a WASM binary.
|
|
33
|
-
*
|
|
34
|
-
* @param config - SDK configuration object.
|
|
35
|
-
* @returns An object providing access to factory methods for creating new reader objects.
|
|
36
|
-
*
|
|
37
|
-
* @example Creating a new SDK instance and reader:
|
|
38
|
-
* ```
|
|
39
|
-
* const c2pa = await createC2pa({ wasmSrc: 'url/hosting/wasm/binary' });
|
|
40
|
-
*
|
|
41
|
-
* const reader = await c2pa.reader.fromBlob(imageBlob.type, imageBlob);
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
export async function createC2pa(config: Config): Promise<C2paSdk> {
|
|
45
|
-
const { wasmSrc, settings } = config;
|
|
46
|
-
|
|
47
|
-
const wasm =
|
|
48
|
-
typeof wasmSrc === 'string' ? await fetchAndCompileWasm(wasmSrc) : wasmSrc;
|
|
49
|
-
|
|
50
|
-
const settingsString = settings ? settingsToWasmJson(settings) : undefined;
|
|
51
|
-
|
|
52
|
-
const worker = await createWorkerManager({ wasm, settingsString });
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
reader: createReaderFactory(worker),
|
|
56
|
-
dispose: worker.terminate,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function fetchAndCompileWasm(src: string) {
|
|
61
|
-
const response = await fetch(src, { integrity: WASM_SRI });
|
|
62
|
-
const wasm = await WebAssembly.compileStreaming(response);
|
|
63
|
-
|
|
64
|
-
return wasm;
|
|
65
|
-
}
|
package/src/lib/error.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { MAX_SIZE_IN_BYTES } from './reader.js';
|
|
11
|
-
|
|
12
|
-
export class AssetTooLargeError extends Error {
|
|
13
|
-
constructor(size: number) {
|
|
14
|
-
super(
|
|
15
|
-
`The provided asset was too large. Size: ${size} bytes. Maximum: ${MAX_SIZE_IN_BYTES}.`
|
|
16
|
-
);
|
|
17
|
-
this.name = 'AssetTooLargeError';
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class UnsupportedFormatError extends Error {
|
|
22
|
-
constructor(format: string) {
|
|
23
|
-
super(`Unsupported format: ${format}.`);
|
|
24
|
-
this.name = 'UnsupportedFormatError';
|
|
25
|
-
}
|
|
26
|
-
}
|
package/src/lib/reader.ts
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { AssetTooLargeError, UnsupportedFormatError } from './error.js';
|
|
11
|
-
import { isSupportedReaderFormat } from './supportedFormats.js';
|
|
12
|
-
import type { WorkerManager } from './worker/workerManager.js';
|
|
13
|
-
|
|
14
|
-
// 1 GB
|
|
15
|
-
export const MAX_SIZE_IN_BYTES = 10 ** 9;
|
|
16
|
-
|
|
17
|
-
export interface ReaderFactory {
|
|
18
|
-
/**
|
|
19
|
-
* Create a Reader from an asset's format and a blob of its bytes.
|
|
20
|
-
*
|
|
21
|
-
* @param format Asset format
|
|
22
|
-
* @param blob Blob of asset bytes
|
|
23
|
-
* @returns An object that provides methods for reading C2PA data from the provided asset.
|
|
24
|
-
*/
|
|
25
|
-
fromBlob: (format: string, blob: Blob) => Promise<Reader>;
|
|
26
|
-
|
|
27
|
-
fromBlobFragment: (
|
|
28
|
-
format: string,
|
|
29
|
-
init: Blob,
|
|
30
|
-
fragment: Blob
|
|
31
|
-
) => Promise<Reader>;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface Reader {
|
|
35
|
-
/**
|
|
36
|
-
* @returns The asset's full manifest store containing all its manifests, validation statuses, and the URI of the active manifest.
|
|
37
|
-
*/
|
|
38
|
-
manifestStore: () => Promise<any>;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @returns The label of the active manifest.
|
|
42
|
-
*/
|
|
43
|
-
activeLabel: () => Promise<string | null>;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Resolves a URI reference to a binary object (e.g. a thumbnail) in the resource store.
|
|
47
|
-
*
|
|
48
|
-
* @param uri URI of the binary object to resolve.
|
|
49
|
-
* @returns An array buffer of the resource's bytes.
|
|
50
|
-
*/
|
|
51
|
-
resourceToBuffer: (uri: string) => Promise<ArrayBuffer>;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Dispose of this Reader, freeing the memory it occupied and preventing further use. Call this whenever the Reader is no longer needed.
|
|
55
|
-
*/
|
|
56
|
-
free: () => Promise<void>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
* @param worker - Worker (via WorkerManager) to be associated with this reader factory
|
|
62
|
-
* @returns Object containing reader creation methods
|
|
63
|
-
*/
|
|
64
|
-
export function createReaderFactory(worker: WorkerManager): ReaderFactory {
|
|
65
|
-
const registry = new FinalizationRegistry<number>((id) => {
|
|
66
|
-
worker.execute({ method: 'reader_free', args: [id] });
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
async fromBlob(format: string, blob: Blob): Promise<Reader> {
|
|
71
|
-
if (!isSupportedReaderFormat(format)) {
|
|
72
|
-
throw new UnsupportedFormatError(format);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (blob.size > MAX_SIZE_IN_BYTES) {
|
|
76
|
-
throw new AssetTooLargeError(blob.size);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const readerId = await worker.execute({
|
|
80
|
-
method: 'reader_fromBlob',
|
|
81
|
-
args: [format, blob],
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const unregisterToken = Symbol(readerId);
|
|
85
|
-
const reader = createReader(worker, readerId, () => {
|
|
86
|
-
registry.unregister(unregisterToken);
|
|
87
|
-
});
|
|
88
|
-
registry.register(reader, readerId, unregisterToken);
|
|
89
|
-
|
|
90
|
-
return reader;
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
async fromBlobFragment(format: string, init: Blob, fragment: Blob) {
|
|
94
|
-
if (!isSupportedReaderFormat(format)) {
|
|
95
|
-
throw new UnsupportedFormatError(format);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (init.size > MAX_SIZE_IN_BYTES) {
|
|
99
|
-
throw new AssetTooLargeError(init.size);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const readerId = await worker.execute({
|
|
103
|
-
method: 'reader_fromBlobFragment',
|
|
104
|
-
args: [format, init, fragment],
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const unregisterToken = Symbol(readerId);
|
|
108
|
-
const reader = createReader(worker, readerId, () => {
|
|
109
|
-
registry.unregister(unregisterToken);
|
|
110
|
-
});
|
|
111
|
-
registry.register(reader, readerId, unregisterToken);
|
|
112
|
-
|
|
113
|
-
return reader;
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function createReader(
|
|
119
|
-
worker: WorkerManager,
|
|
120
|
-
id: number,
|
|
121
|
-
onFree: () => void
|
|
122
|
-
): Reader {
|
|
123
|
-
return {
|
|
124
|
-
// TODO: manifest type
|
|
125
|
-
async manifestStore(): Promise<any> {
|
|
126
|
-
const json = await worker.execute({ method: 'reader_json', args: [id] });
|
|
127
|
-
|
|
128
|
-
const manifestStore = JSON.parse(json);
|
|
129
|
-
|
|
130
|
-
return manifestStore;
|
|
131
|
-
},
|
|
132
|
-
async activeLabel(): Promise<string | null> {
|
|
133
|
-
const label = await worker.execute({
|
|
134
|
-
method: 'reader_activeLabel',
|
|
135
|
-
args: [id],
|
|
136
|
-
});
|
|
137
|
-
return label;
|
|
138
|
-
},
|
|
139
|
-
async resourceToBuffer(uri: string): Promise<ArrayBuffer> {
|
|
140
|
-
return worker.execute({
|
|
141
|
-
method: 'reader_resourceToBuffer',
|
|
142
|
-
args: [id, uri],
|
|
143
|
-
});
|
|
144
|
-
},
|
|
145
|
-
async free(): Promise<void> {
|
|
146
|
-
onFree();
|
|
147
|
-
return worker.execute({ method: 'reader_free', args: [id] });
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
package/src/lib/settings.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export interface Settings {
|
|
11
|
-
trust?: TrustSettings;
|
|
12
|
-
verify?: VerifySettings;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface TrustSettings {
|
|
16
|
-
userAnchors?: string;
|
|
17
|
-
trustAnchors?: string;
|
|
18
|
-
trustConfig?: string;
|
|
19
|
-
allowedList?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface VerifySettings {
|
|
23
|
-
verifyTrust?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type SettingsObjectType = {
|
|
27
|
-
[k: string]: string | boolean | SettingsObjectType;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Converts a settings object to a JSON string of the structure expected by c2pa-rs.
|
|
32
|
-
*/
|
|
33
|
-
export function settingsToWasmJson(settings: Settings) {
|
|
34
|
-
return JSON.stringify(snakeCaseify(settings as SettingsObjectType));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function snakeCaseify(object: SettingsObjectType): SettingsObjectType {
|
|
38
|
-
const formattedObject = Object.entries(object).reduce(
|
|
39
|
-
(formattedObject, [key, val]) => {
|
|
40
|
-
formattedObject[snakeCase(key)] =
|
|
41
|
-
typeof val === 'object' ? snakeCaseify(val) : val;
|
|
42
|
-
return formattedObject;
|
|
43
|
-
},
|
|
44
|
-
{} as SettingsObjectType
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return formattedObject;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function snakeCase(str: string): string {
|
|
51
|
-
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
52
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export const READER_SUPPORTED_FORMATS = [
|
|
11
|
-
'jpg',
|
|
12
|
-
'video/mp4',
|
|
13
|
-
'image/heif',
|
|
14
|
-
'video/x-msvideo',
|
|
15
|
-
'pdf',
|
|
16
|
-
'image/png',
|
|
17
|
-
'application/c2pa',
|
|
18
|
-
'video/quicktime',
|
|
19
|
-
'video/avi',
|
|
20
|
-
'image/gif',
|
|
21
|
-
'application/xml',
|
|
22
|
-
'text/xml',
|
|
23
|
-
'application/xhtml+xml',
|
|
24
|
-
'tiff',
|
|
25
|
-
'audio/wave',
|
|
26
|
-
'mp4',
|
|
27
|
-
'image/avif',
|
|
28
|
-
'image/dng',
|
|
29
|
-
'png',
|
|
30
|
-
'dng',
|
|
31
|
-
'image/svg+xml',
|
|
32
|
-
'image/heic',
|
|
33
|
-
'application/mp4',
|
|
34
|
-
'image/x-nikon-nef',
|
|
35
|
-
'video/msvideo',
|
|
36
|
-
'tif',
|
|
37
|
-
'wav',
|
|
38
|
-
'xml',
|
|
39
|
-
'audio/vnd.wave',
|
|
40
|
-
'xhtml',
|
|
41
|
-
'gif',
|
|
42
|
-
'application/x-troff-msvideo',
|
|
43
|
-
'webp',
|
|
44
|
-
'heic',
|
|
45
|
-
'application/pdf',
|
|
46
|
-
'audio/mpeg',
|
|
47
|
-
'application/x-c2pa-manifest-store',
|
|
48
|
-
'jpeg',
|
|
49
|
-
'image/x-adobe-dng',
|
|
50
|
-
'audio/wav',
|
|
51
|
-
'mp3',
|
|
52
|
-
'mov',
|
|
53
|
-
'image/tiff',
|
|
54
|
-
'audio/mp4',
|
|
55
|
-
'application/svg+xml',
|
|
56
|
-
'arw',
|
|
57
|
-
'c2pa',
|
|
58
|
-
'svg',
|
|
59
|
-
'avi',
|
|
60
|
-
'audio/x-wav',
|
|
61
|
-
'm4a',
|
|
62
|
-
'image/x-sony-arw',
|
|
63
|
-
'image/jpeg',
|
|
64
|
-
'avif',
|
|
65
|
-
'image/webp',
|
|
66
|
-
'nef',
|
|
67
|
-
'heif',
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
export function isSupportedReaderFormat(format: string): boolean {
|
|
71
|
-
return READER_SUPPORTED_FORMATS.includes(format);
|
|
72
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { postError, postSuccess } from './workerResponse.js';
|
|
11
|
-
|
|
12
|
-
export interface WorkerRequest<T, K> {
|
|
13
|
-
method: T;
|
|
14
|
-
args: K;
|
|
15
|
-
transfer?: Transferable[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type WorkerRequestPayload = Omit<WorkerRequest<any, any>, 'transfer'>;
|
|
19
|
-
|
|
20
|
-
export interface WorkerResponse<T> {
|
|
21
|
-
data: T;
|
|
22
|
-
transfer?: Transferable[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type WorkerFunctions = Record<
|
|
26
|
-
string,
|
|
27
|
-
(
|
|
28
|
-
...args: any[]
|
|
29
|
-
) => void | Promise<void> | WorkerResponse<any> | Promise<WorkerResponse<any>>
|
|
30
|
-
>;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Prepares a worker with a list of functions to expose via postMessage and an initialization function
|
|
34
|
-
*
|
|
35
|
-
* @param functions Map of functions keyed by name
|
|
36
|
-
* @param init Initialization function to be called once when the worker is set up
|
|
37
|
-
*/
|
|
38
|
-
export function setupWorker(functions: WorkerFunctions) {
|
|
39
|
-
onmessage = async (e: MessageEvent<WorkerRequestPayload>) => {
|
|
40
|
-
try {
|
|
41
|
-
const { args, method } = e.data;
|
|
42
|
-
const result = await functions[method](...args);
|
|
43
|
-
|
|
44
|
-
if (result?.data !== undefined) {
|
|
45
|
-
postSuccess(result.data, result.transfer);
|
|
46
|
-
} else {
|
|
47
|
-
postSuccess();
|
|
48
|
-
}
|
|
49
|
-
} catch (e) {
|
|
50
|
-
postError(e);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { WorkerDefinition } from '../worker.js';
|
|
11
|
-
import Worker from '../worker?worker&inline';
|
|
12
|
-
import { WorkerRequest, WorkerResponse } from './setupWorker.js';
|
|
13
|
-
import { handleWorkerResponse } from './workerResponse.js';
|
|
14
|
-
|
|
15
|
-
export interface WorkerManager {
|
|
16
|
-
execute: <T extends keyof WorkerDefinition, K extends WorkerDefinition[T]>(
|
|
17
|
-
request: WorkerRequest<T, Parameters<K>>
|
|
18
|
-
) => Promise<
|
|
19
|
-
Awaited<ReturnType<K>> extends WorkerResponse<infer Data>
|
|
20
|
-
? Data
|
|
21
|
-
: Awaited<ReturnType<K>>
|
|
22
|
-
>;
|
|
23
|
-
terminate: () => void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface CreateWorkerManagerConfig {
|
|
27
|
-
wasm: WebAssembly.Module;
|
|
28
|
-
settingsString?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Creates a new web worker and performs initialization steps:
|
|
33
|
-
* - Compile WASM
|
|
34
|
-
* - Load settings (if provided)
|
|
35
|
-
*
|
|
36
|
-
* @param config - configuration object
|
|
37
|
-
* @returns Facade providing convenient control over worker functions
|
|
38
|
-
*/
|
|
39
|
-
export async function createWorkerManager(
|
|
40
|
-
config: CreateWorkerManagerConfig
|
|
41
|
-
): Promise<WorkerManager> {
|
|
42
|
-
const { wasm, settingsString } = config;
|
|
43
|
-
|
|
44
|
-
const worker = new Worker();
|
|
45
|
-
|
|
46
|
-
const execute: WorkerManager['execute'] = (request) => {
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
48
|
-
handleWorkerResponse(worker, {
|
|
49
|
-
onSuccess: (data) => resolve(data),
|
|
50
|
-
onError: (error) => reject(error),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const { method, args, transfer } = request;
|
|
54
|
-
worker.postMessage({ method, args }, transfer ?? []);
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
await execute({ method: 'initWorker', args: [wasm, settingsString] });
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
execute,
|
|
62
|
-
terminate: () => worker.terminate(),
|
|
63
|
-
};
|
|
64
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export function createWorkerObjectMap<T>() {
|
|
11
|
-
let objId = 0;
|
|
12
|
-
const objectMap = new Map<number, T>();
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
add(object: T): number {
|
|
16
|
-
const id = objId++;
|
|
17
|
-
objectMap.set(id, object);
|
|
18
|
-
return id;
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
get(id: number): T {
|
|
22
|
-
const maybeObject = objectMap.get(id);
|
|
23
|
-
|
|
24
|
-
if (!maybeObject) {
|
|
25
|
-
throw new Error('Attempted to use an object that has been freed');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return maybeObject;
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
remove(id: number): boolean {
|
|
32
|
-
return objectMap.delete(id);
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export function postSuccess(payload?: any, transfer?: Transferable[]): void {
|
|
11
|
-
const responseObject = {
|
|
12
|
-
type: 'success',
|
|
13
|
-
...(payload !== undefined ? { payload } : {}),
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
postMessage(responseObject, transfer ?? []);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function postError(error: unknown): void {
|
|
20
|
-
postMessage({ type: 'error', error });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ResponseHandlers {
|
|
24
|
-
onSuccess: (data?: any) => void;
|
|
25
|
-
onError: (error?: any) => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function handleWorkerResponse(
|
|
29
|
-
worker: Worker,
|
|
30
|
-
responseHandlers: ResponseHandlers
|
|
31
|
-
) {
|
|
32
|
-
worker.onmessage = (event) => {
|
|
33
|
-
const { data } = event;
|
|
34
|
-
|
|
35
|
-
if (data.type === 'success') {
|
|
36
|
-
responseHandlers.onSuccess(data?.payload);
|
|
37
|
-
} else {
|
|
38
|
-
responseHandlers.onError(data?.error);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
// @TODO: should these have their own error handlers?
|
|
43
|
-
worker.onerror = (event) => {
|
|
44
|
-
responseHandlers.onError(event.error);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
worker.onmessageerror = (event) => {
|
|
48
|
-
responseHandlers.onError(event.data);
|
|
49
|
-
};
|
|
50
|
-
}
|
package/src/lib/worker.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2025 Adobe
|
|
3
|
-
* All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
6
|
-
* accordance with the terms of the Adobe license agreement accompanying
|
|
7
|
-
* it.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/// <reference lib="webworker" />
|
|
11
|
-
|
|
12
|
-
import { WasmReader, initSync, loadSettings } from '@contentauth/c2pa-wasm';
|
|
13
|
-
import {
|
|
14
|
-
setupWorker,
|
|
15
|
-
WorkerFunctions,
|
|
16
|
-
WorkerResponse,
|
|
17
|
-
} from './worker/setupWorker.js';
|
|
18
|
-
import { createWorkerObjectMap } from './worker/workerObjectMap.js';
|
|
19
|
-
|
|
20
|
-
const readerMap = createWorkerObjectMap<WasmReader>();
|
|
21
|
-
|
|
22
|
-
const workerFunctions = {
|
|
23
|
-
async initWorker(module: WebAssembly.Module, settings?: string) {
|
|
24
|
-
initSync(module);
|
|
25
|
-
|
|
26
|
-
if (settings) {
|
|
27
|
-
loadSettings(settings);
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
// Reader creation methods
|
|
32
|
-
async reader_fromBlob(
|
|
33
|
-
format: string,
|
|
34
|
-
blob: Blob
|
|
35
|
-
): Promise<WorkerResponse<number>> {
|
|
36
|
-
const reader = await WasmReader.fromBlob(format, blob);
|
|
37
|
-
const readerId = readerMap.add(reader);
|
|
38
|
-
return { data: readerId };
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
async reader_fromBlobFragment(
|
|
42
|
-
format: string,
|
|
43
|
-
init: Blob,
|
|
44
|
-
fragment: Blob
|
|
45
|
-
): Promise<WorkerResponse<number>> {
|
|
46
|
-
const reader = await WasmReader.fromBlobFragment(format, init, fragment);
|
|
47
|
-
const readerId = readerMap.add(reader);
|
|
48
|
-
return { data: readerId };
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
// Reader object methods
|
|
52
|
-
reader_json(readerId: number): WorkerResponse<string> {
|
|
53
|
-
const reader = readerMap.get(readerId);
|
|
54
|
-
return { data: reader.json() };
|
|
55
|
-
},
|
|
56
|
-
reader_activeLabel(readerId: number): WorkerResponse<string | null> {
|
|
57
|
-
const reader = readerMap.get(readerId);
|
|
58
|
-
return { data: reader.activeLabel() ?? null };
|
|
59
|
-
},
|
|
60
|
-
reader_resourceToBuffer(
|
|
61
|
-
readerId: number,
|
|
62
|
-
uri: string
|
|
63
|
-
): WorkerResponse<ArrayBuffer> {
|
|
64
|
-
const reader = readerMap.get(readerId);
|
|
65
|
-
const buffer = reader.resourceToBuffer(uri);
|
|
66
|
-
return { data: buffer, transfer: [buffer] };
|
|
67
|
-
},
|
|
68
|
-
reader_free(readerId: number) {
|
|
69
|
-
const reader = readerMap.get(readerId);
|
|
70
|
-
reader.free();
|
|
71
|
-
readerMap.remove(readerId);
|
|
72
|
-
},
|
|
73
|
-
} satisfies WorkerFunctions;
|
|
74
|
-
|
|
75
|
-
export type WorkerDefinition = typeof workerFunctions;
|
|
76
|
-
|
|
77
|
-
setupWorker(workerFunctions);
|
|
Binary file
|