Как переопределить функцию JavaScript из расширения Firefox? - PullRequest
4 голосов
/ 01 июня 2010

Я пытаюсь перехватить вызовы document.write для всех страниц. Настройка перехвата внутри страницы путем внедрения скрипта, подобного

function overrideDocWrite() {
 alert("Override called");
 document.write = function(w) {
  return function(s) {
   alert("special dom");
   w.call(this, wrapString(s));
  };
 }(document.write);
 alert("Override finished");
}

Это просто и работает, но я бы хотел, чтобы мое расширение настроило перехват для каждого объекта документа изнутри расширения. Я не мог найти способ сделать это. Я попытался прослушать событие «загрузки» и настроить там перехват, но это также не удается. Как перехватить звонки на doc.write с добавочного номера?

Я добился определенного прогресса:

var myExtension = {
  init: function() {
    var appcontent = document.getElementById("appcontent"); // browser
    if (appcontent)
      appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad,
        true);
  },

  onPageLoad: function(aEvent) {
    var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
    // do something with the loaded page.
    // doc.location is a Location object (see below for a link).
    // You can use it to make your code executed on certain pages only.
    alert("Override called");
    alert(doc);
    alert(doc.write);
    alert(doc.wrappedJSObject);
    alert(doc.wrappedJSObject.write);
    doc.wrappedJSObject.write = function(w) {
      return function(s) {
        alert("special dom");
        w.call(this, "(" + s + ")");
      };
    }(doc.write);
    alert("Override finished");
  }
}

Кажется, это работает, но DOMContentLoaded - неправильное событие для задания, потому что оно запускается слишком поздно! Есть ли раннее событие для прослушивания?

Ответы [ 2 ]

3 голосов
/ 12 июля 2011

Воскрешение вопроса! Я получил ответ. Вот пример кода:

const os    = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);

os.addObserver({
    observe : function(aWindow, aTopic, aData) {
        if (aWindow instanceof Ci.nsIDOMWindow && aTopic == 'content-document-global-created') {
            aWindow.wrappedJSObject.myfunction = function(){
                // Do some stuff . . .
            }
        }
    }
}, 'content-document-global-created', false);

То же самое относится и к документу со вставленным документом-элементом события, начиная с gecko 2.0.

0 голосов
/ 01 июня 2010

JavaScript использует прототипную систему наследования, вместо классов объекты имеют прототипы. Прототипы - это реальные объекты, которые используются в качестве ссылки на другие объекты для наследования методов и атрибутов.

Лучшей стратегией было бы переопределение метода write в прототипе "document" (для HTML-документа это HTMLDocument). Это должно эффективно обернуть метод для всех экземпляров «документа» внутри страниц, загруженных в браузер, поскольку все они используют один и тот же прототип.

Вместо

document.write = function() { ... }

попробуйте что-то вроде этого:

HTMLDocument.prototype.write= function() { ... }

ОБНОВЛЕНИЕ: Кажется, это не так просто, как я думал, это не работает с первой попытки.

...