feat(download): make the package's own .elpx download button work in embeds - #156
Conversation
…embeds The download-source-file iDevice rebuilds the .elpx in the browser. In an embed that never saved a file: the content CSP blocks fflate's blob: workers (exelearning/exelearning#2488) and the iframe sandbox drops the download. While the embed offers the .elpx, route the package's downloadElpx() to the original attachment; otherwise let the rebuild finish by allowing blob: workers and downloads in the frame.
Test in WordPress PlaygroundTest the plugin with the code from this branch:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #156 +/- ##
============================================
- Coverage 96.43% 96.42% -0.01%
Complexity 806 806
============================================
Files 36 36
Lines 4238 4256 +18
============================================
+ Hits 4087 4104 +17
- Misses 151 152 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Refs exelearning/exelearning#2488. Same fix as exelearning/omeka-s-exelearning#63; complements exelearning/exelearning#2489.
Thanks to smorros for reporting it and to @biyayo for forwarding it.
Problem
In a published package, the download-source-file iDevice button ("Download .elpx" inside the content) never saves a file in a WordPress embed. It fails in two independent places:
ExeLearning_Content_Proxyserves HTML withscript-src 'self' 'unsafe-inline' 'unsafe-eval'and noworker-src. The button rebuilds the.elpxwith the asyncfflate.zip(), which compresses inblob:workers. The workers are blocked, fflate's callback never fires, and the button stays at "Processing... 100%".sandbox="allow-scripts allow-same-origin allow-popups", withoutallow-downloads. Even once the rebuild completes (fix(elpx-download): fall back to zipSync when the CSP blocks blob: workers exelearning#2489 adds azipSyncfallback), Chrome drops the download: "Download is disallowed. The frame initiating or instantiating the download is sandboxed, but the flag 'allow-downloads' is not set". I reproduced this on the Omeka S equivalent, which uses the same CSP and sandbox.Even when it works, rebuilding refetches the whole package and holds it in memory 2–3 times over. Packages exported before exelearning/exelearning#2196 also rebuild without
content.xml, so the result cannot be re-imported.Change
Serve the original (
assets/js/wp-exe-download.js). While an embed's toolbar offers an enabled.elpxitem, the script replaces the package's globaldownloadElpx()(called by the iDevice's inlineonclick) with one that downloads the original attachment. It goes through the samedownloadFormat()path as the toolbar button..exelearning-preview/.exelearning-block-frontend).loadlistener reapplies it on every page the frame navigates to, andinit()covers frames that loaded earlier.exelearning_content_origin) raises an access error, which is caught, and the package keeps its own download.Let the rebuild finish when routing does not apply. That covers the
.elpxnot offered (for exampleshow_downloadoff, the default), "Open in new tab", or a cross-origin content origin.worker-src 'self' blob:(includes/class-content-proxy.php).allow-downloads.Neither relaxation grants package scripts anything new. They already run with
'unsafe-inline'/'unsafe-eval'in the site origin and can start downloads through the same-origin parent. The decision is recorded in ADR-156-01.Tests
tests/js/wp_exe_download.test.js: new routing the package's own .elpx button block. It covers the original download, block embeds, in-frame navigation, the.elpxnot offered or disabled, packages without the button, a cross-origin frame, and several embeds on one page. 4 of these tests fail onmain.allow-downloads. 3 of these tests fail onmain.