@swf2es/desktop 0.1.20 → 0.1.22
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/dist/main/air-bridge.d.ts +7 -0
- package/dist/main/air-bridge.d.ts.map +1 -0
- package/dist/main/air-bridge.js +166 -0
- package/dist/main/air-bridge.js.map +1 -0
- package/dist/main/dialogs.d.ts +18 -0
- package/dist/main/dialogs.d.ts.map +1 -0
- package/dist/main/dialogs.js +128 -0
- package/dist/main/dialogs.js.map +1 -0
- package/dist/main/main.js +28 -788
- package/dist/main/main.js.map +1 -1
- package/dist/main/menu.d.ts +2 -0
- package/dist/main/menu.d.ts.map +1 -0
- package/dist/main/menu.js +80 -0
- package/dist/main/menu.js.map +1 -0
- package/dist/main/network-rules.d.ts +35 -0
- package/dist/main/network-rules.d.ts.map +1 -0
- package/dist/main/network-rules.js +167 -0
- package/dist/main/network-rules.js.map +1 -0
- package/dist/main/network-types.d.ts +131 -0
- package/dist/main/network-types.d.ts.map +1 -0
- package/dist/main/network-types.js +21 -0
- package/dist/main/network-types.js.map +1 -0
- package/dist/main/network.d.ts +1 -113
- package/dist/main/network.d.ts.map +1 -1
- package/dist/main/network.js +8 -181
- package/dist/main/network.js.map +1 -1
- package/dist/main/open.d.ts +55 -0
- package/dist/main/open.d.ts.map +1 -0
- package/dist/main/open.js +256 -0
- package/dist/main/open.js.map +1 -0
- package/dist/main/permissions.d.ts +17 -0
- package/dist/main/permissions.d.ts.map +1 -0
- package/dist/main/permissions.js +113 -0
- package/dist/main/permissions.js.map +1 -0
- package/dist/main/state.d.ts +17 -0
- package/dist/main/state.d.ts.map +1 -0
- package/dist/main/state.js +30 -0
- package/dist/main/state.js.map +1 -0
- package/dist/main/switches.d.ts +25 -0
- package/dist/main/switches.d.ts.map +1 -0
- package/dist/main/switches.js +69 -0
- package/dist/main/switches.js.map +1 -0
- package/package.json +7 -7
- package/src/main/air-bridge.ts +185 -0
- package/src/main/dialogs.ts +147 -0
- package/src/main/main.ts +56 -937
- package/src/main/menu.ts +84 -0
- package/src/main/network-rules.ts +199 -0
- package/src/main/network-types.ts +150 -0
- package/src/main/network.ts +30 -337
- package/src/main/open.ts +302 -0
- package/src/main/permissions.ts +135 -0
- package/src/main/state.ts +44 -0
- package/src/main/switches.ts +87 -0
package/src/main/menu.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// The application menu, built again as what plays and the settings change.
|
|
2
|
+
import { app, Menu, type MenuItemConstructorOptions } from "electron";
|
|
3
|
+
import { chooseLibrary, refuse, resetLibrary, showOpenDialog, showUrlDialog } from "./dialogs.ts";
|
|
4
|
+
import { closeMovie, current, openEntry } from "./open.ts";
|
|
5
|
+
import { settings, window } from "./state.ts";
|
|
6
|
+
|
|
7
|
+
export function buildMenu(): void {
|
|
8
|
+
const recent = settings.settings.recent;
|
|
9
|
+
const template: MenuItemConstructorOptions[] = [
|
|
10
|
+
...(process.platform === "darwin" ? [{ role: "appMenu" as const }] : []),
|
|
11
|
+
{
|
|
12
|
+
label: "&File",
|
|
13
|
+
submenu: [
|
|
14
|
+
{ label: "&Open…", accelerator: "CmdOrCtrl+O", click: () => void showOpenDialog() },
|
|
15
|
+
{ label: "Open &URL…", accelerator: "CmdOrCtrl+L", click: showUrlDialog },
|
|
16
|
+
{
|
|
17
|
+
label: "Open &Recent",
|
|
18
|
+
submenu: [
|
|
19
|
+
...recent.map((entry) => ({ label: entry, click: () => void openEntry(entry) })),
|
|
20
|
+
...(recent.length > 0 ? [{ type: "separator" as const }] : []),
|
|
21
|
+
{
|
|
22
|
+
label: "Clear Recent",
|
|
23
|
+
enabled: recent.length > 0,
|
|
24
|
+
click: () => {
|
|
25
|
+
settings.clearRecent();
|
|
26
|
+
app.clearRecentDocuments();
|
|
27
|
+
buildMenu();
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "close-movie",
|
|
34
|
+
label: "&Close Movie",
|
|
35
|
+
accelerator: "CmdOrCtrl+W",
|
|
36
|
+
enabled: !!current,
|
|
37
|
+
click: closeMovie,
|
|
38
|
+
},
|
|
39
|
+
{ type: "separator" },
|
|
40
|
+
{ label: "Choose playerglobal.abc…", click: () => void chooseLibrary("playerglobal") },
|
|
41
|
+
{
|
|
42
|
+
label: "Use the App's playerglobal",
|
|
43
|
+
enabled: !!settings.settings.playerglobal,
|
|
44
|
+
click: () => resetLibrary("playerglobal"),
|
|
45
|
+
},
|
|
46
|
+
{ type: "separator" },
|
|
47
|
+
{ role: "quit" },
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: "&View",
|
|
52
|
+
submenu: [
|
|
53
|
+
{
|
|
54
|
+
id: "reload-movie",
|
|
55
|
+
label: "&Reload Movie",
|
|
56
|
+
accelerator: "CmdOrCtrl+R",
|
|
57
|
+
enabled: !!current,
|
|
58
|
+
click: () => current && void openEntry(current.path),
|
|
59
|
+
},
|
|
60
|
+
{ role: "togglefullscreen", accelerator: "F11" },
|
|
61
|
+
{ type: "separator" },
|
|
62
|
+
{
|
|
63
|
+
id: "stage3d",
|
|
64
|
+
label: "Stage3D",
|
|
65
|
+
type: "checkbox",
|
|
66
|
+
checked: settings.stage3D,
|
|
67
|
+
click: (item) => {
|
|
68
|
+
if (!settings.setStage3D(item.checked)) {
|
|
69
|
+
refuse(
|
|
70
|
+
"The settings could not be saved.",
|
|
71
|
+
"The Stage3D choice holds until you quit.",
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
window?.webContents.reload();
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ type: "separator" },
|
|
79
|
+
{ role: "toggleDevTools" },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
|
|
84
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// The rules network.ts applies that need none of its state: Referers,
|
|
2
|
+
// redirects, ports, the certificate switch, and the small helpers its
|
|
3
|
+
// requests share. Without Electron, as network.ts is.
|
|
4
|
+
import { isIPv4 } from "node:net";
|
|
5
|
+
import * as tls from "node:tls";
|
|
6
|
+
import { addressClass, badPort } from "./addresses.ts";
|
|
7
|
+
import { type NetResponse, Refused } from "./network-types.ts";
|
|
8
|
+
import type { Requester } from "./policy.ts";
|
|
9
|
+
import { ProxyError } from "./proxy.ts";
|
|
10
|
+
|
|
11
|
+
const REDIRECTS = new Set([301, 302, 303, 307, 308]);
|
|
12
|
+
|
|
13
|
+
/** The system's trusted roots beside Node's, where this Node can tell them. */
|
|
14
|
+
export function defaultCa(): string[] | undefined {
|
|
15
|
+
const get = (tls as { getCACertificates?: (type: string) => string[] }).getCACertificates;
|
|
16
|
+
if (typeof get !== "function") {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
return [...new Set([...get("default"), ...get("system")])];
|
|
22
|
+
} catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The hosts --ignore-certificate-errors names, of the app's arguments up to
|
|
29
|
+
* an AIR application's own after "--": null without the switch; with it
|
|
30
|
+
* alone, every host; with `=a.test,b.test`, those, whatever their case.
|
|
31
|
+
* A host is a name or an address, with no port: every port of it.
|
|
32
|
+
*/
|
|
33
|
+
export function unverifiedHosts(argv: string[]): { all: boolean; hosts: string[] } | null {
|
|
34
|
+
const end = argv.indexOf("--");
|
|
35
|
+
const own = end < 0 ? argv : argv.slice(0, end);
|
|
36
|
+
let named = false;
|
|
37
|
+
let all = false;
|
|
38
|
+
const hosts: string[] = [];
|
|
39
|
+
for (const arg of own) {
|
|
40
|
+
if (arg === "--ignore-certificate-errors") {
|
|
41
|
+
named = true;
|
|
42
|
+
all = true;
|
|
43
|
+
} else if (arg.startsWith("--ignore-certificate-errors=")) {
|
|
44
|
+
// The switch with nothing named ignores nothing, rather than everything by a slip.
|
|
45
|
+
named = true;
|
|
46
|
+
for (const host of arg.slice(arg.indexOf("=") + 1).split(",")) {
|
|
47
|
+
if (host.trim() !== "") {
|
|
48
|
+
hosts.push(host.trim().toLowerCase());
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return named ? { all, hosts } : null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Whether `url` is potentially trustworthy, as the Secure Contexts
|
|
59
|
+
* specification has it for a Referer: https, or this machine by its
|
|
60
|
+
* loopback address or a name under localhost.
|
|
61
|
+
*/
|
|
62
|
+
function trustworthy(url: URL): boolean {
|
|
63
|
+
if (url.protocol === "https:") {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// A name with its root's dot is the same name; of IPv6 addresses the
|
|
68
|
+
// specification names ::1 alone, not an IPv4 loopback address inside one.
|
|
69
|
+
const host = bare(url.hostname).toLowerCase().replace(/\.$/, "");
|
|
70
|
+
return (
|
|
71
|
+
host === "localhost" ||
|
|
72
|
+
host.endsWith(".localhost") ||
|
|
73
|
+
host === "::1" ||
|
|
74
|
+
(isIPv4(host) && addressClass(host) === "loopback")
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The longest Referer sent whole, as the Referrer Policy specification has it. */
|
|
79
|
+
const MAX_REFERER = 4096;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The Referer a request from the SWF at `swf` to `target` carries, as
|
|
83
|
+
* browsers' strict-origin-when-cross-origin has it: the SWF's URL to its
|
|
84
|
+
* own origin, its origin alone to another, and nothing from https to what
|
|
85
|
+
* is not potentially trustworthy; a URL longer than 4096 characters goes
|
|
86
|
+
* as its origin.
|
|
87
|
+
*/
|
|
88
|
+
export function refererFor(swf: URL | null, target: URL): string | null {
|
|
89
|
+
if (!swf || (swf.protocol === "https:" && !trustworthy(target))) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const origin = `${swf.origin}/`;
|
|
94
|
+
if (swf.origin !== target.origin || swf.href.length > MAX_REFERER) {
|
|
95
|
+
return origin.length > MAX_REFERER ? null : origin;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return swf.href;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** `promise`, or a Refused once `signal` aborts: a request stops waiting on a shared policy. */
|
|
102
|
+
export function abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {
|
|
103
|
+
if (signal.aborted) {
|
|
104
|
+
return Promise.reject(new Refused("aborted"));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
const stop = () => reject(new Refused("aborted"));
|
|
109
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
110
|
+
promise.then(
|
|
111
|
+
(value) => {
|
|
112
|
+
signal.removeEventListener("abort", stop);
|
|
113
|
+
resolve(value);
|
|
114
|
+
},
|
|
115
|
+
(error) => {
|
|
116
|
+
signal.removeEventListener("abort", stop);
|
|
117
|
+
reject(error);
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** A host name without an IPv6 address's brackets. */
|
|
124
|
+
export function bare(host: string): string {
|
|
125
|
+
return host.replace(/^\[(.*)\]$/, "$1");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function checkPort(url: URL): void {
|
|
129
|
+
const port = Number(url.port || (url.protocol === "https:" ? 443 : 80));
|
|
130
|
+
if (badPort(port)) {
|
|
131
|
+
throw new Refused(`port ${port} is not for HTTP`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Where a redirect goes, if `response` is one, to http or https; one elsewhere is refused. */
|
|
136
|
+
export function redirectOf(url: URL, response: NetResponse): URL | null {
|
|
137
|
+
if (!REDIRECTS.has(response.status)) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const location = response.headers.find(([n]) => n.toLowerCase() === "location")?.[1];
|
|
142
|
+
if (location === undefined) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let next: URL;
|
|
147
|
+
try {
|
|
148
|
+
next = new URL(location, url);
|
|
149
|
+
} catch {
|
|
150
|
+
throw new Refused("a redirect to no URL");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (next.protocol !== "http:" && next.protocol !== "https:") {
|
|
154
|
+
throw new Refused(`a redirect to ${next.protocol}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (next.username || next.password) {
|
|
158
|
+
throw new Refused("a redirect to a URL with credentials");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
next.hash = "";
|
|
162
|
+
return next;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** `key`'s value in `cache`, made once with `make`; a cache grown past its bound starts again. */
|
|
166
|
+
export function cached<T>(
|
|
167
|
+
cache: Map<string, Promise<T>>,
|
|
168
|
+
key: string,
|
|
169
|
+
make: () => Promise<T>,
|
|
170
|
+
): Promise<T> {
|
|
171
|
+
let value = cache.get(key);
|
|
172
|
+
if (!value) {
|
|
173
|
+
if (cache.size >= 512) {
|
|
174
|
+
cache.clear();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
value = make();
|
|
178
|
+
cache.set(key, value);
|
|
179
|
+
// A failure, a proxy's, is not kept: the next request asks again.
|
|
180
|
+
const made = value;
|
|
181
|
+
made.catch(() => {
|
|
182
|
+
if (cache.get(key) === made) {
|
|
183
|
+
cache.delete(key);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Whether `error` is a refusal for a proxy that failed, not a server it did not reach. */
|
|
192
|
+
export function proxyFault(error: unknown): boolean {
|
|
193
|
+
const cause = (error as Error | null)?.cause;
|
|
194
|
+
return cause instanceof ProxyError && cause.fault;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export function describe(requester: Requester): string {
|
|
198
|
+
return requester.host === null ? 'a local SWF (domain="*")' : requester.host;
|
|
199
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// What network.ts's requests are and what bounds them: the request and
|
|
2
|
+
// response a SWF's fetch carries, the movie they are judged for, the
|
|
3
|
+
// limits, and the state one movie's requests share.
|
|
4
|
+
import type { AddressClass } from "./addresses.ts";
|
|
5
|
+
import type { Requester, SocketPolicy, UrlPolicy } from "./policy.ts";
|
|
6
|
+
import type { ProxyConfig } from "./proxy.ts";
|
|
7
|
+
|
|
8
|
+
export type Purpose = "movie" | "content" | "data" | "send";
|
|
9
|
+
|
|
10
|
+
export interface NetRequest {
|
|
11
|
+
url: string;
|
|
12
|
+
method: string;
|
|
13
|
+
headers: [string, string][];
|
|
14
|
+
body: Uint8Array | null;
|
|
15
|
+
purpose: Purpose;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the body of a response whose status is 400 or more is read
|
|
18
|
+
* too, which an AIR application's URLLoader and URLStream complete
|
|
19
|
+
* with; only an application is given it.
|
|
20
|
+
*/
|
|
21
|
+
errorBody?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NetResponse {
|
|
25
|
+
bytes: Uint8Array | null;
|
|
26
|
+
status: number;
|
|
27
|
+
headers: [string, string][];
|
|
28
|
+
/** Where redirects took it, where that differs from the URL asked for. */
|
|
29
|
+
url?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** A request refused, with why, for the terminal; the SWF sees a failed load. */
|
|
33
|
+
export class Refused extends Error {}
|
|
34
|
+
|
|
35
|
+
export interface Limits {
|
|
36
|
+
/** The longest URL. */
|
|
37
|
+
url: number;
|
|
38
|
+
/** The most headers a SWF sends, and their names' and values' length all told. */
|
|
39
|
+
headers: number;
|
|
40
|
+
headerBytes: number;
|
|
41
|
+
/** The largest body a SWF sends. */
|
|
42
|
+
body: number;
|
|
43
|
+
/** The largest response read: a SWF, a sound, a level's data. */
|
|
44
|
+
response: number;
|
|
45
|
+
/** The largest policy file, URL or socket. */
|
|
46
|
+
policy: number;
|
|
47
|
+
redirects: number;
|
|
48
|
+
/** From the request to its response's headers, and from one chunk of its body to the next. */
|
|
49
|
+
timeout: number;
|
|
50
|
+
/**
|
|
51
|
+
* How long a request may take all told, however its bytes trickle in, so
|
|
52
|
+
* that a server sending a byte a second holds no turn for long; a policy
|
|
53
|
+
* file's whole fetch takes `policyTimeout` at most, as a movie keeps it.
|
|
54
|
+
*/
|
|
55
|
+
deadline: number;
|
|
56
|
+
/** How long a policy file may take, and port 843's socket policy, which most servers lack. */
|
|
57
|
+
policyTimeout: number;
|
|
58
|
+
masterSocketTimeout: number;
|
|
59
|
+
/**
|
|
60
|
+
* The bytes a movie's responses may hold at once, all told: past it a
|
|
61
|
+
* response is refused, so many large ones together cannot take the
|
|
62
|
+
* main process's memory, as each alone may come near `response`.
|
|
63
|
+
*/
|
|
64
|
+
buffered: number;
|
|
65
|
+
/** Requests under way at once; the rest wait their turn, up to `queue`. */
|
|
66
|
+
concurrent: number;
|
|
67
|
+
queue: number;
|
|
68
|
+
/** Policy files a movie may name with Security.loadPolicyFile. */
|
|
69
|
+
policyFiles: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const LIMITS: Limits = {
|
|
73
|
+
url: 64 * 1024,
|
|
74
|
+
headers: 32,
|
|
75
|
+
headerBytes: 8 * 1024,
|
|
76
|
+
body: 32 * 1024 * 1024,
|
|
77
|
+
response: 128 * 1024 * 1024,
|
|
78
|
+
policy: 1024 * 1024,
|
|
79
|
+
redirects: 10,
|
|
80
|
+
timeout: 30_000,
|
|
81
|
+
deadline: 300_000,
|
|
82
|
+
policyTimeout: 10_000,
|
|
83
|
+
masterSocketTimeout: 3_000,
|
|
84
|
+
buffered: 256 * 1024 * 1024,
|
|
85
|
+
concurrent: 16,
|
|
86
|
+
queue: 1024,
|
|
87
|
+
policyFiles: 64,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The movie whose requests are judged: a remote SWF by its URL, a local
|
|
92
|
+
* one with networking, or an AIR application, whose sandbox reaches the
|
|
93
|
+
* network unjudged, as AIR's application sandbox does: any address, no
|
|
94
|
+
* policy file.
|
|
95
|
+
*/
|
|
96
|
+
export type Movie = { kind: "remote"; url: string } | { kind: "local" } | { kind: "application" };
|
|
97
|
+
|
|
98
|
+
export interface NetworkOptions {
|
|
99
|
+
/** A host name's addresses, in order of preference: the system's resolver by default. */
|
|
100
|
+
resolve?: (host: string) => Promise<string[]>;
|
|
101
|
+
/** Where an address is: addresses.ts's by default; null for one never reached. */
|
|
102
|
+
classify?: (address: string) => AddressClass | null;
|
|
103
|
+
/** The certificate authorities HTTPS trusts, in place of Node's and the system's. */
|
|
104
|
+
ca?: string | string[];
|
|
105
|
+
/**
|
|
106
|
+
* Hosts whose HTTPS certificate is not verified: a server with one it
|
|
107
|
+
* signed itself, as a developer's own has (--ignore-certificate-errors).
|
|
108
|
+
* None by default.
|
|
109
|
+
*/
|
|
110
|
+
unverified?: (host: string) => boolean;
|
|
111
|
+
limits?: Partial<Limits>;
|
|
112
|
+
/** Where a socket server keeps its master policy: 843. */
|
|
113
|
+
socketPolicyPort?: number;
|
|
114
|
+
/** What every connection goes through (--proxy); none by default. */
|
|
115
|
+
proxy?: ProxyConfig | null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** A remote movie once its SWF has come, where from. */
|
|
119
|
+
export interface Origin {
|
|
120
|
+
/** Its URL after redirects: its loaderInfo.url, and its Referer. */
|
|
121
|
+
url: URL;
|
|
122
|
+
requester: Requester;
|
|
123
|
+
rank: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface Pinned {
|
|
127
|
+
address: string;
|
|
128
|
+
rank: number;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** What one movie's requests share, and lose as the next opens. */
|
|
132
|
+
/** What one request's responses hold of its movie's `buffered`, given back as it is answered. */
|
|
133
|
+
export interface Budget {
|
|
134
|
+
session: Session;
|
|
135
|
+
taken: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface Session {
|
|
139
|
+
movie: Movie;
|
|
140
|
+
origin: Origin | null;
|
|
141
|
+
abort: AbortController;
|
|
142
|
+
/** URL and socket policies, by where they came from and the address they came from. */
|
|
143
|
+
policies: Map<string, Promise<UrlPolicy | null>>;
|
|
144
|
+
socketPolicies: Map<string, Promise<SocketPolicy | null>>;
|
|
145
|
+
/** What Security.loadPolicyFile named: http(s) URLs, and xmlsocket "host:port"s. */
|
|
146
|
+
urlPolicyFiles: URL[];
|
|
147
|
+
socketPolicyFiles: { host: string; port: number }[];
|
|
148
|
+
/** The bytes its responses hold now, of `buffered`. */
|
|
149
|
+
buffered: number;
|
|
150
|
+
}
|