Изменить документ HTML до загрузки с расширением Chrome, используя document_start - PullRequest
2 голосов
/ 14 марта 2012

Я пытаюсь создать расширение для изменения существующего сайта и исправить ошибку в существующем javascript. Простая замена текстового содержимого документа перед загрузкой исправит ошибку - в частности, жестко закодированные значения в теге в заголовке - и моя первая попытка (удаление меток времени из значений даты) была примерно такой:

document.documentElement.innerHTML = document.documentElement.innerHTML.replace(/("date_of_birth": new Date\("[A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4}) \d{2}:\d{2}:\d{2} GMT/g, "$1");

Например, любой экземпляр "date_of_birth": new Date("Tue, 30 Oct 1984 00:01:00 GMT") становится "date_of_birth": new Date("Tue, 30 Oct 1984")

Проблема в том, что единственный доступный для меня HTML-доступ к документу - это document.documentElement.innerHTML. Выполнение этого в document_start завершается неудачно, так как DOM еще не загружен, поэтому documentElement.innerHTML является пустой строкой. Выполнение вышеуказанного кода после загрузки DOM будет слишком запоздалым, так как инициализирующие сценарии уже запущены, и изменение html документа в этот момент перезагружает эти сценарии, вызывая все виды хаоса на странице, насыщенной сценариями.

Я не могу просто добавить к элементу documentElement перед загрузкой DOM, как это было самое распространенное предложение при поиске решения. Это должно изменить существующие сценарии перед их загрузкой и запуском.

Есть ли способ получить доступ и предварительно обработать необработанное содержимое документа HTML до его загрузки?

Заранее спасибо.

1 Ответ

4 голосов
/ 14 марта 2012

Невозможно «отредактировать» содержимое <script> перед его выполнением: при обнаружении закрывающего тега </script> содержимое оценивается сразу.

Вместо изменения кодаСам по себе, косвенный подход может быть использован: перезаписать глобальный Date объект, что можно сделать с помощью кода ниже:

(function(global) {
    var _Date = global.Date; /* Store original Date object */
    var overwriteafterXmatches = 1; /* Overwrite after X matches*/
    function date(year, month, day, hour, minute, second, millisecond) {
        var tmp = /^([A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4}) \d{2}:\d{2}:\d{2} GMT$/.exec(year);
        switch(arguments.length) {
            case 0:
                return new _Date();
            case 1:
                if (tmp) { /* If match */
                    tmp = new _Date(match[1]);
                    if (--overwriteAfterXmatches <= 0) {
                        /* Set the original Date object*/
                        global.Date = _Date;
                    }
                }
                return new _Date(year);
            case 2:
                return new _Date(year, month);
            case 3:
                return new _Date(year, month, day);
            case 4:
                return new _Date(year, month, day, hour);
            case 5:
                return new _Date(year, month, day, hour, minute);
            case 6:
                return new _Date(year, month, day, hour, minute, second);
            default:
                return new _Date(year, month, day, hour, minute, second, millisecond);
        }
    }
    /* Overwrite global Date object*/
    global.Date = date;
})(window);

contentscript.js

Сценарии содержимого выполняются в изолированной среде .Это означает, что вы не можете изменять глобальные свойства напрямую.Чтобы заставить код работать в скрипте содержимого , вы должны вставить тег <script> следующим образом:

var code = "\
(function(global) {\
    var _Date = global.Date; /* Store original date object*/\
    var overwriteafterXmatches = 1; /* Overwrite after X matches*/\
    function date(year, month, day, hour, minute, second, millisecond) {\
        var tmp = /^([A-Z][a-z]{2}, \d{2} [A-Z][a-z]{2} \d{4}) \d{2}:\d{2}:\d{2} GMT$/.exec(year);\
        switch(arguments.length) {\
            case 0:\
                return new _Date();\
            case 1:\
                if (tmp) { /* If match */\
                    tmp = new _Date(match[1]);\
                    if (--overwriteAfterXmatches <= 0) {\
                        /* Set the original Date object*/\
                        global.Date = _Date;\
                    }\
                }\
                return new _Date(year);\
            case 2:\
                return new _Date(year, month);\
            case 3:\
                return new _Date(year, month, day);\
            case 4:\
                return new _Date(year, month, day, hour);\
            case 5:\
                return new _Date(year, month, day, hour, minute);\
            case 6:\
                return new _Date(year, month, day, hour, minute, second);\
            default:\
                return new _Date(year, month, day, hour, minute, second, millisecond);\
        }\
    }\
    /* Overwrite global Date object*/\
    global.Date = date;\
})(window);\
";
var script = document.createElement('script');
script.appendChild(document.createTextNode(code));
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);

manifest.json

Вотпример файла manifest.json.Замените <all_urls> более конкретным шаблоном совпадения .

{
  "name": "Test",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["contentscript.js"],
      "run_at": "document_start"
    }
   ],
   "permissions": ["<all_urls>"]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...