I need a Firefox extension which performs some actions (redirect and
others) before the URL is open. Simply using Mozilla's
window.addEventListener("load", Handler, ..) does not work since I have
to catch the URL *before* the page is loaded. Not too exotic task on my
thought. I also read a couple of relevant posts here, however I rushed
into problems.
What exactly I did (I use Firefox 2.0, WinXP SP2):
I implemented nsIURIContentListener interface.
// MyOverlay.js
//implementation of nsIURIContentListener
var myListener =
{
QueryInterface: function(iid)
{
alert("QueryInterface "+iid);
if (iid.equals(Components.interfaces.nsIURIContentListener) ||
iid.equals(Components.interfaces.nsISupportsWeakReference)
||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
onStartURIOpen: function(uri)
{
alert("onStartURIOpen "+uri);
return false;
},
doContent: function(contentType, isContentPreferred, request,
contentHandler)
{
alert("doContent");
return false;
},
isPreferred: function(contentType, desiredContentType)
{
alert("isPreferred");
return false;
},
canHandleContent: function(contentType, isContentPreferred,
desiredContentType)
{
alert("canHandleContent");
return false;
},
GetWeakReference: function()
{
alert("GetWeakReference");
return this;
}
}
// I set up the content listener: attempt 1
var wnd =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
wnd.parentURIContentListener = myListener;
I get the following error the java script error log:
Error: uncaught exception: [Exception... "Cannot modify properties of a
WrappedNative" nsresult: "0x80570034
(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN)" location: "JS frame ::
chrome://foxmon/content/FoxmonOverlay.js :: :: line 44"
data: no]
Line 44 is docShell.parentURIContentListener = myListener;
Trying to get the exact nsIWebBrowser interface from the window using
QueryInterface did not succeed. After googling for a while I found
another method to get nsIWebBrowser interface:
// Setting up the content listener: attempt 2
var wnd =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var treeItem =
wnd.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
var treeOwner = treeItem.treeOwner;
var interfaceRequestor =
treeOwner.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var webBrowserChrome =
interfaceRequestor.getInterface(Components.interfaces.nsIWebBrowserChrome);
if (webBrowserChrome)
{
var chromeFlags = webBrowserChrome.chromeFlags;
var res = chromeFlags &
Components.interfaces.nsIWebBrowserChrome.CHROME_ALL;
var res2 = chromeFlags &
Components.interfaces.nsIWebBrowserChrome.CHROME_DEFAULT;
if ( res == Components.interfaces.nsIWebBrowserChrome.CHROME_ALL ||
res2 == Components.interfaces.nsIWebBrowserChrome.CHROME_DEFAULT)
{
var wb = webBrowserChrome.webBrowser;
}
}
This code works fine until the selected line where an attempt to get
webBrowser member of webBrowserChromw returned me
Error: uncaught exception: [Exception... "Component returned failure
code: 0x80004005 (NS_ERROR_FAILURE) [nsIWebBrowserChrome.webBrowser]"
nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame ::
chrome://foxmon/content/FoxmonOverlay.js :: :: line 57"
data: no]
After that I tried the following
// Setting up the content listener: attempt 3
var uriLoader =
Components.classes["@mozilla.org/uriloader;1"].getService(Components.interfaces.nsIURILoader);
uriLoader.registerContentListener(myListener);
Things went slightly better: I traced (with alerts) two calls to
myListener.QueryInterface: first one was a request for nsISupports, the
second one was a request for
nsISupportsWeakReference when the Firefox started. However
onStartURIOpen was not called when I pointed my browser to my favourite
URL.
Finally I tried to set the content listener like that:
// Setting up the content listener: attempt 4
var myIWebBrowser =
(Components.classes["@mozilla.org/embedding/browser/nsWebBrowser;1"]).getService(Components.interfaces.nsIWebBrowser);
if(!myIWebBrowser) alert("Not Created");
myIWebBrowser.parentURIContentListener = myListener;
And, after tracing the call to nsISupports interface in
myListener.QueryInterface I got the same error as in my first attempt
Error: uncaught exception: [Exception... "Component returned failure
code: 0x80004005 (NS_ERROR_FAILU