nsIWebProgressListener redirectTo not working

It’s not possible to do a redirectTo from a nsIWebProgress listener?

If I go to non http uri:

[Exception… “Component returned failure code: 0x80004002 (NS_NOINTERFACE) [nsISupports.QueryInterface]” nsresult: “0x80004002 (NS_NOINTERFACE)” location: “JS frame :: Scratchpad/1 :: myExtension.onLocationChange :: line 9” data: no]

If I go to http uri like bing:

[Exception… “Component returned failure code: 0x804b000f (NS_ERROR_IN_PROGRESS) [nsIHttpChannel.redirectTo]” nsresult: “0x804b000f (NS_ERROR_IN_PROGRESS)” location: “JS frame :: Scratchpad/1 :: myExtension.onLocationChange :: line 10” data: no]

Here’s the copy paste code:

var myExtension = {
    // nsIWebProgressListener
    QueryInterface: XPCOMUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),

    onLocationChange: function(aProgress, aRequest, aURI) {
        console.log(aURI.spec)
        var httpChannel = aRequest.QueryInterface(Ci.nsIHttpChannel);
        httpChannel.redirectTo(Services.io.newURI('data:text/html,blocked', null, null));
    },

    onStateChange: function() {},
    onProgressChange: function() {},
    onStatusChange: function() {},
    onSecurityChange: function() {}
};

gBrowser.addProgressListener(myExtension);

I was going to say I just reviewed an addon (FoxBangs) which uses a similar process but noticed that you have already seen it :smile:

Hahaha yeah I helped the guy. He wanted a quick solution while I kept working on the gURIKeywordFixup so took your advice.

You can’t do redirectTo() from onLocationChange because the channel has already been opened. Do it from a content policy handler or an http observer. onLocationChange is mostly for watching rather than intercepting. You could cancel the request completely and start another one, but it certainly isn’t the cleanest solution.

1 Like

Ah thanks Litho

There are a few other points worth noting about the posted code snippet.

onLocationChange() for gBrowser content listeners will fire with aRequest=null for tab switches, and very occasionally in other cases, which will cause the code to throw. However, it will not fire for document loads in background tabs, which I suspect is desired here. You can use addTabsProgressListener() to be notified of document loads in all tabs (and not notified about tab switches).

The object passed to gBrowser.addProgressListener() does not actually need to implement nsIWebProgressListener. It is simply an object that may, or may not, have properties that can be called to report web progress events. Therefore the QueryInterface property is not required. More importantly, the tabbrowser holds a strong reference on the object, so the QueryInterface line is actually somewhat misleading. It is important not to sneak away when you’re finished and expect the garbage collector to clean up such an object because it will leak.

Web progress listener functions which are not required do not need to be included in the object. If they are undefined then they will not be called and no errors will occur. Defining them just makes for (possibly a great many) redundant function calls.

1 Like

This is seriously enlightening! Thanks for that share.

There is also times that something in nsIWebProgressListener catches url’s that are of the protocol something like w*** its like wcyj: or something like that, do you know what thats all about? I couldn’t seem to figure out what it was, I thought it was like cached pages but i couldnt directly correlate it with my experiments.

There is a wyciwyg protocol, used as a workaround for maintaining navigation history when documents are being dynamically written using document.write.

1 Like

Ahhhh that’s the one!!! Is there anywhere I can go to learn more about that, it doesn’t make so much sense to me yet.

Not sure there if there are any good write-ups on this. Wikipedia has an article, but it is fairly lightweight. You could go back to the originating bug, which says all there is to say if you wade through it. If nothing else, you get a concise description of the problem that the wyciwyg protocol solves.
https://bugzilla.mozilla.org/show_bug.cgi?id=35340

In summary “pseudo-navigation” pages, where the page content changes but the page location doesn’t, were not stored in the navigation history, so you might click through a hundred “pages” on a shopping or email site, then press back and get catapulted right out of the site to the page you were on before. wyciwyg urls are made up and cached for each of those pseudo-pages so you can then navigate back through them as if they were real pages. Occasionally you can spot the wyciwyg url, for example if you view source for one of those pages.

You may find it interesting to examine the flags and request parameters from onLocationChange() for this type of url.

1 Like