共有ワーカーにユーザースクリプトをロードしたい。問題は、ユーザースクリプトが無料であり、ファイルをホストするためのビジネスモデルがないことです。また、1つの小さなファイルをホストするために、無料のサーバーであってもサーバーを使用したくありません。とにかく、 私はそれを試しました そして私は(もちろん)同じOriginポリシーエラーを受け取ります:
Uncaught SecurityError: Failed to construct 'SharedWorker': Script at 'https://cdn.rawgit.com/viziionary/Nacho-Bot/master/webworker.js' cannot be accessed from Origin 'http://stackoverflow.com'.
別の方法があります ワーカー関数を文字列に変換してからBlobに変換し、それをワーカーとしてロードすることでWebワーカーをロードしますが、私もそれを試しました:
var sharedWorkers = {};
var startSharedWorker = function(workerFunc){
var funcString = workerFunc.toString();
var index = funcString.indexOf('{');
var funcStringClean = funcString.substring(index + 1, funcString.length - 1);
var blob = new Blob([funcStringClean], { type: "text/javascript" });
sharedWorkers.google = new SharedWorker(window.URL.createObjectURL(blob));
sharedWorkers.google.port.start();
};
そして、それも機能しません。どうして?共有ワーカーは、ワーカーファイルのロード元の場所に基づいて共有されるためです。 createObjectURL
は使用ごとに一意のファイル名を生成する であるため、ワーカーが同じURLを持つことはなく、したがって共有されることもありません。
どうすればこの問題を解決できますか?
注:特定の解決策について質問しようとしましたが、現時点で私ができる最善のことは、より広い方法で問題の任意のソリューション。同一生成元ポリシーまたは方法のために、試行したすべてのソリューションは基本的に不可能に見えるためです
URL.createObjectURL
動作します( 仕様から 、結果のファイルURLを変更することは不可能のようです)。そうは言っても、私の質問が何らかの形で改善または明確化できる場合は、コメントを残してください。
fetch()
、response.blob()
を使用して、返されたBlob
からタイプ_Blob URL
_の_application/javascript
_を作成できます。 SharedWorker()
パラメータをURL.createObjectURL()
によって作成された_Blob URL
_に設定します。新しく開いたload
のwindow.open()
、window
イベントを利用して、元のSharedWorker
で以前に定義した同じwindow
を定義し、新しく開いたmessage
sで元のSharedWorker
にwindow
イベントを添付します。
javascript
はconsole
at iFrameの内容を別のiFrameからクリアする方法 で試行されました。ここで、現在の質問URLは新しいtab
にmessage
でwindow
を開いてからworker.port.postMessage()
イベントハンドラーまでロードする必要があります。 console
に記録されています。
window
を開くと、同様にmessage
を開くときに、worker.postMessage(/* message */)
を使用して新しく開いたwindow
から投稿されたときに、window
イベントもログに記録する必要があります
_window.worker = void 0, window.so = void 0;
fetch("https://cdn.rawgit.com/viziionary/Nacho-Bot/master/webworker.js")
.then(response => response.blob())
.then(script => {
console.log(script);
var url = URL.createObjectURL(script);
window.worker = new SharedWorker(url);
console.log(worker);
worker.port.addEventListener("message", (e) => console.log(e.data));
worker.port.start();
window.so = window.open("https://stackoverflow.com/questions/"
+ "38810002/"
+ "how-can-i-load-a-shared-web-worker-"
+ "with-a-user-script", "_blank");
so.addEventListener("load", () => {
so.worker = worker;
so.console.log(so.worker);
so.worker.port.addEventListener("message", (e) => so.console.log(e.data));
so.worker.port.start();
so.worker.port.postMessage("hi from " + so.location.href);
});
so.addEventListener("load", () => {
worker.port.postMessage("hello from " + location.href)
})
});
_
console
のいずれかのtab
で、次のように使用できます。 at 別のiFrameからiFrameのコンテンツをクリアする方法worker.postMessage("hello, again")
at new window
of current URL 共有Webワーカーにユーザースクリプトをロードするにはどうすればよいですか? 、worker.port.postMessage("hi, again");
ここで、各message
にwindow
イベントが付加され、2つのwindow
間の通信は、初期URLで作成された元のSharedWorker
を使用して実現できます。
SharedWorker
のURLは同一生成元ポリシーの対象となります。Worker
のURLに対するCORSサポートはありません。GM_worker
のサポートはWONT_FIXになり、は不可能に近いようですFirefoxの変更により実装する。サンドボックス化されたWorker
(unsafeWindow.Worker
ではなく)も機能しないという注意事項もあります。達成したいと思うのは、統計を収集したり、どこにでも表示されるグローバルUIを作成したりする@include *
ユーザースクリプトです。したがって、実行時にいくつかの状態または統計の集計を維持するワーカーが必要です(ユーザースクリプトのすべてのインスタンスから簡単にアクセスできます)、および/または計算量の多いルーチンを実行する必要があります(そうでない場合はそうなるため)ターゲットサイトの速度が低下します)。
私が提案したい解決策は、SharedWorker
デザインを別のものに置き換えることです。
GM_setValue
とその仲間)を使用してください。すべてのuserscriptインスタンス間で共有されます(シーンの背後にあるSQLite)。unsafeWindow.Worker
に入れて、結果をGreasemonkeyストレージに戻します。localStorage
を使用しますが、GreasemomkeyのAPIは同じであるため、使用しないでください。それにアダプタを書くのは難しいです)。したがって、1つのuserscriptインスタンスでロックを取得し、そのインスタンスでルーチンを実行できます。同様に、 [〜#〜] iwc [〜#〜] または ByTheWay ( ここで使用される可能性が高い Stack Exchangeで; それについて投稿する )。よくわかりませんが、ServiceWorker
を希望どおりに機能させるためにSharedWorker
から作成された巧妙な応答のなりすましがある可能性があります。出発点は この回答の編集 にあります。
私はあなたが別の答えを望んでいると確信していますが、悲しいことにこれが要約されます。
ブラウザーはsame-Origin-policiesを実装してインターネットユーザーを保護します。意図は明確ですが、sharedWorkerのオリジンを変更できる正規のブラウザーはありません。
sharedWorker
内のすべてのブラウジングコンテキストは、まったく同じオリジンを共有する必要があります
この問題をハックすることはできません。メソッドに加えてiframeを使用しようとしましたが、機能しません。
たぶん、それをあなたのjavascriptファイルをgithubに置き、彼らのraw.
サービスを使ってファイルを取得することができます。こうすれば、それほど労力をかけずに実行することができます。
私はchromeアップデートを読んでいて、あなたがこれについて尋ねたことを思い出しました。クロスオリジンサービスワーカーがクロームに到着しました!
これを行うには、SWのインストールイベントに以下を追加します。
self.addEventListener('install', event => {
event.registerForeignFetch({
scopes: [self.registration.scope], // or some sub-scope
origins: ['*'] // or ['https://example.com']
});
});
他にもいくつかの考慮事項が必要です。チェックしてください。