почему Chrome unsafeWindow trick не поддерживает переопределение отправки XMLHttpRequest?


Я хочу переопределить отправку XMLHttpRequest, чтобы мой userscript знал, когда данные обновляются на странице через такой запрос. Мой код переопределения выглядит следующим образом:

var oldSend = unsafeWindow.XMLHttpRequest.prototype.send;

unsafeWindow.XMLHttpRequest.prototype.send = function(){
    console.log("notified of XHR update");
    oldSend.apply(this, arguments);
}

Если я введу это в страницу (без ссылок на unsafeWindow), это работает нормально,но я хотел бы получить эту работу из области userscript. unsafeWindow работает для этого в Firefox, но не в Chrome. Поэтому я ухватился за ловкий трюк Брока Адамса, чтобы создать рабочий unsafeWindow в Chrome :

var bGreasemonkeyServiceDefined     = false;

try {
    if (typeof Components.interfaces.gmIGreasemonkeyService === "object") {
        bGreasemonkeyServiceDefined = true;
    }
}
catch (err) {
    //Ignore.
}

if ( typeof unsafeWindow === "undefined"  ||  ! bGreasemonkeyServiceDefined) {
    unsafeWindow    = ( function () {
        var dummyElem   = document.createElement('p');
        dummyElem.setAttribute ('onclick', 'return window;');
        return dummyElem.onclick ();
    } ) ();
}

Однако, когда я совместить эти два ничего не получится. Все это работает вставлено в консоль, но нет ни ошибки, ни вывода при запуске этого из userscript. Я делаю что-то не так или, возможно, это за пределами возможностей этого трюка?

Хм, просто попробовал что-то попроще, например: unsafeWindow.document.title = 'testing'; и это тоже не работает, так что, возможно, это не специфично для XMLHttpRequest.

Я пытаюсь избежать инъекции в страницу, если это вообще возможно.

1 2

1 ответ:

Это:

/*--- Create a proper unsafeWindow object on browsers where it doesn't exist
    (Chrome, mainly).
    Chrome now defines unsafeWindow, but does not give it the same access to
    a page's javascript that a properly unsafe, unsafeWindow has.
    This code remedies that.
*/
var bGreasemonkeyServiceDefined     = false;

try {
    if (typeof Components.interfaces.gmIGreasemonkeyService === "object") {
        bGreasemonkeyServiceDefined = true;
    }
}
catch (err) {
    //Ignore.
}

if ( typeof unsafeWindow === "undefined"  ||  ! bGreasemonkeyServiceDefined) {
    unsafeWindow    = ( function () {
        var dummyElem   = document.createElement('p');
        dummyElem.setAttribute ('onclick', 'return window;');
        return dummyElem.onclick ();
    } ) ();
}

Далее следует:

unsafeWindow.document.title = 'testing';

Отлично работает с моими тестовыми пользовательскими текстами.

Они также работают в соответствии с трюком unsafeWindow:

unsafeWindow.foo = function () {
    console.log ("In foo().");
};

unsafeWindow.alert = function (s) {
    console.log ("Alert: ", s);
};

(на странице, где был запущен скрипт, ввод foo() в консоль дает: " In foo().". alert() не генерирует всплывающее окно,а выводит его на консоль.)

Я не знаю, почему (пока) это переопределение XMLHttpRequest.prototype.send не работает так из пользовательского кода Chrome, но я не рекомендую подход unsafeWindow для во всяком случае, так.

введите код переопределения. Используйте postMessage () (который также работает в Chrome) для связи между областью страницы и областью сценария, если вы не можете (или не можете) ввести весь сценарий.