Search code examples
firefoxfirefox-addonfirefox-addon-sdk

Get content type of an HTTP request


I am developing a Firefox extension on the Addon SDK (V1.9).

Objective

I need to examine HTTP requests for a specific content type before they are loaded (before the request is sent).

Problem

When adding an observer through the 'observer-service' module, I use "http-on-modify-request" to examine all HTTP requests. This provides the headers. However, when checking for content-type, it is never set on request.

Content-type is indeed set on response, which I examine using "http-on-examine-response". But this means that the request has already loaded, defeating the purpose of my extension.

Edit

@Wladimir Palant Thanks for pointing out that content-type is not set when the request headers are being sent.

I am trying to test HTTP requests' urls on a bunch of regexes that are relevant for me and block them. However, I wanted to be able to skip certain content-types (such as images) since they are not relevant for my application.


Solution

  • So, to wrap up on the issue. The best way to have full control of resources loading into the browser seems to be using nsIContentPolicy.

    @WladimirPalant wrote a great example here. And this is how his code would look adapted to the Addon SDK (v1.9):

    const { Cc, Ci, Cu, Cm, components } = require('chrome');
    const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    
    
    let policy =
    {
        classDescription: "Test content policy",
        classID: components.ID("{12345678-1234-1234-1234-123456789abc}"),
        contractID: "@adblockplus.org/test-policy;1",
        xpcom_categories: ["content-policy"],
    
        init: function()
        {
            let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
            registrar.registerFactory(this.classID, this.classDescription, this.contractID, this);
    
            let catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
            for each (let category in this.xpcom_categories)
                catMan.addCategoryEntry(category, this.contractID, this.contractID, false, true);
    },
    
        // nsIContentPolicy interface implementation
        shouldLoad: function(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra)
        {
            dump("shouldLoad: " + contentType + " " +
                          (contentLocation ? contentLocation.spec : "null") + " " +
                          (requestOrigin ? requestOrigin.spec : "null") + " " +
                          node + " " +
                          mimeTypeGuess + "\n");
            return Ci.nsIContentPolicy.ACCEPT;
        },
    
        shouldProcess: function(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra)
        {
            dump("shouldProcess: " + contentType + " " +
                            (contentLocation ? contentLocation.spec : "null") + " " +
                            (requestOrigin ? requestOrigin.spec : "null") + " " +
                            node + " " +
                            mimeTypeGuess + "\n");
            return Ci.nsIContentPolicy.ACCEPT;
        },
    
        // nsIFactory interface implementation
        createInstance: function(outer, iid)
        {
            if (outer)
                throw Cr.NS_ERROR_NO_AGGREGATION;
            return this.QueryInterface(iid);
        },
    
        // nsISupports interface implementation
        QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy, Ci.nsIFactory])
    };
    
    policy.init();