Изменение 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, у которых слишком много собственных проблем)?

4 ответа

Решение

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

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

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

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

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

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

Веб-браузеры намеренно предотвращают такое поведение, оно предназначено для обеспечения безопасности сети, например, когда вы используете 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() и не может применяться глобально.

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


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

Как насчет ES: Harmony Proxies? http://brendaneich.com/2010/11/proxy-inception/

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

Другие вопросы по тегам