scripts javascript greasemonkey userscripts

javascript - greasemonkey scripts



¿Cómo puedo cargar un trabajador web compartido con un script de usuario? (3)

Condición previa

  • Como ha investigado y como se ha mencionado en los comentarios, la URL de SharedWorker está sujeta a la Política del mismo origen.
  • Según esta pregunta, no hay soporte de CORS para la URL del Worker .
  • De acuerdo con este problema, el soporte de GM_worker ahora es un WONT_FIX, y parece lo suficientemente cerca como imposible de implementar debido a los cambios en Firefox. También hay una nota de que Workboxed Worker (en oposición a unsafeWindow.Worker ) tampoco funciona.

Diseño

Lo que supongo que desea lograr es un script de usuario @include * que recopilará algunas estadísticas o creará una interfaz de usuario global que aparecerá en todas partes. Y, por lo tanto, desea tener un trabajador para mantener algunos agregados estadísticos o de estado en tiempo de ejecución (que será de fácil acceso desde cada instancia de script de usuario), y / o desea hacer alguna rutina de cálculo pesado (porque de lo contrario lo hará sitios objetivos lentos).

En el camino de cualquier solución

La solución que quiero proponer es reemplazar el diseño de SharedWorker con una alternativa.

  • Si solo desea mantener un estado en el trabajador compartido, simplemente use el almacenamiento de Greasemonkey ( GM_setValue y amigos). Se comparte entre todas las instancias de script de usuario (SQLite detrás de las escenas).
  • Si desea hacer algo que unsafeWindow.Worker mucha tarea de cómputo, unsafeWindow.Worker en unsafeWindow.Worker y unsafeWindow.Worker colocar el resultado en el almacenamiento de Greasemonkey.
  • Si desea realizar algunos cálculos en segundo plano y debe ejecutarse solo por una sola instancia, hay varias bibliotecas de sincronización "entre ventanas" (en su mayoría usan localStorage pero Greasemomkey tiene la misma API, por lo que no debería ser difícil de escribir un adaptador para eso). Por lo tanto, puede adquirir un bloqueo en una instancia de usercript y ejecutar sus rutinas en él. Me gusta, IWC o ByTheWay ( probablemente usado aquí en Stack Exchange; publique sobre esto ).

Otra manera

No estoy seguro, pero puede haber una suplantación de respuesta ingeniosa, realizada desde ServiceWorker para hacer que SharedWorker funcione como a usted le gustaría. El punto de partida está en la edición de esta respuesta .

Quiero cargar un trabajador compartido con un script de usuario. El problema es que el script de usuario es gratuito y no tiene un modelo de negocio para alojar un archivo, ni me gustaría usar un servidor, incluso uno gratuito, para alojar un archivo pequeño. De todos modos, lo probé y (por supuesto) obtengo el mismo error de política de origen:

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''.

Hay otra forma de cargar un trabajador web convirtiendo la función de trabajador en una cadena y luego en un Blob y cargando eso como trabajador, pero también lo intenté:

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(); };

Y eso tampoco funciona. ¿Por qué? Debido a que los trabajadores compartidos se comparten en función de la ubicación desde la que se carga su archivo de trabajador. Dado que createObjectURL genera un nombre de archivo único para cada uso , los trabajadores nunca tendrán la misma URL y, por lo tanto, nunca se compartirán.

¿Como puedó resolver esté problema?

Nota: Intenté preguntar sobre soluciones específicas, pero en este punto creo que lo mejor que puedo hacer es pedir de manera más amplia cualquier solución al problema, ya que todas mis soluciones intentadas parecen fundamentalmente imposibles debido a las mismas políticas de origen o forma en que funciona URL.createObjectURL (a partir de las especificaciones , parece imposible alterar la URL del archivo resultante).

Dicho esto, si mi pregunta se puede mejorar o aclarar de alguna manera, por favor deje un comentario.


Estoy bastante seguro de que quieres una respuesta diferente, pero lamentablemente esto es a lo que se reduce.

Los navegadores implementan políticas del mismo origen para proteger a los usuarios de Internet, y aunque sus intenciones son claras, ningún navegador legítimo le permite cambiar el origen de un Trabajador compartido.

Todos los contextos de navegación en un sharedWorker deben compartir exactamente el mismo origen

  • anfitrión
  • protocolo
  • Puerto

No puedes hackear este problema, estoy intentando usar iframes además de tus métodos, pero no funcionará.

Tal vez puedas ponerlo en tu archivo javascript en github y usar su raw. servicio para obtener el archivo, de esta manera puede ejecutarlo sin mucho esfuerzo.

Actualizar

Estaba leyendo actualizaciones de Chrome y recordé que preguntaste sobre esto. ¡Los trabajadores de servicio de origen cruzado llegaron a Chrome!

Para hacer esto, agregue lo siguiente al evento de instalación para el SW:

self.addEventListener(''install'', event => { event.registerForeignFetch({ scopes: [self.registration.scope], // or some sub-scope origins: [''*''] // or [''https://example.com''] }); });

También se necesitan algunas otras consideraciones, échale un vistazo:

Enlace completo: https://developers.google.com/web/updates/2016/09/foreign-fetch?hl=en?utm_campaign=devshow_series_crossoriginserviceworkers_092316&utm_source=gdev&utm_medium=yt-desc


Puede usar fetch() , response.blob() para crear una Blob URL de Blob URL de tipo application/javascript desde Blob devuelto; establecer el parámetro SharedWorker() en Blob URL creado por URL.createObjectURL() ; utilice window.open() , load evento de la window recién abierta para definir el mismo SharedWorker definido previamente en la window original, adjunte el evento del message al SharedWorker original en la window recién abierta s.

Se intentó javascript en la console en Cómo borrar el contenido de un iFrame de otro iFrame , donde la URL de la pregunta actual debe cargarse en una nueva tab con el message de la window apertura a través del controlador de eventos worker.port.postMessage() registrado en la console .

La window apertura también debe registrar el evento del message cuando se publica desde una window recién abierta usando worker.postMessage(/* message */) , de manera similar en la window apertura

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://.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) }) });

En la console en cualquiera de las tab , puede usar, por ejemplo; en Cómo borrar el contenido de un iFrame de otro iFrame worker.postMessage("hello, again") en una nueva window de la URL actual ¿Cómo puedo cargar un trabajador web compartido con un script de usuario? , worker.port.postMessage("hi, again"); donde los eventos de message se adjuntan en cada window , la comunicación entre las dos window se puede lograr utilizando SharedWorker original creado en la URL inicial.