Подтвердить что ты не робот

Изменение Window.prototype.open способом, который не обнаруживается/обратимым

Я изучаю способы расширения блокировки всплывающих окон Firefox из расширения. Один из вариантов заменяет window.open() (или, скорее, Window.prototype.open()) на веб-странице с помощью функции обертки. Важным требованием является то, что эта манипуляция не может быть обнаружена или отменена веб-страницей. Например, если я просто делаю это:

Window.prototype.open = wrapper;

Веб-страница может легко вернуть изменения, выполнив следующие действия:

delete Window.prototype.open;

Вместо этого я могу использовать Object.defineProperty() для установки расширенных флагов свойств:

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

Веб-страница больше не может отменить это изменение, но она все еще может ее обнаружить: delete Window.prototype.open обычно меняет значение Window.prototype.open (другой экземпляр той же самой функции), здесь delete не будет иметь никакого эффекта вообще. Кроме того, Window.prototype.open = "test";delete Window.prototype.open; приведет к несогласованным результатам (разные в зависимости от того, указан ли флаг writable: false для свойства).

Есть ли что-нибудь еще, что я могу сделать для эмуляции поведения исходного свойства (не считая использования двоичных компонентов XPCOM, у которых слишком много собственных проблем)?

4b9b3361

Ответ 1

В конце концов мне пришлось отказаться от использования JavaScript-прокси для задания. Несмотря на то, что с некоторыми усилиями я могу создать оболочку для window.open(), которая ведет себя точно так же, как оригинал (ошибка 650299, Кажется, это правильный способ заменить оригинальную функцию window.open(). Измененное свойство всегда будет отличаться от исходного, слишком плохо.

Поэтому я решил использовать другой подход как всплывающее блокирующее решение: прослушать content-document-global-created уведомление и посмотреть предмет (новое окно), а также его открыватель. Windows с ненулевым открывателем - это всплывающие окна. Можно посмотреть URL-адреса и решить, следует ли блокировать всплывающее окно. Для блокировки один из них вызовет window.stop() (останавливает все сетевые действия до отправки любых сетевых запросов) и window.close(). Последнее должно быть названо асинхронно (с задержкой), потому что это приведет к сбою в противном случае, поскольку инициализация окна будет продолжена. Некоторые замечания по этому подходу:

  • Для всплывающих окон, открываемых в новом окне, окно все равно будет отображаться, но сразу исчезнет. Это кажется неизбежным.
  • Для веб-страницы похоже, что всплывающее окно открыто, но было закрыто сразу - это не то, как работает встроенный блокировщик всплывающих окон, больше похожий на внешнее всплывающее окно.
  • Новые окна всегда загружают about:blank сначала, прежде чем перейти к их фактическому месту назначения. Для всплывающих окон того же самого происхождения последнее не отправляет новое уведомление content-document-global-created, которое является неудачным.

В целом: не идеально, но полезно. И это очень просто, не так далеко от кода, необходимого для прокси-серверов JavaScript.

Ответ 2

Вы можете попробовать использовать nsIWindowWatcher интерфейс для регистрации вашего собственного создателя окна (nsIWindowCreator). Таким образом, вы можете управлять открытием нового окна, не затрагивая сам объект окна (и, таким образом, оставаться невидимым для веб-сайтов).

Я не уверен, является ли невозможностью изменить реализацию window.open(), если это не обнаружено, является ошибкой. Возможно, это просто не считается важным требованием для таких методов, как Object.defineProperty. Но, возможно, стоит обратить внимание на то, что другие думают о том, чтобы сделать этот вариант в будущем. В конце концов, блокировка рекламы является основным прецедентом.

Ответ 3

Веб-браузеры преднамеренно предотвращают это поведение, оно для обеспечения безопасности сети, например. когда вы используете iFrame, вы не хотите, чтобы iFrame испортил или взломал вашу страницу.

Но вместо того, чтобы манипулировать свойствами окна-объекта, почему бы не создать оболочку для окна-объекта и переопределить окно локально?

Пример:

// 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));

Кстати, это влияет только на тело внутри функции fakeScope() и не может применяться глобально.

Ответ 4

он ударил меня сегодня утром: вы можете использовать Object.freeze(Window.prototype);! тест показал, что методы, защищенные этой пушкой, будут удалены, но их можно легко обнаружить.


старый ответ:

Как насчет ES: Гармония Proxies? http://brendaneich.com/2010/11/proxy-inception/

Конечно, они нестабильны, но они работают в Firefox 4+, и вы не тот человек, который боится трудностей;)