在新标签中收听页面加载

时间:2014-03-27 14:43:24

标签: javascript https firefox-addon

我的Firefox扩展程序正在侦听onSecurityChange事件(通过HTTPS加载页面)。出于这个原因,我实现了一个nsIWebProgressListener并使用getBrowser()注册它.addTabsProgressListener()。

在事件处理程序中,我必须做一些事情,包括暂停和恢复实际的nsIRequest。事件处理程序中的大多数代码都包含在if语句中,检查aRequest.isPending()是否为true(否则,suspend将无法工作)。

总的来说,这很有效。但是当我在新选项卡中打开一个链接时,onSecurityChange不会被调用,直到页面加载完成(即isPending为false)。这太晚了。

我该怎么做?

2 个答案:

答案 0 :(得分:0)

你有3个选择。

  1. 继续使用nsiWebProgressListener,添加onStateChange:https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIWebProgressListener#onStateChange%28%29
  2. 将事件列表器添加到浏览器以收听页面加载:https://gist.github.com/Noitidart/9287185#
  3. 使用频道观察者观看所有频道并获取调用它的标签并附在那里(这个是最棘手的,因为你必须使用方法来区分重定向和多个频道执行,有些你可能无法做到从中获取loadContext以获取选项卡

答案 1 :(得分:0)

我能够开发一个(可能是hacky)解决方案,它允许我使用onLocationChange拦截HTTPS页面加载。这可能还不完美。

无法使用onSecurityChange(正如我在我的问题中所述),因为在新标签页中打开链接时未正确触发事件。

onLocationChange: function(aBrowser, aWebProgress, aRequest, aLocation, aFlags) {

    if(aRequest != null) {

        // suspend early, because that becomes impossible later
        aRequest.suspend();

        // check if it is HTTPS (no HTTP, no about:, etc.)
        if(aLocation.scheme == "https") {

            var whateverIWantToDo = {
                notify: function(timer) {

                    try {
                        // for example I'm interested in the validation result:
                        let secUI = aBrowser.securityUI;
                        secUI.QueryInterface(Components.interfaces.nsISSLStatusProvider);
                        let status = secUI.SSLStatus;

                        // do something what you want here
                        // and do not forget to resume the request at any point. otherwise that could lead to problems
                        aRequest.resume();
                        //....
                        // the reason I suspend the request at all:
                        // I do not want to completely load the page until I know if the certificate is valid
                    }
                    catch(err) {
                        // maybe it's too early to access the SSLStatus when the event handler kicks in.
                        // in this case an error will be thrown which is caught here
                        // wait 10 ms and try it again, usually that works! (I know, it's a bit hacky)
                        var timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
                        timer.initWithCallback(whateverIWantToDo, 10, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
                    }

                }
            }

            whateverIWantToDo.notify();

        } else {
            // continue normally when it's not a HTTPS request, we want to intercept
            aRequest.resume();
        }
    }
}