RPGアツマールで、WebWorker が動かない
HTML5な自作SRPGをRPGアツマールに投稿してみたら、何もしてないのに動いた!
https://game.nicovideo.jp/atsumaru/games/gm4246
という感動もつかの間、Firefoxで表示するとWebWorkerがエラー吐いてゲームが止まってしまった。Chromeでは動いたのに。
Content Security Policy: ページの設定により次のリソースの読み込みをブロックしました: https://html5.nicogame.jp/games/gm4246/path/to/worker.js (“child-src 'none'”)
恥を忍んでニコニコヘルプに問い合わせを投げてみたら、丁寧な回答が得られたので。
Firefoxは現状CSP Lv2までしか実装されていない
CSP(Content Security Policy)とは、以下のことらしい。
Content Security Policy (CSP) とは、クロスサイトスクリプティング (XSS) やデータを差し込む攻撃などといった、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。これらの攻撃はデータの窃取からサイトの改ざん、マルウェアの拡散に至るまで、様々な目的に用いられます。
で、なぜChromeで動いてFirefoxで動かなかったかというと、Firefoxは、このCSPがLv2までしか実装されていないとのこと。 ChromeはLv3まで実装されているのだそうだ。
Lv3では、CSPにworker-src
という設定をできるのだが、Lv2ではchild-src
しか設定できず、child-src
ではiframeまで許可してしまうから、アツマールではchild-src 'none'
と設定しているそう。
それなら、child-src https://html5.nicogame.jp/games/gmXXXX
みたいに設定すればまあ問題ないのではと思わなくもないがめんどくさいのだろう。
WebWorkerの代替としてのrequestIdleCallback
恥ずかしながらrequestIdleCallbackというものを初めて知った。
window.requestIdleCallback() メソッドを利用することで、ブラウザーがアイドル状態の時に実行される関数をキューに登録できます。これによりアニメーションや入力への応答など遅延が問題となる処理に影響を与えることなく、優先度の低いバックグラウンド処理をメインスレッド内で実行させられます。キューに登録された関数は、関数登録時に設定したタイムアウト時間に達していない限り、登録順に呼び出されます。
ChromeとFirefoxしか対応していないようなので実装状況はイマイチ。 サクッとバックグラウンド実行したいときに便利そう。
結論
WebWorkerが使えないときは、バックグラウンドで処理するのを諦めた。 敵の思考ルーチン中に画面がカクつくが、動かないよりマシなので…
ちなみに、WebWorkerが使えるかどうかは、以下のようにerror
イベントをハンドリングすることで可能。(少なくともFirefoxの場合)
const worker = new window.Worker('worker.js') worker.addEventListener('error', (ev) => { console.log('使えないよ!') });