I am looking for a simple solution to catch any window re-directions (301
, 302
etc.) to retrieve the corresponding url from a nsiWebProgress
.
Current solution
Right now, I am using the nsIWebProgress.NOTIFY_STATE_DOCUMENT
event listener, processing any STATE_REDIRECTING
status responses (also known as "flags") and iterating the responseHeaders
from the corresponding request's nsIHttpChannel
interface , as shown below.
Question
However, I am not sure, if I am using the best event listener (NOTIFY_STATE_DOCUMENT
) and if this is really the fastest possible solution.
Furthermore, I am wondering, if firefox has processed any validation of the response's location
header at this state, since I am tending to parse the location
header by using the sdk/url.URL
method, to be sure that the given location
header is valid and no xss scam.
Client request:
GET /garage HTTP/1.1 Host: www.batmans.cave
Server response:
HTTP/1.1 301 Moved Permanently Location: https://batmans.cave/garage/batmobile
Working example (simplified):
const { Ci } = require("chrome");
const LOCATION_HEADER = "location";
...
interfaces: ["nsIWebProgressListener", "nsISupportsWeakReference"],
add(browser) {
try {
browser.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
} catch (error) {}
},
...
/**
* Called when the state has changed for the window being watched changes.
* @see https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIWebProgressListener#onStateChange%28%29
* @param {nsIWebProgress} webProgress
* @param {nsIRequest} request
* @param {nsresult} status
* @param {String} message
*/
onStateChange(webProgress, request, status, message) {
if (status & Ci.nsIWebProgressListener.STATE_REDIRECTING) {
const window = webProgress.DOMWindow;
if (request instanceof Ci.nsIHttpChannel) {
const httpChannel = request.QueryInterface(Ci.nsIHttpChannel);
let location;
httpChannel.visitResponseHeaders(function (header, value) {
if (header.toLowerCase() == LOCATION_HEADER) {
location = value;
}
});
if (location) {
try {
const url = URL(location).toString();
console.log("redirect to", url); // OK! "https://batmans.cave/garage/batmobile"
}
catch (error) {}
}
}
}
}