没有办法挂钩到加载过程本身,但是具有未知类型的脚本不会作为脚本处理,这与具有自定义类型的脚本不执行的事实相结合,这是以下 hack 所依赖的。
调用window.stop 将阻止文档在其轨道中加载,如果我们在文档的最顶部调用它,我们可以假设文档没有加载。
然后,我们可以发出 XHR 请求来获取文档的内容,并进行一些搜索和替换,通过在将修改后的内容写入文档之前给它们一个自定义脚本类型来使文档中的所有脚本惰性化.
window.stop();
var request = new XMLHttpRequest();
request.open('GET', location.href);
request.onload = function(event) {
var html = request.responseText
.replace(/type=\"text\/javascript\"/g, '')
.replace(/<script/g, '<script type="x-instrument/javascript"');
document.open();
document.write(html);
document.close();
};
request.send(null);
此时,所有脚本都已被渲染为惰性,基本的顺序加载程序可能如下所示:
setTimeout(function next(index) {
var script = document.scripts[index];
if (script == null) {
return setTimeout(callback, 0);
}
if (script.hasAttribute('src')) {
var request = new XMLHttpRequest();
request.open('GET', script.getAttribute('src'));
request.onload = function() {
var code = instrument(request.responseText);
eval(code);
setTimeout(next, 0, ++index);
};
request.send(null);
} else {
var code = instrument(script.textContent);
eval(code);
setTimeout(next, 0, ++index);
}
}, 0, 0);
有了这个,任何页面都可以通过将此脚本插入到文档的开头来检测。
您也可以将其作为内容脚本加载到 chrome 扩展程序中,但请确保将 run_at 设置为 document_start。
{
"manifest_version": 2,
"name": "instrument",
"version": "0.0.0",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["instrument.js"],
"run_at": "document_start"
}
],
"web_accessible_resources": [
"instrument.js"
],
"permissions": [
"tabs", "<all_urls>"
]
}
Example