“Un-redefining” Google Chrome's console Object

做~自己de王妃 提交于 2019-11-29 11:59:36

问题


I'm dealing with a system where the following Javascript code (which is out of my control) is being executed early in the page

if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}

This code appears to be used to create a mock console object to prevent javascript errors in environments without a javascript console. This is great, except that it also prevents Google Chrome's console from running. The conditional explicatly checks for firebug, but that's it

    if (!("console" in window) || !("firebug" in console))

So, is there way to tell Chrome's debugger to re-initialize its console object? That is, in plain english, tell Chrome

Hey, you know when you load up a page and define a console object for me to use? Do that again so we can override what someone in user-space has done.

I realize I could do something like

console.firebug = "faketrue";

and have the conditional caught, but I'm restricted in the system and don't have a way to add javascript before the above console redefinition hits. Put another way, no, I can't just add a bit of javascript code right after the start of the head.


回答1:


I believe you could possibly do this with an iframe inject and then copy the iframe's console object:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
</script>
<iframe id="text"></iframe>
<script type="text/javascript">
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
</script>

http://jsfiddle.net/nmY6k/

Note, this is just a demonstration that the concept should work.

EDIT

With a pure JS iframe:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
</script>

http://jsfiddle.net/nmY6k/1/

EDIT

And of course, if you need to remove the iframe element afterwards:

<script type="text/javascript">
console = {};
try {
    console.log('1');
} catch(e){
    alert('No console');
}
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = window.frames[0].console;
try {
    console.log('test');
} catch(e){
    alert('No console');
}
console.log(typeof window.frames);
document.body.removeChild(iframe);
console.log(typeof window.frames);
</script>



回答2:


In Google Chrome, deleting the console object works:

<script>
window.console = {};
delete console;
console.log('still works');
</script>

However, this doesn't seem to work in Firefox 4. It's a start, though.




回答3:


This seems to work:

iframe = document.createElement('iframe');
document.body.appendChild(iframe);
console = iframe.contentWindow.console;

However it looks like you cannot remove the iframe




回答4:


You could write a pretty basic userscript to assign console as suggested above. Then go into the manifest.json for that userscript, and change the run_at setting (see http://code.google.com/chrome/extensions/content_scripts.html ) to document_start. That will make the userscript now run before any of the page scripts run, so before console ever gets messed with.

...edit...

Actually, I note from http://blog.chromium.org/2011/07/chrome-extensions-now-with-more.html that chrome also now supports @run-at, so you can set that, and don't even have to mess with manifest.json directly. They have an example script using @run-at at document_start at http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/userscript-runat/runat.user.js?view=markup




回答5:


Can't you put your own script directly in the head of the html right at the top?

<script ...>
    if (console) { window.cache_console = console; }
</script>
</head>
<body>
... html ...

<script>
    window.console = window.cache_console;
</script>
</body>
</html>

You can't get much earlier than right up in the HEAD.




回答6:


Assuming the reason you're concerned is that you want to use the console normally as you develop, you could whip up a simple chrome extension that defines console.firebug so that the condition will evaluate to false. That way you don't need to worry about any potential quirky behavior that might arise from using some other frame's console object, nor do you have to worry about repeatedly inserting and deleting a hack as you develop/deploy.




回答7:


Here is a method I wrote based on the previous answers. It's got a bit of extra logic so that you can call it multiple times without recreating the iframe.

function fixConsole() {

    var iframe;
    if(!(iframe = document.getElementById('fixConsole'))) {
        iframe = document.createElement('iframe');
        iframe.id = 'fixConsole';
        document.body.appendChild(iframe);
    }
    delete console;    
    console = iframe.contentWindow.console;

};

I anticipate the need to call fixConsole multiple times in the case that the code which originally redefined console is self repairing.



来源:https://stackoverflow.com/questions/6131651/un-redefining-google-chromes-console-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!