我的 nsIContentPolicy Firefox/IceWeasel 扩展 XPCOMponent 实现中缺少什么来调用 shouldLoad?

发布于 2024-12-25 01:03:24 字数 4088 浏览 2 评论 0原文

简而言之

,为什么根据下面详细的代码,shouldLoad 函数没有被调用?

更长的版本

我的目标

我正在尝试构建一个 Firefox/Iceweasel 扩展,它将取消/重定向某些 url 请求。

背景

根据我在网上看到的内容,一种方法(如果我想拦截每个请求而不仅仅是顶部文档)是创建一个实现 nsIContentPolicy 接口的 XPCOM 组件,并在扩展中注册该组件,并让 shouldLoad 函数检查请求的 url 并在适当时拒绝。

问题

我已经尽我最大的努力实现了一个组件,并将其与我的扩展集成。该组件似乎可以在 compreg.dat 等中注册,但是 - 据我所知,shouldLoad 函数没有被调用。

详细信息

Environment

我正在 Debian Linux 上使用与 FireFox 3.5.16 相对应的 IceWeasel 版本进行开发。

Extension

我的扩展基于以下给出的示例扩展 http://kb.mozillazine.org/Getting_started_with_extension_development#reg-em 本质上,它所做的只是添加一个菜单项,打开一个类似警报的对话框,说“你好,世界”。它有一个 onLoad 注册,可以触发并发出警报“onLoad Reporting!”。警报每次都会毫无问题地触发。

Reference

我已经安装了扩展重定向器,看起来运行原理相同, https://addons.mozilla.org/en-US/firefox/addon/重定向器/ 并且它有效(所以这可能是我的代码中的错误而不是环境不好)。

Component

我的组件实现基于我在互联网上找到的各种资源。 我把它放在目录 {pathtoextension}/helloworld/components/PolicyComponent.js 中的一个文件中,其代码如下:

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");  
const CI = Components.interfaces, CC = Components.classes, CR = Components.results;  

var componentobj = null;

function PolicyComponent()
{
    // this.wrappedJSObject = this;
}  

PolicyComponent.prototype = {  
  classDescription: "My QWERTY nsIContentPolicy XPCOM Component",  
  classID:          Components.ID("{6ffd2f60-3784-11e1-b86c-0800200c9a66}"),  
  contractID:       "@abc.def.com/policycomp;1",  
  QueryInterface: XPCOMUtils.generateQI([CI.nsIContentPolicy]),  


  testFunction: function() { return "Your component is not entirely broken!"; },  

  _xpcom_categories: [{
        category: "content-policy"
    }],

    _xpcom_factory  :
    {
        createInstance: function(outer, iid)
        {
            if (outer)
            { throw CR.NS_ERROR_NO_AGGREGATION;}
            if (componentobj == null)
            {
                componentobj = new PolicyComponent();   
            }
            else {}
            return componentobj.QueryInterface(iid);
        }
    },



    shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra)
    {
        if (contentType != Ci.nsIContentPolicy.TYPE_DOCUMENT) {
                return Ci.nsIContentPolicy.ACCEPT;
            }

        if(-1 != contentLocation.spec.search("abc"))
            {
                aContext.loadURI("http://www.stroustrup.com/", requestOrigin, null);
                return Ci.nsIContentPolicy.REJECT_REQUEST;
            }
        return CI.nsIContentPolicy.ACCEPT;
    },

    shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) {
        return CI.nsIContentPolicy.ACCEPT;
    }    

};  
var components = [PolicyComponent];  

if (XPCOMUtils.generateNSGetFactory)  
    var NSGetFactory = XPCOMUtils.generateNSGetFactory([PolicyComponent]);  
else  
    var NSGetModule = XPCOMUtils.generateNSGetModule([PolicyComponent]);
Status

该组件似乎被 IceWeasel 识别了。如果我删除 compreg.dat 和 xpti.dat 并重新启动 IceWeasel,则 compreg.dat 中内容策略的 grep 会给出以下结果:

...
@mozilla.org/embedding/browser/content-policy;1,{f66bc334-1dd1-11b2-bab2-90e04fe15c19}
content-policy,@mozilla.org/data-document-content-policy;1,@mozilla.org/data-document-content-policy;1
content-policy,My QWERTY nsIContentPolicy XPCOM Component,@abc.def.com/policycomp;1
content-policy,@mozilla.org/no-data-protocol-content-policy;1,@mozilla.org/no-data-protocol-content-policy;1
...

因此,看起来该组件至少有一些正确的内容。 但是,我仍然可以访问 url 中包含“abc”的网页(这使我们相信 shouldLoad 函数未被调用)。

Further info

我没有在 chrome.manifest 文件中添加任何有关扩展名的内容。我相信在 FF/IW 3.5.x 版本中我不需要这样做。

问题

  1. 出了什么问题? :)

  2. 我需要在 chrome.manifest 中添加一些内容吗?或者仅适用于 FF 4+?

  3. 我是否需要以某种方式进一步实例化组件/服务?就像 onLoad 挂钩中的overlay.js 一样?

  4. 我是否需要以更明确的方式将组件注册为对扩展有效,如果需要,如何?

提前致谢!

In short

Why, based on the code detailed below, is the shouldLoad function not called?

Longer version

My goal

I am trying to construct a Firefox/Iceweasel extension that will cancel/redirect certain url requests.

Background

Based on what I have seen on the web, one way (if I want to intercept every request and not just the top document) to do this is to make an XPCOM component that implements the nsIContentPolicy interface, and register that component in the extension, and have the shouldLoad function examine the requested url and deny when appropriate.

Problem

I have implemented a component to the best of my effort, and integrated it with my extension. The component seems to work in the sense that it gets registered in compreg.dat, etc, BUT - the shouldLoad function does not get called, as far as I can tell.

Details

Environment

I am developing on Debian Linux using an IceWeasel version corresponding to FireFox 3.5.16.

Extension

My extension is based off of an example extension given at
http://kb.mozillazine.org/Getting_started_with_extension_development#reg-em
In essence, all it does is add a menu item that opens an alert-like dialog saying hello world. it has an onLoad registration that fires and alert saying "onLoad Reporting!". The alert fires without problems every time.

Reference

I have installed the extension Redirector, seemingly operating on the same principles,
https://addons.mozilla.org/en-US/firefox/addon/redirector/
and it works (so it is likely to be a mistake in my code rather than the environment being bad).

Component

My component implementation is based on various sources I have found on the internet.
I have placed it in a file in directory {pathtoextension}/helloworld/components/PolicyComponent.js, and its code is as follows:

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");  
const CI = Components.interfaces, CC = Components.classes, CR = Components.results;  

var componentobj = null;

function PolicyComponent()
{
    // this.wrappedJSObject = this;
}  

PolicyComponent.prototype = {  
  classDescription: "My QWERTY nsIContentPolicy XPCOM Component",  
  classID:          Components.ID("{6ffd2f60-3784-11e1-b86c-0800200c9a66}"),  
  contractID:       "@abc.def.com/policycomp;1",  
  QueryInterface: XPCOMUtils.generateQI([CI.nsIContentPolicy]),  


  testFunction: function() { return "Your component is not entirely broken!"; },  

  _xpcom_categories: [{
        category: "content-policy"
    }],

    _xpcom_factory  :
    {
        createInstance: function(outer, iid)
        {
            if (outer)
            { throw CR.NS_ERROR_NO_AGGREGATION;}
            if (componentobj == null)
            {
                componentobj = new PolicyComponent();   
            }
            else {}
            return componentobj.QueryInterface(iid);
        }
    },



    shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra)
    {
        if (contentType != Ci.nsIContentPolicy.TYPE_DOCUMENT) {
                return Ci.nsIContentPolicy.ACCEPT;
            }

        if(-1 != contentLocation.spec.search("abc"))
            {
                aContext.loadURI("http://www.stroustrup.com/", requestOrigin, null);
                return Ci.nsIContentPolicy.REJECT_REQUEST;
            }
        return CI.nsIContentPolicy.ACCEPT;
    },

    shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) {
        return CI.nsIContentPolicy.ACCEPT;
    }    

};  
var components = [PolicyComponent];  

if (XPCOMUtils.generateNSGetFactory)  
    var NSGetFactory = XPCOMUtils.generateNSGetFactory([PolicyComponent]);  
else  
    var NSGetModule = XPCOMUtils.generateNSGetModule([PolicyComponent]);

Status

The component seems to be recognised by IceWeasel. If I remove compreg.dat and xpti.dat and restart IceWeasel, a grep on content-policy in compreg.dat gives the following result:

...
@mozilla.org/embedding/browser/content-policy;1,{f66bc334-1dd1-11b2-bab2-90e04fe15c19}
content-policy,@mozilla.org/data-document-content-policy;1,@mozilla.org/data-document-content-policy;1
content-policy,My QWERTY nsIContentPolicy XPCOM Component,@abc.def.com/policycomp;1
content-policy,@mozilla.org/no-data-protocol-content-policy;1,@mozilla.org/no-data-protocol-content-policy;1
...

So it seems as if there is at least something correct with the component.
HOWEVER, I can still access web pages with "abc" in the url (which makes believe that the shouldLoad function is not called).

Further info

I have not added anything about the extension to the chrome.manifest file. It is my belief that I need not do that in version 3.5.x of FF/IW.

Questions

  1. What's wrong? :)

  2. Would I need to add something to chrome.manifest? Or is that only for FF 4+?

  3. Do I need to somehow instantiate the component/service further? Like in, say, the overlay.js in the onLoad hook?

  4. Do I need to register the component as valid for the extension in a more explicit way, and if so, how?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

可遇━不可求 2025-01-01 01:03:24

看来您没有验证您的 shouldLoad 方法确实没有被调用。我建议使用 dump() 函数 来查看您的系统中到底发生了什么成分。看起来更有可能它被调用,但它抛出一个异常,如“aContext.loadURI 不是一个函数”。原因是 TYPE_DOCUMENT 调用的 aContext 是一个 HTMLDocument 对象,并且它没有 loadURI 方法。您可能想改为调用aContext.defaultView.location.replace()。但从内容策略中执行此操作将是一个安全漏洞(事实上,从内容策略中执行任何可能导致网页脚本运行的操作都将是一个安全漏洞)。如果您查看接口定义 你会看到它附带了很大的警告。

因此,像这样的操作需要延迟发生,以确保它在引擎处于一致状态时发生。例如你可以这样做:

aContext.defaultView.setTimeout("window.location.replace('http://www.stroustrup.com/')", 0);

怎么了? :)

除了我上面提到的之外,您可能不应该定义自定义 _xpcom_factory 函数。内容策略始终用作服务,这意味着它们自动是单例的。当然,您自己的访问组件的代码也应该使用 getService() 。

我需要向 chrome.manifest 添加一些内容吗?还是仅适用于 FF 4+?

是的,适用于 FF4+。像这样的东西:

component {6ffd2f60-3784-11e1-b86c-0800200c9a66} components/PolicyComponent.js
contract @abc.def.com/policycomp;1 {6ffd2f60-3784-11e1-b86c-0800200c9a66}
category content-policy @abc.def.com/policycomp;1 @abc.def.com/policycomp;1

我是否需要以某种方式进一步实例化组件/服务?就像 onLoad 挂钩中的overlay.js 一样?

不,这是由内置内容策略组件自动发生的。

我是否需要以更明确的方式将组件注册为对扩展有效,如果需要,如何注册?

不知道你的意思。

Looks like you didn't verify that your shouldLoad method really isn't being called. I would suggest using dump() function to see what's really happening in your component. It seems more likely that it is being called but it throws an exception like "aContext.loadURI is not a function". Reason is that aContext for TYPE_DOCUMENT calls is an HTMLDocument object and it has no loadURI method. You probably want to call aContext.defaultView.location.replace() instead. But doing that from a content policy would be a security vulnerability (in fact, doing anything from a content policy that could cause the web page scripts to run would be a security vulnerability). If you look at the interface definition you will see that it comes with big warnings attached.

So a manipulation like this one needs to happen delayed, to make sure that it happens when the engine is in a consistent state. E.g. you could do:

aContext.defaultView.setTimeout("window.location.replace('http://www.stroustrup.com/')", 0);

What's wrong? :)

Other than what I mentioned above, you probably shouldn't define your custom _xpcom_factory function. Content policies are always used as a service meaning that they are automatically singletons. Your own code accessing the component should use getService() as well of course.

Would I need to add something to chrome.manifest? Or is that only for FF 4+?

Yes, for FF4+. Something like:

component {6ffd2f60-3784-11e1-b86c-0800200c9a66} components/PolicyComponent.js
contract @abc.def.com/policycomp;1 {6ffd2f60-3784-11e1-b86c-0800200c9a66}
category content-policy @abc.def.com/policycomp;1 @abc.def.com/policycomp;1

Do I need to somehow instantiate the component/service further? Like in, say, the overlay.js in the onLoad hook?

No, that happens automatically by the built-in content policy component.

Do I need to register the component as valid for the extension in a more explicit way, and if so, how?

Don't know what you mean.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文