@nativewindow/webview 0.1.1

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/index.js ADDED
@@ -0,0 +1,406 @@
1
+ import { NativeWindow as NativeWindow$1, init, pumpEvents } from "../native-window.js";
2
+ import { checkRuntime, ensureRuntime, loadHtmlOrigin } from "../native-window.js";
3
+ let _pump = null;
4
+ let _windowCount = 0;
5
+ function ensureInit() {
6
+ if (_pump) return;
7
+ init();
8
+ _pump = setInterval(() => {
9
+ try {
10
+ pumpEvents();
11
+ } catch (e) {
12
+ console.error("[native-window] pumpEvents() error:", e);
13
+ }
14
+ }, 16);
15
+ }
16
+ function stopPump() {
17
+ if (_pump) {
18
+ clearInterval(_pump);
19
+ _pump = null;
20
+ }
21
+ }
22
+ class NativeWindow {
23
+ /** @internal */
24
+ _native;
25
+ /** @internal */
26
+ _closed = false;
27
+ /** @internal */
28
+ _unsafe;
29
+ /** @internal */
30
+ _devtools;
31
+ constructor(options) {
32
+ ensureInit();
33
+ _windowCount++;
34
+ this._native = new NativeWindow$1(options);
35
+ this._native.onClose(() => this._handleClose());
36
+ }
37
+ /** @internal */
38
+ _handleClose() {
39
+ if (this._closed) return;
40
+ this._closed = true;
41
+ _windowCount--;
42
+ this._userCloseCallback?.();
43
+ if (_windowCount <= 0) {
44
+ _windowCount = 0;
45
+ setTimeout(() => stopPump(), 200);
46
+ }
47
+ }
48
+ /**
49
+ * Throws if the window has been closed.
50
+ * @internal
51
+ */
52
+ _ensureOpen() {
53
+ if (this._closed) {
54
+ throw new Error("Window is closed");
55
+ }
56
+ }
57
+ // ---- onClose with user callback support ----
58
+ _userCloseCallback;
59
+ /**
60
+ * Register a handler for the window close event.
61
+ * The pump is automatically stopped when all windows are closed.
62
+ *
63
+ * Calling this multiple times replaces the previous handler.
64
+ */
65
+ onClose(callback) {
66
+ if (this._userCloseCallback) {
67
+ console.warn(
68
+ "NativeWindow: onClose() called multiple times. The previous handler will be replaced."
69
+ );
70
+ }
71
+ this._userCloseCallback = callback;
72
+ }
73
+ // ---- Getters ----
74
+ /** Unique window ID */
75
+ get id() {
76
+ return this._native.id;
77
+ }
78
+ // ---- Content loading ----
79
+ loadUrl(url) {
80
+ this._ensureOpen();
81
+ this._native.loadUrl(url);
82
+ }
83
+ /**
84
+ * Load raw HTML content into the webview.
85
+ *
86
+ * @security **Injection risk.** Never interpolate unsanitized user input
87
+ * into HTML strings. Use a dedicated sanitization library such as
88
+ * [DOMPurify](https://github.com/cure53/DOMPurify) or
89
+ * [sanitize-html](https://github.com/apostrophecms/sanitize-html) to
90
+ * sanitize untrusted content before embedding it.
91
+ */
92
+ loadHtml(html) {
93
+ this._ensureOpen();
94
+ this._native.loadHtml(html);
95
+ }
96
+ postMessage(message) {
97
+ this._ensureOpen();
98
+ this._native.postMessage(message);
99
+ }
100
+ // ---- Unsafe operations ----
101
+ /**
102
+ * Namespace for operations that require extra care to avoid injection risks.
103
+ * Methods under `unsafe` execute arbitrary code in the webview context.
104
+ *
105
+ * @security Never pass unsanitized user input to these methods.
106
+ * Use {@link sanitizeForJs} to escape strings before embedding them in
107
+ * script code.
108
+ */
109
+ get unsafe() {
110
+ this._ensureOpen();
111
+ if (!this._unsafe) {
112
+ this._unsafe = {
113
+ evaluateJs: (script) => {
114
+ this._ensureOpen();
115
+ this._native.evaluateJs(script);
116
+ }
117
+ };
118
+ }
119
+ return this._unsafe;
120
+ }
121
+ // ---- Devtools ----
122
+ /**
123
+ * Namespace for controlling the browser devtools panel.
124
+ * Requires `devtools: true` in {@link WindowOptions} at window creation.
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * const win = new NativeWindow({ devtools: true });
129
+ * win.devtools.open();
130
+ * console.log(win.devtools.isOpen()); // true
131
+ * win.devtools.close();
132
+ * ```
133
+ */
134
+ get devtools() {
135
+ this._ensureOpen();
136
+ if (!this._devtools) {
137
+ this._devtools = {
138
+ open: () => {
139
+ this._ensureOpen();
140
+ this._native.openDevtools();
141
+ },
142
+ close: () => {
143
+ this._ensureOpen();
144
+ this._native.closeDevtools();
145
+ },
146
+ isOpen: () => {
147
+ this._ensureOpen();
148
+ return this._native.isDevtoolsOpen();
149
+ }
150
+ };
151
+ }
152
+ return this._devtools;
153
+ }
154
+ // ---- Window control ----
155
+ setTitle(title) {
156
+ this._ensureOpen();
157
+ this._native.setTitle(title);
158
+ }
159
+ setSize(width, height) {
160
+ this._ensureOpen();
161
+ this._native.setSize(width, height);
162
+ }
163
+ setMinSize(width, height) {
164
+ this._ensureOpen();
165
+ this._native.setMinSize(width, height);
166
+ }
167
+ setMaxSize(width, height) {
168
+ this._ensureOpen();
169
+ this._native.setMaxSize(width, height);
170
+ }
171
+ setPosition(x, y) {
172
+ this._ensureOpen();
173
+ this._native.setPosition(x, y);
174
+ }
175
+ setResizable(resizable) {
176
+ this._ensureOpen();
177
+ this._native.setResizable(resizable);
178
+ }
179
+ setDecorations(decorations) {
180
+ this._ensureOpen();
181
+ this._native.setDecorations(decorations);
182
+ }
183
+ setAlwaysOnTop(alwaysOnTop) {
184
+ this._ensureOpen();
185
+ this._native.setAlwaysOnTop(alwaysOnTop);
186
+ }
187
+ /**
188
+ * Set the window icon from a PNG or ICO file path.
189
+ * On macOS this is silently ignored (macOS doesn't support per-window icons).
190
+ * Relative paths resolve from the working directory.
191
+ */
192
+ setIcon(path) {
193
+ this._ensureOpen();
194
+ this._native.setIcon(path);
195
+ }
196
+ // ---- Window state ----
197
+ show() {
198
+ this._ensureOpen();
199
+ this._native.show();
200
+ }
201
+ hide() {
202
+ this._ensureOpen();
203
+ this._native.hide();
204
+ }
205
+ close() {
206
+ this._ensureOpen();
207
+ this._native.close();
208
+ }
209
+ focus() {
210
+ this._ensureOpen();
211
+ this._native.focus();
212
+ }
213
+ maximize() {
214
+ this._ensureOpen();
215
+ this._native.maximize();
216
+ }
217
+ minimize() {
218
+ this._ensureOpen();
219
+ this._native.minimize();
220
+ }
221
+ unmaximize() {
222
+ this._ensureOpen();
223
+ this._native.unmaximize();
224
+ }
225
+ reload() {
226
+ this._ensureOpen();
227
+ this._native.reload();
228
+ }
229
+ // ---- Event handlers ----
230
+ /**
231
+ * Register a handler for messages from the webview.
232
+ *
233
+ * @security **No origin filtering.** The raw `onMessage` API does not
234
+ * enforce origin restrictions. If your webview navigates to untrusted
235
+ * URLs, validate the `sourceUrl` parameter before processing messages.
236
+ * For automatic origin filtering, use `createChannel()` with the
237
+ * `trustedOrigins` option from `native-window-ipc`.
238
+ *
239
+ * @security **No rate limiting.** Messages from the webview are delivered
240
+ * without throttling. A malicious page can flood the host with messages.
241
+ * Consider implementing application-level rate limiting if loading
242
+ * untrusted content.
243
+ */
244
+ onMessage(callback) {
245
+ this._ensureOpen();
246
+ this._native.onMessage(callback);
247
+ }
248
+ onResize(callback) {
249
+ this._ensureOpen();
250
+ this._native.onResize(callback);
251
+ }
252
+ onMove(callback) {
253
+ this._ensureOpen();
254
+ this._native.onMove(callback);
255
+ }
256
+ onFocus(callback) {
257
+ this._ensureOpen();
258
+ this._native.onFocus(callback);
259
+ }
260
+ onBlur(callback) {
261
+ this._ensureOpen();
262
+ this._native.onBlur(callback);
263
+ }
264
+ onPageLoad(callback) {
265
+ this._ensureOpen();
266
+ this._native.onPageLoad(callback);
267
+ }
268
+ onTitleChanged(callback) {
269
+ this._ensureOpen();
270
+ this._native.onTitleChanged(callback);
271
+ }
272
+ onReload(callback) {
273
+ this._ensureOpen();
274
+ this._native.onReload(callback);
275
+ }
276
+ /**
277
+ * Register a handler for blocked navigation events.
278
+ * Fired when a navigation is blocked by the {@link WindowOptions.allowedHosts}
279
+ * restriction. Receives the URL that was blocked.
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * win.onNavigationBlocked((url) => {
284
+ * console.log("Blocked navigation to:", url);
285
+ * });
286
+ * ```
287
+ */
288
+ onNavigationBlocked(callback) {
289
+ this._ensureOpen();
290
+ this._native.onNavigationBlocked(callback);
291
+ }
292
+ // ---- Cookie access ----
293
+ /**
294
+ * Validate and parse a raw cookies JSON array from the native layer.
295
+ * Returns a cleaned {@link CookieInfo} array or `null` if the payload
296
+ * is malformed.
297
+ *
298
+ * @internal
299
+ */
300
+ _validateCookies(raw) {
301
+ let parsed;
302
+ try {
303
+ parsed = JSON.parse(raw);
304
+ } catch {
305
+ return null;
306
+ }
307
+ if (!Array.isArray(parsed)) return null;
308
+ const cookies = [];
309
+ for (const item of parsed) {
310
+ if (typeof item !== "object" || item === null) continue;
311
+ const obj = item;
312
+ if (typeof obj.name !== "string" || typeof obj.value !== "string") {
313
+ continue;
314
+ }
315
+ if (typeof obj.domain !== "string" || typeof obj.path !== "string") {
316
+ continue;
317
+ }
318
+ if (typeof obj.httpOnly !== "boolean" || typeof obj.secure !== "boolean") {
319
+ continue;
320
+ }
321
+ if (typeof obj.sameSite !== "string" || typeof obj.expires !== "number") {
322
+ continue;
323
+ }
324
+ cookies.push({
325
+ name: obj.name,
326
+ value: obj.value,
327
+ domain: obj.domain,
328
+ path: obj.path,
329
+ httpOnly: obj.httpOnly,
330
+ secure: obj.secure,
331
+ sameSite: obj.sameSite,
332
+ expires: obj.expires
333
+ });
334
+ }
335
+ return cookies;
336
+ }
337
+ /**
338
+ * Query cookies from the native cookie store.
339
+ *
340
+ * Returns a Promise that resolves with validated {@link CookieInfo} objects,
341
+ * including `HttpOnly` cookies that are invisible to `document.cookie`.
342
+ *
343
+ * - **macOS**: Uses `WKHTTPCookieStore.getAllCookies` with client-side
344
+ * URL filtering (domain + path match).
345
+ * - **Windows**: Uses `ICoreWebView2CookieManager.GetCookies` which
346
+ * filters by URI natively.
347
+ *
348
+ * @param url If provided, only cookies matching this URL are returned.
349
+ * If omitted, all cookies in the webview's cookie store are returned.
350
+ *
351
+ * @example
352
+ * ```ts
353
+ * const cookies = await win.getCookies("https://example.com");
354
+ * const session = cookies.find((c) => c.name === "session_id");
355
+ * if (session) console.log("Session:", session.value, "HttpOnly:", session.httpOnly);
356
+ * ```
357
+ */
358
+ getCookies(url) {
359
+ this._ensureOpen();
360
+ return new Promise((resolve, reject) => {
361
+ const timeout = setTimeout(() => {
362
+ reject(new Error("getCookies() timed out after 10 seconds"));
363
+ }, 1e4);
364
+ this._native.onCookies((raw) => {
365
+ clearTimeout(timeout);
366
+ const validated = this._validateCookies(raw);
367
+ if (validated) {
368
+ resolve(validated);
369
+ } else {
370
+ reject(new Error("Failed to parse cookie response"));
371
+ }
372
+ });
373
+ this._native.getCookies(url);
374
+ });
375
+ }
376
+ /**
377
+ * Clear cookies from the native cookie store.
378
+ *
379
+ * - If `host` is provided, only cookies whose domain matches that host
380
+ * are deleted (e.g. `"example.com"` deletes `.example.com` cookies).
381
+ * - If omitted, all cookies in the webview's cookie store are cleared.
382
+ *
383
+ * @example
384
+ * ```ts
385
+ * // Clear all cookies
386
+ * win.clearCookies();
387
+ *
388
+ * // Clear cookies for a specific host
389
+ * win.clearCookies("example.com");
390
+ * ```
391
+ */
392
+ clearCookies(host) {
393
+ this._ensureOpen();
394
+ this._native.clearCookies(host);
395
+ }
396
+ }
397
+ function sanitizeForJs(input) {
398
+ return JSON.stringify(input).slice(1, -1).replace(/<\/script>/gi, "<\\/script>").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
399
+ }
400
+ export {
401
+ NativeWindow,
402
+ checkRuntime,
403
+ ensureRuntime,
404
+ loadHtmlOrigin,
405
+ sanitizeForJs
406
+ };
@@ -0,0 +1,264 @@
1
+ /* eslint-disable */
2
+ // Auto-generated type declarations for the native addon.
3
+ // These will be overwritten by `napi build` but serve as
4
+ // a reference during development.
5
+
6
+ export interface WindowOptions {
7
+ /** Window title. Default: "" */
8
+ title?: string;
9
+ /** Inner width in logical pixels. Default: 800 */
10
+ width?: number;
11
+ /** Inner height in logical pixels. Default: 600 */
12
+ height?: number;
13
+ /** X position in screen coordinates */
14
+ x?: number;
15
+ /** Y position in screen coordinates */
16
+ y?: number;
17
+ /** Minimum inner width */
18
+ minWidth?: number;
19
+ /** Minimum inner height */
20
+ minHeight?: number;
21
+ /** Maximum inner width */
22
+ maxWidth?: number;
23
+ /** Maximum inner height */
24
+ maxHeight?: number;
25
+ /** Allow resizing. Default: true */
26
+ resizable?: boolean;
27
+ /** Show window decorations (title bar, borders). Default: true */
28
+ decorations?: boolean;
29
+ /** Transparent window background. Default: false */
30
+ transparent?: boolean;
31
+ /** Always on top of other windows. Default: false */
32
+ alwaysOnTop?: boolean;
33
+ /** Initially visible. Default: true */
34
+ visible?: boolean;
35
+ /** Enable devtools. Default: false */
36
+ devtools?: boolean;
37
+ /**
38
+ * Content Security Policy to inject at document start.
39
+ * When set, a `<meta http-equiv="Content-Security-Policy">` tag is injected
40
+ * before any page scripts run.
41
+ *
42
+ * **Limitation:** The CSP is applied via a `<meta>` tag at `DOMContentLoaded`,
43
+ * so scripts executing before that event are not restricted. Meta-tag CSP also
44
+ * cannot enforce `frame-ancestors` or `report-uri` directives. For stronger
45
+ * enforcement, serve pages via the custom protocol handler with a real HTTP
46
+ * `Content-Security-Policy` header.
47
+ *
48
+ * @example `"default-src 'self'; script-src 'self' 'unsafe-inline'"`
49
+ */
50
+ csp?: string;
51
+ /**
52
+ * Trusted origins for IPC messages at the native layer.
53
+ * When set, only messages whose source URL origin matches one of these
54
+ * entries are forwarded to the host. Messages from other origins are
55
+ * silently dropped.
56
+ *
57
+ * Each entry should be a full origin string (scheme + host + optional port),
58
+ * e.g. `"https://example.com"`. No trailing slash.
59
+ *
60
+ * @security Defense-in-depth. For application-level origin filtering,
61
+ * use `trustedOrigins` in `createChannel()` from `native-window-ipc`.
62
+ *
63
+ * @example `["https://myapp.com", "https://cdn.myapp.com"]`
64
+ */
65
+ trustedOrigins?: string[];
66
+ /**
67
+ * Allowed hosts for navigation restriction.
68
+ * When set and non-empty, ALL navigations (including `loadUrl()`, link
69
+ * clicks, form submissions, and redirects) are restricted to URLs whose
70
+ * host matches one of these patterns.
71
+ *
72
+ * Supports wildcard prefixes: `"*.example.com"` matches any subdomain
73
+ * of `example.com` and `example.com` itself.
74
+ *
75
+ * Internal navigations (`about:blank`, `loadHtml()` content) are always
76
+ * permitted. When unset or empty, all hosts are allowed.
77
+ *
78
+ * @example `["myapp.com", "*.cdn.myapp.com"]`
79
+ */
80
+ allowedHosts?: string[];
81
+ /**
82
+ * Allow the webview to access the camera when requested.
83
+ * Default: false (all camera requests are denied).
84
+ * @note Not yet enforced in the wry backend. The OS default (prompt user) applies.
85
+ */
86
+ allowCamera?: boolean;
87
+ /**
88
+ * Allow the webview to access the microphone when requested.
89
+ * Default: false (all microphone requests are denied).
90
+ * @note Not yet enforced in the wry backend. The OS default (prompt user) applies.
91
+ */
92
+ allowMicrophone?: boolean;
93
+ /**
94
+ * Allow the webview to use the File System Access API
95
+ * (`showOpenFilePicker`, `showSaveFilePicker`, `showDirectoryPicker`).
96
+ * Default: false (all file system access requests are denied).
97
+ * @note Not yet enforced in the wry backend. The OS default applies.
98
+ */
99
+ allowFileSystem?: boolean;
100
+
101
+ /**
102
+ * Path to a PNG or ICO file for the window icon (title bar).
103
+ * On macOS this option is silently ignored (macOS doesn't support
104
+ * per-window icons). Relative paths resolve from the working directory.
105
+ */
106
+ icon?: string;
107
+ /**
108
+ * Run the webview in incognito (private) mode.
109
+ * When `true`, no cookies, cache, or other browsing data are persisted to disk.
110
+ * Each window starts with a clean, isolated session and all data is discarded
111
+ * when the window closes.
112
+ *
113
+ * Platform notes:
114
+ * - **macOS**: Uses `WKWebsiteDataStore.nonPersistentDataStore()` (WKWebView).
115
+ * - **Windows**: Enables `IsInPrivateModeEnabled` on the WebView2 controller.
116
+ * - **Linux**: Uses a temporary in-memory WebContext (no persistent storage).
117
+ *
118
+ * Default: `false`
119
+ */
120
+ incognito?: boolean;
121
+ }
122
+
123
+ export class NativeWindow {
124
+ constructor(options?: WindowOptions);
125
+
126
+ /** Unique window ID */
127
+ readonly id: number;
128
+
129
+ // Content loading
130
+ loadUrl(url: string): void;
131
+ loadHtml(html: string): void;
132
+ evaluateJs(script: string): void;
133
+ postMessage(message: string): void;
134
+
135
+ // Window control
136
+ setTitle(title: string): void;
137
+ setSize(width: number, height: number): void;
138
+ setMinSize(width: number, height: number): void;
139
+ setMaxSize(width: number, height: number): void;
140
+ setPosition(x: number, y: number): void;
141
+ setResizable(resizable: boolean): void;
142
+ setDecorations(decorations: boolean): void;
143
+ setAlwaysOnTop(alwaysOnTop: boolean): void;
144
+ /** Set the window icon from a PNG or ICO file path. Ignored on macOS. */
145
+ setIcon(path: string): void;
146
+
147
+ // Window state
148
+ show(): void;
149
+ hide(): void;
150
+ close(): void;
151
+ focus(): void;
152
+ maximize(): void;
153
+ minimize(): void;
154
+ unmaximize(): void;
155
+ reload(): void;
156
+
157
+ // Event handlers
158
+ onMessage(callback: (message: string, sourceUrl: string) => void): void;
159
+ onClose(callback: () => void): void;
160
+ onResize(callback: (width: number, height: number) => void): void;
161
+ onMove(callback: (x: number, y: number) => void): void;
162
+ onFocus(callback: () => void): void;
163
+ onBlur(callback: () => void): void;
164
+ onPageLoad(callback: (event: "started" | "finished", url: string) => void): void;
165
+ onTitleChanged(callback: (title: string) => void): void;
166
+ onReload(callback: () => void): void;
167
+ onNavigationBlocked(callback: (url: string) => void): void;
168
+
169
+ // Cookie access
170
+ getCookies(url?: string): void;
171
+ onCookies(callback: (cookies: string) => void): void;
172
+ clearCookies(host?: string): void;
173
+
174
+ // Devtools
175
+ /** Open the browser devtools panel. Requires `devtools: true` in options. */
176
+ openDevtools(): void;
177
+ /** Close the browser devtools panel. */
178
+ closeDevtools(): void;
179
+ /** Check whether the devtools panel is currently open. */
180
+ isDevtoolsOpen(): boolean;
181
+ }
182
+
183
+ /** Initialize the native window system. Must be called once before creating any windows. */
184
+ export function init(): void;
185
+
186
+ /** Process pending native UI events. Call periodically (~16ms) to keep windows responsive. */
187
+ export function pumpEvents(): void;
188
+
189
+ /** Information about the native webview runtime. */
190
+ export interface RuntimeInfo {
191
+ /** Whether the webview runtime is available. */
192
+ available: boolean;
193
+ /** The version string of the runtime, if detected. */
194
+ version?: string;
195
+ /** The current platform: "macos", "windows", "linux", or "unsupported". */
196
+ platform: "macos" | "windows" | "linux" | "unsupported";
197
+ }
198
+
199
+ /**
200
+ * Check if the native webview runtime is available.
201
+ *
202
+ * - **macOS**: Always returns available (WKWebView is a system framework).
203
+ * - **Windows**: Detects WebView2 via `GetAvailableCoreWebView2BrowserVersionString`.
204
+ * - **Linux**: Always returns available (WebKitGTK is required at build time).
205
+ * - **Other**: Returns `{ available: false, platform: "unsupported" }`.
206
+ */
207
+ export function checkRuntime(): RuntimeInfo;
208
+
209
+ /**
210
+ * Ensure the native webview runtime is available, installing it if necessary.
211
+ *
212
+ * - **macOS**: Returns immediately (WKWebView is always available).
213
+ * - **Windows**: If WebView2 is missing, downloads the Evergreen Bootstrapper
214
+ * (~2MB) from Microsoft and runs it silently. Throws on failure.
215
+ * - **Linux**: Returns immediately (WebKitGTK is required at build time).
216
+ * - **Other**: Throws an error.
217
+ *
218
+ * @security This function downloads and executes a Microsoft-signed binary
219
+ * from the internet (Windows only). Authenticode signature verification is
220
+ * performed before execution; unverified binaries are never run.
221
+ *
222
+ * **Do not call in an elevated (Administrator) context without explicit user
223
+ * consent.** The silent installer applies system-wide. Prefer calling
224
+ * {@link checkRuntime} first to avoid unnecessary network requests when the
225
+ * runtime is already present.
226
+ */
227
+ export function ensureRuntime(): RuntimeInfo;
228
+
229
+ /**
230
+ * Escape a string for safe embedding inside a JavaScript string literal.
231
+ * Handles backslashes, quotes, newlines, null bytes, closing `</script>` tags,
232
+ * and Unicode line/paragraph separators (U+2028, U+2029).
233
+ *
234
+ * @security Use this when interpolating untrusted input into `win.unsafe.evaluateJs()` calls.
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * import { sanitizeForJs } from "native-window";
239
+ *
240
+ * const userInput = 'He said "hello"\n<script>alert(1)</script>';
241
+ * win.unsafe.evaluateJs(`display("${sanitizeForJs(userInput)}")`);
242
+ * ```
243
+ */
244
+ export function sanitizeForJs(input: string): string;
245
+
246
+ /**
247
+ * Returns the origin of pages loaded via `loadHtml()`.
248
+ *
249
+ * Use this in `trustedOrigins` to restrict IPC messages to only accept
250
+ * messages from `loadHtml()` content.
251
+ *
252
+ * - macOS/Linux: `"nativewindow://localhost"`
253
+ * - Windows: `"https://nativewindow.localhost"`
254
+ *
255
+ * @example
256
+ * ```ts
257
+ * import { NativeWindow, loadHtmlOrigin } from "@nativewindow/webview";
258
+ *
259
+ * const win = new NativeWindow({
260
+ * trustedOrigins: [loadHtmlOrigin()],
261
+ * });
262
+ * ```
263
+ */
264
+ export function loadHtmlOrigin(): string;