javascript firefox firefox-addon firefox4 prototype-programming

javascript - Cambiar Window.prototype.open de una manera que no es detectable/reversible



firefox firefox-addon (4)

Estoy buscando formas de extender el bloqueo de ventanas emergentes de Firefox desde una extensión. Una opción es reemplazar window.open() (o más bien Window.prototype.open() ) en la página web por una función de contenedor. Un requisito importante es que esta manipulación no puede ser detectada o revertida por la página web. Por ejemplo, si simplemente hago esto:

Window.prototype.open = wrapper;

La página web puede revertir fácilmente el cambio haciendo lo siguiente:

delete Window.prototype.open;

En su lugar, puedo usar Object.defineProperty () para establecer indicadores avanzados de propiedades:

Object.defineProperty(Window.prototype, "open", {value: wrapper, configurable: false});

La página web ya no puede revertir este cambio, pero aún puede detectarlo: delete Window.prototype.open normalmente cambia el valor de Window.prototype.open (diferente instancia de la misma función que parece), aquí la delete no tendrá ningún efecto en absoluto. Además, Window.prototype.open = "test";delete Window.prototype.open; producirá resultados inconsistentes (diferentes dependiendo de si se writable: false bandera writable: false se especifica para la propiedad).

¿Hay algo más que pueda hacer para emular el comportamiento de la propiedad original (excepto el uso de componentes binarios de XPCOM que tienen demasiados problemas propios)?


Los navegadores web previenen intencionalmente este comportamiento, es para mantener la seguridad de la web. Por ejemplo, cuando usa iFrame no quiere que iFrame estropee o piratee su página.

Pero en lugar de manipular las propiedades de los objetos de la ventana, ¿por qué no crear un contenedor para el objeto ventana y anular la ventana mediante el contenedor localmente?

Ejemplo:

// Copy window object to wraper var wrapper = {}; for(prop in window) { wrapper[prop] = window[prop]; } wrapper.open = function yourNewOpenFunction() { /// do your custom code here } (function fakeScope(window){ window.open(); // this is wrapper.open }(wrapper));

Por cierto, esto afecta solo al cuerpo dentro de la función fakeScope () y no se puede aplicar globalmente.


Puede intentar usar la interfaz nsIWindowWatcher para registrar su propio creador de ventanas ( nsIWindowCreator ). De esta forma puede controlar si se abre una nueva ventana sin afectar el objeto de la ventana en sí (y por lo tanto permanecer invisible para los sitios web).

No estoy seguro de si la incapacidad de cambiar la implementación de window.open() sin que esto sea detectable es un error. Tal vez simplemente no se considera un requisito importante para métodos como Object.defineProperty . Pero valdría la pena archivar un error para ver qué piensan los demás acerca de hacer de esto una opción en el futuro. Después de todo, el bloqueo de anuncios es un caso de uso importante.


Al final tuve que dejar de usar proxies JavaScript para el trabajo. Aunque con un poco de esfuerzo puedo crear un contenedor para window.open() que se comporta exactamente como el original (se debe considerar el error 650299 ), no parece haber una forma adecuada de reemplazar el window.open() original window.open() función. La propiedad modificada siempre se comportará de manera diferente a la original, muy mal.

Así que decidí ir con un enfoque diferente como una solución de bloqueo de ventanas emergentes: escuche la notificación content-document-global-created por content-document-global-created y eche un vistazo al tema (la nueva ventana) así como a su abrelatas. Windows con un abridor no nulo son ventanas emergentes de algún tipo. Uno puede mirar las URL y decidir si la ventana emergente debería estar bloqueada. Para bloquear uno se llamaría a window.stop() (detiene todas las actividades de la red antes de que se envíen las solicitudes de red) y window.close() . Este último tiene que ser llamado de forma asíncrona (con un retraso) porque de lo contrario causará un bloqueo a medida que continúa la inicialización de la ventana. Algunas notas sobre este enfoque:

  • Para las ventanas emergentes que se abren en una nueva ventana, la ventana seguirá apareciendo pero desaparecerá inmediatamente. Esto parece ser inevitable.
  • Para la página web, parece que se abrió la ventana emergente, pero se cerró inmediatamente; así no es como funciona el bloqueador de elementos emergentes integrado, sino más bien como una aplicación de bloqueo de ventanas emergentes.
  • Las ventanas nuevas siempre cargan about:blank primero en about:blank antes de cambiar a su destino real. Para las ventanas emergentes del mismo origen, este último no enviará una nueva notificación de content-document-global-created que es desafortunado.

En general: no es perfecto pero utilizable. Y es muy simple, ni cerca de la cantidad de código requerido para los proxies de JavaScript.


me Object.freeze(Window.prototype); esta mañana: puede usar Object.freeze(Window.prototype); ! Las pruebas han demostrado que los métodos protegidos con este cañón se eliminan, pero se pueden detectar fácilmente.

vieja respuesta:

¿Qué hay de ES: Harmony Proxies ? http://brendaneich.com/2010/11/proxy-inception/

Por supuesto, son inestables, pero están funcionando en Firefox 4+, y usted no es el hombre que tiene miedo a las dificultades;)