最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Modify document html before load with Chrome extension, using document_start - Stack Overflow

programmeradmin0浏览0评论

I'm trying to create an extension to modify an existing site, and fix a bug in the existing javascript. A simple replace on the text contents of the document before the load would fix the bug -- specifically, hard-coded values in a tag in the header -- and my first attempt (removing the timestamps from date values) was something like this:

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

For example, any instance of "date_of_birth": new Date("Tue, 30 Oct 1984 00:01:00 GMT") bees "date_of_birth": new Date("Tue, 30 Oct 1984")

The problem is that the only way I know of to access the HTML contents of the document is document.documentElement.innerHTML. Running this at document_start fails, as the DOM hasn't been loaded yet, so documentElement.innerHTML is an empty string. Running the above code after the DOM loads will be too late, as the initializing scripts have already run, and modifying the document's html at that point reloads those scripts, causing all kinds of havoc in the script-heavy page.

I cannot simply append to the documentElement before the DOM is loaded, as was the most mon suggestion when searching for a solution. This needs to modify the existing scripts before they are loaded and run.

Is there any way to access and preprocess the raw contents of the HTML document before it is loaded?

Thanks in advance.

I'm trying to create an extension to modify an existing site, and fix a bug in the existing javascript. A simple replace on the text contents of the document before the load would fix the bug -- specifically, hard-coded values in a tag in the header -- and my first attempt (removing the timestamps from date values) was something like this:

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

For example, any instance of "date_of_birth": new Date("Tue, 30 Oct 1984 00:01:00 GMT") bees "date_of_birth": new Date("Tue, 30 Oct 1984")

The problem is that the only way I know of to access the HTML contents of the document is document.documentElement.innerHTML. Running this at document_start fails, as the DOM hasn't been loaded yet, so documentElement.innerHTML is an empty string. Running the above code after the DOM loads will be too late, as the initializing scripts have already run, and modifying the document's html at that point reloads those scripts, causing all kinds of havoc in the script-heavy page.

I cannot simply append to the documentElement before the DOM is loaded, as was the most mon suggestion when searching for a solution. This needs to modify the existing scripts before they are loaded and run.

Is there any way to access and preprocess the raw contents of the HTML document before it is loaded?

Thanks in advance.

Share Improve this question asked Mar 14, 2012 at 7:40 Author XAuthor X 331 silver badge3 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

There is no way to "edit" the contents of <script> before it is executed: Once the closing </script> tag is encountered, the contents is evaluated right away.

Instead of modifying the code itself, an indirect approach can be used: Overwrite the global Date object, which can be done using the code below:

(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

Content scripts run in an isolated environment. That means that you cannot modify global properties directly. To get the code to work in a Content script, you have to inject a <script> tag, in this way:

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

Here's an example of the manifest.json file. Replace <all_urls> with a more specific match pattern.

{
  "name": "Test",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["contentscript.js"],
      "run_at": "document_start"
    }
   ],
   "permissions": ["<all_urls>"]
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论