Comment puis-je charger un worker Web partagé avec un user-script?
je veux charger un worker partagé avec un user-script. Le problème est que le script utilisateur est libre, et n'a pas de modèle d'affaires pour héberger un fichier - ni voudrais-je utiliser un serveur, même un libre, pour héberger un petit fichier. Quoi qu'il en soit, j'ai essayé et j'obtiens (bien sûr) une même erreur de politique d'origine:
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'.
il y a une autre façon de charger un web worker en convertissant la fonction worker pour une chaîne, puis dans un Blob et le chargement de ce que le travailleur, mais j'ai essayé aussi:
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();
};
et ça ne marche pas non plus. Pourquoi? Parce que les travailleurs partagés sont partagé basé sur l'endroit où leur dossier de travailleur est chargé à partir. Depuis createObjectURL
génère un nom de fichier unique pour chaque utilisation , les travailleurs n'auront jamais la même URL et ne seront donc jamais partagés.
comment résoudre ce problème?
Note: j'ai essayé de poser des questions sur des solutions spécifiques, mais à ce point je pense le mieux que je puisse faire est de demander d'une manière plus large pour tout solution au problème, car toutes mes tentatives de solutions semblent fondamentalement impossible en raison des mêmes politiques d'origine ou de la manière
URL.createObjectURL
œuvres de la "caractéristiques techniques des 151960920" , il semble impossible d' modifier L'URL du fichier résultant).cela dit, si ma question peut être améliorée ou clarifiée, veuillez laisser un commentaire.
3 réponses
Vous pouvez utiliser fetch()
, response.blob()
pour créer un Blob URL
de type application/javascript
de retour Blob
; set SharedWorker()
paramètre Blob URL
créé par URL.createObjectURL()
; utiliser window.open()
, load
l'événement de la nouvellement ouvert window
pour définir le même SharedWorker
précédemment défini à l'origine window
ajouter message
de l'événement à l'original SharedWorker
nouvellement ouvert window
.
javascript
a été jugé à console
à comment effacer le contenu d'une iFrame à partir d'une autre iFrame , où L'URL de la question actuelle devrait être chargé à nouveau tab
avec message
de l'ouverture window
à worker.port.postMessage()
gestionnaire d'événements connecté à console
.
Ouverture window
devrait également ouvrir une session message
événement quand il est affiché à partir nouvellement ouvert window
à l'aide worker.postMessage(/* message */)
, de la même manière lors de l'ouverture du 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
vous pouvez ensuite utiliser, par exemple; à Comment effacer le contenu d'une iFrame à partir d'un autre iFrame worker.postMessage("hello, again")
à nouveau window
de l'URL actuelle Comment puis-je charger un web partagé travailleur de l'utilisateur, le script? , worker.port.postMessage("hi, again");
où message
événements attachés à chaque window
, la communication entre les deux window
peut être réalisée en utilisant l'original SharedWorker
créé lors de la première URL.
condition préalable
- Comme vous l'avez fait des recherches et comme il a été mentionné dans les commentaires,
SharedWorker
'URL est soumis à la Même Politique d'Origine. - selon cette question il n'y a pas de support CORS pour L'URL de
Worker
. - selon ce numéro
GM_worker
est maintenant un WONT_FIX, et semble assez proche de l'impossible à mettre en œuvre en raison de changements dans Firefox. Il y a aussi une note que SandboxWorker
(par opposition àunsafeWindow.Worker
) ne fonctionne pas non plus.
Design
ce que je suppose que vous voulez réaliser est un userscript @include *
qui va collecter des statistiques ou créer quelque UI globale ce qui apparaîtra partout. Et donc vous voulez avoir un travailleur pour maintenir certains états ou agrégats statistiques dans l'exécution (qui sera facile d'accès à partir de chaque instance de user-script), et/ou vous voulez faire une routine computation-heavy (parce que sinon il ralentira les sites cibles).
À la manière de toute solution
la solution que je veux proposer est de remplacer SharedWorker
design par une alternative.
- si vous voulez simplement maintenir un État dans le travailleur partagé, utilisez simplement Greasemonkey storage (
GM_setValue
et ses amis). Il est partagé entre toutes les instances userscript (SQLite cache les scènes). - si vous voulez faire quelque chose de calcul-lourde tâche, à lui dans
unsafeWindow.Worker
et remettre le résultat dans le stockage Greasemonkey. - si vous voulez faire un calcul d'arrière-plan et qu'il ne doit être exécuté que par une seule instance, il existe un certain nombre de bibliothèques de synchronisation" inter-fenêtres "(la plupart utilisent
localStorage
mais Greasemomkey's a la même API, donc il ne devrait pas être difficile à écrire un adaptateur). Ainsi, vous pouvez acquérir une serrure dans une instance userscript et y exécuter vos routines. Comme, IWC ou ByTheWay ( probablement utilisé ici sur le Stack Exchange; post about it ).
Autre façon
Je ne suis pas sûr, mais il peut y avoir une réponse ingénieuse spoofing, à partir de ServiceWorker
à faire SharedWorker
travail comme vous le souhaitez. Le point de départ est dans cette réponse édite .
je suis assez sûr que vous voulez une réponse différente, mais malheureusement c'est ce que cela revient à.
Navigateurs de même origine " politiques pour protéger les utilisateurs d'internet, et même si vos intentions sont pures, pas de pièce de théâtre navigateur vous permet de changer l'origine d'un sharedWorker.
tous les contextes de navigation dans un sharedWorker
doivent avoir exactement la même origine
- hôte
- protocole
- port
Vous ne pouvez pas pirater autour de cette question, j'ai essayer en utilisant les iframes, en plus de vos méthodes, mais non fonctionnera.
peut-être que vous pouvez mettre votre fichier javascript sur github et utiliser leur service raw.
pour obtenir le fichier, de cette façon vous pouvez le faire fonctionner sans beaucoup d'efforts.
mise à Jour
je lisais les mises à jour chrome et je rappeler vous poser à ce sujet. les travailleurs des services D'origine croisée sont arrivés sur chrome!
pour ce faire, ajouter ce qui suit à l'événement d'installation pour le SW:
self.addEventListener('install', event => {
event.registerForeignFetch({
scopes: [self.registration.scope], // or some sub-scope
origins: ['*'] // or ['https://example.com']
});
});
D'autres considérations sont nécessaires ainsi, vérifier: