14

我正在处理一个系统,其中在页面的早期执行以下 Javascript 代码(这是我无法控制的)

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() {}
}

此代码似乎用于创建模拟console对象,以防止在没有 javascript 控制台的环境中出现 javascript 错误。这很好,除了它还会阻止 Google Chrome 的控制台运行。条件明确地检查firebug,但仅此而已

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

那么,有没有办法告诉 Chrome 的调试器重新初始化它的控制台对象呢?也就是说,用简单的英语告诉 Chrome

嘿,你知道当你加载一个页面并定义一个控制台对象供我使用吗?再做一次,这样我们就可以覆盖用户空间中某人所做的事情。

我意识到我可以做类似的事情

console.firebug = "faketrue";

并捕获了条件,但是我在系统中受到限制,并且无法在上述控制台重新定义命中之前添加 javascript。换句话说,不,我不能只是在头部开始之后添加一些 javascript 代码。

4

7 回答 7

17

我相信您可以使用 iframe 注入来执行此操作,然后复制 iframe 的控制台对象:

<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/

请注意,这只是该概念应该有效的演示。

编辑

使用纯 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/

编辑

当然,如果您之后需要删除 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');
}
console.log(typeof window.frames);
document.body.removeChild(iframe);
console.log(typeof window.frames);
</script>
于 2011-05-25T22:47:08.620 回答
3

在 Google Chrome 中,删除console对象有效:

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

但是,这在 Firefox 4 中似乎不起作用。不过,这只是一个开始。

于 2011-05-25T23:37:22.617 回答
2

这似乎有效:

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

但是,您似乎无法删除 iframe

于 2011-05-25T22:51:43.533 回答
1

您可以按照上面的建议编写一个非常基本的用户脚本来分配控制台。然后进入该用户脚本的 manifest.json,并将 run_at 设置(参见http://code.google.com/chrome/extensions/content_scripts.html)更改为 document_start。这将使用户脚本现在在任何页面脚本运行之前运行,因此在控制台被弄乱之前

...编辑...

实际上,我从http://blog.chromium.org/2011/07/chrome-extensions-now-with-more.html注意到 chrome 现在也支持@run-at,所以你可以设置它,不要甚至不得不直接弄乱 manifest.json 。他们在http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/userscript-runat/runat.user有一个使用@run-at 的示例脚本.js?view=标记

于 2012-01-22T11:07:57.653 回答
0

你不能把自己的脚本直接放在html的顶部吗?

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

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

你不能比在 HEAD 中早得多了。

于 2011-05-25T22:31:59.610 回答
0

假设您担心的原因是您想在开发时正常使用控制台,您可以创建一个简单的 chrome 扩展来定义 console.firebug,以便条件评估为 false。这样您就不必担心使用其他框架的控制台对象可能产生的任何潜在的古怪行为,也不必担心在开发/部署时重复插入和删除 hack。

于 2011-05-25T23:04:20.060 回答
0

这是我根据之前的答案编写的方法。它有一些额外的逻辑,因此您可以多次调用它而无需重新创建 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;

};

如果最初重新定义的代码是自我修复的,我预计需要fixConsole多次调用。console

于 2019-09-12T15:32:12.107 回答