开发者

"Un-redefining" Google Chrome's console Object

I'm dealing with a system where the following Javascript code (whic开发者_Go百科h 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.


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>


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.


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


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


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜