From 2f836ecde2f6bd31d8432bbcfd422fc9df4bad75 Mon Sep 17 00:00:00 2001 From: Remy Blank Date: Thu, 19 Sep 2024 18:18:02 +0200 Subject: [PATCH] Allow more flexibility in choosing which requests get the COI workaround. --- package-lock.json | 27 ----------------- package.json | 1 - tdoc/common/__init__.py | 12 ++++---- tdoc/common/static/tdoc-coi.js | 54 ++++++++++++++++++++++++++++++++++ tools/hatch_hooks.py | 1 - 5 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 tdoc/common/static/tdoc-coi.js diff --git a/package-lock.json b/package-lock.json index 762d58a..bce4fed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,6 @@ "@codemirror/view": "^6.33.0", "@rollup/plugin-node-resolve": "^15.2.3", "@sqlite.org/sqlite-wasm": "^3.46.1-build1", - "mini-coi": "^0.4.2", "rollup": "^4.21.2", "rollup-plugin-license": "^3.5.2" } @@ -733,19 +732,6 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/mini-coi": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/mini-coi/-/mini-coi-0.4.2.tgz", - "integrity": "sha512-9HPJlEWRjdmpplnGHEV6+0PYQMTQzsRtVwWROvBck1tKkBZRVf7Y6jriVgoNcDWc2iu1QC9AozjHrqUuwMNvpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "static-handler": "^0.5.3" - }, - "bin": { - "mini-coi": "mini-cli.js" - } - }, "node_modules/moment": { "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", @@ -962,19 +948,6 @@ "spdx-ranges": "^2.0.0" } }, - "node_modules/static-handler": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/static-handler/-/static-handler-0.5.3.tgz", - "integrity": "sha512-VSg7+Dd6HkgwjdJ9nRN2mmBZkP/u6ICA7RQuLqBFi3KdzWe9BEQXhMiDw3A8TYcllshIVn5nNP5fRcicOPZhzQ==", - "dev": true, - "license": "ISC", - "bin": { - "static-handler": "static-handler.cjs" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/style-mod": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", diff --git a/package.json b/package.json index 7564da9..55db712 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "@codemirror/view": "^6.33.0", "@rollup/plugin-node-resolve": "^15.2.3", "@sqlite.org/sqlite-wasm": "^3.46.1-build1", - "mini-coi": "^0.4.2", "rollup": "^4.21.2", "rollup-plugin-license": "^3.5.2" }, diff --git a/tdoc/common/__init__.py b/tdoc/common/__init__.py index fd50fd6..6eb8aad 100644 --- a/tdoc/common/__init__.py +++ b/tdoc/common/__init__.py @@ -96,7 +96,7 @@ def on_builder_inited(app): # The file must be at the root of the website, to avoid limiting the scope # of the service worker to _static. - fileutil.copy_asset_file(_common / 'static.gen' / 'mini-coi.js', + fileutil.copy_asset_file(_common / 'static' / 'tdoc-coi.js', app.builder.outdir, force=True) @@ -106,15 +106,15 @@ def on_html_page_context(app, page, template, context, doctree): license_url = app.config.license_url if license_url: context['license_url'] = license_url - # Work around Cross-Origin Isoaltion issues when the corresponding headers - # cannot be set server-side. - app.add_js_file('../mini-coi.js', priority=0) + # Work around Cross-Origin Isolation issues when the relevant headers cannot + # be set server-side. + app.add_js_file('../tdoc-coi.js', priority=0, + scope=context['pathto']('', resource=True)) + # Add language-specific .js files. if doctree: for lang in sorted(Exec.find_nodes(doctree)): app.add_js_file(f'tdoc-{lang}.js', type='module') - # TODO: Add Cross-Origin-*-Policy headers in the dev server - # TODO: Work around inability to specify headers on GitHub Pages def add_reload_js(app, page, template, context, doctree): diff --git a/tdoc/common/static/tdoc-coi.js b/tdoc/common/static/tdoc-coi.js new file mode 100644 index 0000000..a1db039 --- /dev/null +++ b/tdoc/common/static/tdoc-coi.js @@ -0,0 +1,54 @@ +// Copyright 2024 Remy Blank +// SPDX-License-Identifier: MIT + +(({document: doc, navigator: {serviceWorker: workers}}) => { + if (!doc) { + // Running in the service worker. Capture fetch() requests and add the + // relevant headers. + addEventListener('install', () => skipWaiting()); + addEventListener('activate', e => e.waitUntil(clients.claim())); + addEventListener('fetch', e => { + const req = e.request; + if (req.cache === 'only-if-cached' && req.mode !== 'same-origin') { + return; + } + e.respondWith((async () => { + const resp = await fetch(req); + const {status, statusText, body} = resp; + if (!status || status >= 400) return resp; + const headers = new Headers(resp.headers); + headers.set('Cross-Origin-Embedder-Policy', 'require-corp'); + headers.set('Cross-Origin-Opener-Policy', 'same-origin'); + headers.set('Cross-Origin-Resource-Policy', 'cross-origin'); + return new Response(resp.body, {status, statusText, headers}); + })()); + }); + return; + } + + // Running in the main thread. Register the service worker if necessary. + if (crossOriginIsolated) { + console.info("[t-doc] Already cross-origin isolated"); + return; + } + if (!isSecureContext) { + console.warn("[t-doc] Not a secure context; COI workaround disabled"); + return; + } + if (!workers) { + console.warn( + "[t-doc] No service worker container; COI workaround disabled"); + return; + } + const script = doc.currentScript; + workers.register(script.src, {scope: script.getAttribute('scope')}) + .then(reg => { + console.info('[t-doc] COI service worker registered'); + reg.addEventListener('updatefound', () => location.reload()); + if (reg.active && !workers.controller) location.reload(); + }) + .catch(e => { + console.error( + `[t-doc] Failed to register COI service worker: ${e}`); + }); +})(self); diff --git a/tools/hatch_hooks.py b/tools/hatch_hooks.py index 96abcd3..4fe456b 100644 --- a/tools/hatch_hooks.py +++ b/tools/hatch_hooks.py @@ -34,7 +34,6 @@ def initialize(self, version, build_data): self.app.display_info("Generating files") os.makedirs(static_gen, exist_ok=True) node_modules = root / 'node_modules' - shutil.copy2(node_modules / 'mini-coi' / 'mini-coi.js', static_gen) shutil.copytree(node_modules / '@sqlite.org' / 'sqlite-wasm' / 'sqlite-wasm' / 'jswasm', static_gen, symlinks=True, dirs_exist_ok=True)