你如何检测脚本加载*和*在Chrome扩展中执行? [英] How do you detect that a script was loaded *and* executed in a chrome extension?

查看:105
本文介绍了你如何检测脚本加载*和*在Chrome扩展中执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在追踪一个错误数天......然后我意识到这个错误就是我。 :/ b

我一直在使用webRequest.onComplete,根据脚本进行过滤。我的错误是我做了正在加载和正在执行的脚本之间的不正确关联。 get的加载顺序与它们执行的顺序不同,因此事件的时间并不按照我需要的顺序。我需要在特定的脚本之间插入,所以我需要在执行文件之后和之前下一个。

我现在唯一能想到的解决方案是在被执行之前修改JS被加载。但它使我的胃转向。而且bfcache会带来更大的破坏,所以也不是一个好的解决方案。

我会使用HTML5规范的afterscriptexecute,但这并未在Chrome中实现。是否有另一个API,可能是我可以使用的一个扩展API?

解决方案

注意:此方法不再适用于Chrome 36以上版本。没有直接的选择。

注意:下面的答案只适用于外部脚本,即用< ;脚本src>



在Chrome(和Safari)中,beforeload加载。这个事件允许一个人阻止资源,这样脚本永远不会被抓取。在此事件中,您可以确定加载的资源是否为脚本,并检查您是否要执行某些操作。

此事件可用于模拟 beforescriptexecute / afterscriptexecute code> document.addEventListener('beforeload',function(event){
var target = event.target;
if(target.nodeName.toUpperCase()!=='SCRIPT')return ;
var dispatchEvent = function(name,bubbles,cancelable){
var evt = new CustomEvent(name,{
bubbles:bubbles,
cancelable:cancelable
} );
target.dispatchEvent(evt);
if(evt.defaultPrevented){
event.preventDefault();
}
};
var onload = function(){
cleanup();
dispatchEvent('afterscriptexecute',true,false);
};
var cleanup = function(){
target.removeEventListener('load',onload,true);
target.removeEventListener('error',cleanup,true);
}
target.addEventListener('error',cleanup,true);
target.addEventListener('load',onload,true);

dispatchEvent('beforescriptexecute',true,true);
},true);

发货时间与原始发货时间并非100%相同,但在大多数情况下已足够。这是(非模拟)事件的时间线:

beforeload在网络请求
beforescriptexecute在脚本执行之前
afterscriptexecute脚本执行
onload后执行

以下是一个简单的方法,可以看到事件按预期工作:

  window.addEventListener('afterscriptexecute',function(){
alert(window.x);
});
document.head.appendChild(document.createElement('script'))。src ='data:,x = 1';
document.head.appendChild(document.createElement('script'))。src ='data:,x = 2';

演示可以在 http://jsfiddle.net/sDaZt/


I've been tracking down a bug for days... then I realized the bug was me. :/

I had been using webRequest.onComplete, filtered for scripts. My error was that I made the incorrect association between the scripts being loaded and being executed. The get loaded in a different order than they get executed, and thus the timing of the events is not in the order I need them in. I need to inject between certain scripts so I need an event right after a file has been executed and before the next one.

The only solution I can think of at the moment is to alter the JS being loaded before it gets executed. But it makes my stomach turn. And the bfcache would wreak even more havoc, so not a great solution either.

I would use the HTML5 spec's afterscriptexecute, but that is not implemented in Chrome. Is there another API, perhaps an extension API that I can use?

解决方案

Note: This method no longer works as of Chrome 36. There are no direct alternatives.

Note: The answer below only applies to external scripts, i.e. those loaded with <script src>.

In Chrome (and Safari), the "beforeload" event is triggered right before a resource is loaded. This event allows one to block the resource, so that the script is never fetched. In this event, you can determine whether the loaded resource is a script, and check whether you want to perform some action

This event can be used to emulate beforescriptexecute / afterscriptexecute:

document.addEventListener('beforeload', function(event) {
    var target = event.target;
    if (target.nodeName.toUpperCase() !== 'SCRIPT') return;
    var dispatchEvent = function(name, bubbles, cancelable) {
        var evt = new CustomEvent(name, {
            bubbles: bubbles,
            cancelable: cancelable
        });
        target.dispatchEvent(evt);
        if (evt.defaultPrevented) {
            event.preventDefault();
        }
    };
    var onload = function() {
        cleanup();
        dispatchEvent('afterscriptexecute', true, false);
    };
    var cleanup = function() {
        target.removeEventListener('load', onload, true);
        target.removeEventListener('error', cleanup, true);
    }
    target.addEventListener('error', cleanup, true);
    target.addEventListener('load', onload, true);

    dispatchEvent('beforescriptexecute', true, true);
}, true);

The dispatch times are not 100% identical to the original ones, but it is sufficient for most cases. This is the time line for the (non-emulated) events:

beforeload             Before the network request is started
beforescriptexecute    Before a script executes
afterscriptexecute     After a script executes
onload                 After the script has executed

Here's an easy way to see that the events are working as expected:

window.addEventListener('afterscriptexecute', function() {
    alert(window.x);
});
document.head.appendChild(document.createElement('script')).src = 'data:,x=1';
document.head.appendChild(document.createElement('script')).src = 'data:,x=2';

The demo can be seen live at http://jsfiddle.net/sDaZt/

这篇关于你如何检测脚本加载*和*在Chrome扩展中执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆