I used to have the extension Header Spy https://addons.mozilla.org/fr/firefox/addon/header-spy/ before Firefox 45. With Status4Evar to display the status bar (I will never understand why there is no more status bar) it still works perfectly.
Now it seems that Firefox changes something and the extension does not receive any HTTP headers (and display "*none*" or nothing depending on the options).
Can someone help me to make it work again? I don't find any replacement so easy to use than the tooltip from this one.
The header_spy.js file is like following. At the beginning it's written "based on livehttpheaders code" so I download it to compare but I don't know enough extension development to understand.
Code: Select all
// ---
var header_spy = {
options: null,
hdr_request: "REQUEST",
hdr_response: "RESPONSE",
// will be updated on tab change
request_uri: null,
headers_request : {"None": "None"},
headers_request_idx : {"none": "None"},
headers_response : {"None": "None"},
headers_response_idx : {"none": "None"},
get_headers: function(theDocument) {
if ("header_spy_headers" in theDocument) {
return theDocument.header_spy_headers;
} else if (theDocument && 'defaultView' in theDocument && 'controllers' in theDocument.defaultView) {
// based on livehttpheaders code
var controllers = theDocument.defaultView.controllers
while (controllers.wrappedJSObject) {
controllers = controllers.wrappedJSObject
}
var controller = controllers.getControllerForCommand('header_spy_headers');
if (!controller) return false;
// The controller might be wrapped multiple times
while (controller && !('headers' in controller)) {
controller = controller.wrappedJSObject;
}
if (controller && controller.url == theDocument.defaultView.location.href) {
headers = controller.headers;
}
}
return null;
},
get_headers_request: function(header_spy_headers, headers_idx) {
var headers = [];
if (header_spy_headers) {
//headers[header_spy.hdr_request] = header_spy_headers.request;
headers_idx[header_spy.hdr_request.toLowerCase()] = header_spy.hdr_request;
headers[header_spy.hdr_request.toLowerCase()] = header_spy_headers.request;
for (i in header_spy_headers.requestHeaders) {
//headers[i] = header_spy_headers.requestHeaders[i];
headers_idx[i.toLowerCase()] = i;
headers[i.toLowerCase()] = header_spy_headers.requestHeaders[i];
}
}
return headers;
},
get_headers_response: function(header_spy_headers, headers_idx) {
var headers = [];
if (header_spy_headers) {
//headers[header_spy.hdr_response] = header_spy_headers.response;
headers_idx[header_spy.hdr_response.toLowerCase()] = header_spy.hdr_response;
headers[header_spy.hdr_response.toLowerCase()] = header_spy_headers.response;
for (i in header_spy_headers.responseHeaders) {
//headers[i] = header_spy_headers.responseHeaders[i];
headers_idx[i.toLowerCase()] = i;
headers[i.toLowerCase()] = header_spy_headers.responseHeaders[i];
}
//for (i in header_spy_headers.responseHeaders) {
// // Server can send some headers multiple times...
// // Try to detect this and present them in the "good" way.
// var multi = header_spy_headers.responseHeaders[i].split('\n');
// for (var o in multi) {
// responseheaders.addRow([i, multi[o]]);
// }
//}
}
return headers;
},
fetch_headers: function(headers, headers_idx, i, _popup_headers, v_headers, v_values) {
// var v_headers = [];
// var v_values = [];
var ph_array = [];
if (_popup_headers == "*") { // all headers
//ph_array = headers;
// TODO optimize for speed?
for (i in headers) {
ph_array.push(i); // copy headers names
}
} else {
ph_array = _popup_headers.split(' ');
}
for (var ph in ph_array) {
var header_name = ph_array[ph].toLowerCase(); // low case
var header_value = headers[header_name];
if (header_name.length == 0) break;
if (header_value == null) { // no value
if (this.options.panels[i].popup_headers.show_if_exist) continue;
header_value = header_spy_options_store.defaults.status;
}
// Server can send some headers multiple times...
// Try to detect this and present them in the "good" way.
var multi = header_value.split('\n');
for (var o in multi) {
//v_headers.push(headers_idx[header_name]); // real case
var hn = headers_idx[header_name]; // real case
if (hn == undefined) hn = ph_array[ph]; // case from settings
v_headers.push(hn); // name vs real case
v_values.push(multi[o]);
}
}
},
populate_tooltip_init: function(i) {
var vbx = document.getElementById(this.options.panels[i].sbp_tooltip);
if (vbx) {
while (vbx.firstChild) vbx.removeChild(vbx.firstChild); // clear list
}
return vbx;
},
populate_tooltip: function(headers, headers_idx, i, _popup_headers, vbx, _title) {
var v_headers = [];
var v_values = [];
this.fetch_headers(headers, headers_idx, i, _popup_headers, v_headers, v_values);
if (0 == v_headers.length) return 0;
// ---
var egroupbox, evbox_names, evbox_values, ename, evalue;
evbox_names = document.createElement("vbox");
evbox_values = document.createElement("vbox");
var wrap_on = this.options.panels[i].popup_headers.wrap_on;
for (j in v_headers) {
var sh = v_headers[j], sv, svrest = v_values[j];
for ( ; ; ) {
if (wrap_on <= 0) { // don't wrap
sv = svrest;
svrest = "";
} else {
sv = svrest.substring(0, wrap_on);
svrest = svrest.substring(wrap_on);
}
ename = evbox_names.appendChild(document.createElement("label"));
ename.setAttribute("value", sh);
ename.setAttribute("style", "font-weight: 900;");
evalue = evbox_values.appendChild(document.createElement("label"));
//evalue.setAttribute("style", "width: 500px;");
evalue.setAttribute("crop", "right");
evalue.setAttribute("value", sv);
if (0 == svrest.length) break; // no more to show
sh = null; // don't show header on wrapped lines
}
}
egroupbox = vbx.appendChild(document.createElement("groupbox"));
evalue = egroupbox.appendChild(document.createElement("hbox"));
evalue.appendChild(evbox_names);
evalue.appendChild(evbox_values);
ename = egroupbox.appendChild(document.createElement("caption"));
ename.setAttribute("label", _title);
return v_headers.length;
},
populate_menu: function(headers, headers_idx, i, _popup_headers, vbx, _title, _title_hint) {
var v_headers = [];
var v_values = [];
this.fetch_headers(headers, headers_idx, i, _popup_headers, v_headers, v_values);
if (0 == v_headers.length) return 0;
// ---
var ename, emenu, emenupopup;
ename = vbx.appendChild(document.createElement("menuitem"));
ename.setAttribute("label", _title);
ename.setAttribute("style", "font-weight: 900;"); // bold
ename.setAttribute("onclick", "header_spy.copy2clipboard(this.value)");
ename.setAttribute("tooltiptext", _title_hint);
// ---
var sh_prev, x_txt = "";
for (j in v_headers) {
var sh = v_headers[j], sv = v_values[j];
x_txt = x_txt
+ (sh == header_spy.hdr_request || sh == header_spy.hdr_response ? "" : sh + ": ")
+ (sv != header_spy_options_store.defaults.status ? sv : "") // don't print dumb value "* none *"
+ '\n'; // collect headers as plain text
if (sh == sh_prev) continue; // skip the same name
for (var k = 1 + parseInt(j) ; k < v_headers.length && sh == v_headers[k] ; k++) sv += '\n' + v_values[k];
emenu = vbx.appendChild(document.createElement("menu"));
emenu.setAttribute("label", sh);
//emenu.setAttribute("tooltip", sv); // pass to submenu
//emenu.setAttribute("tooltip", sh + '\1' + sv); // pass to submenu
emenu.setAttribute("value", sh + '\1' + sv); // pass to submenu
emenupopup = emenu.appendChild(document.createElement("menupopup"));
emenupopup.addEventListener("popupshowing", header_spy.populate_menu_item, true);
/* WTF?
ename = emenupopup.appendChild(document.createElement("menuitem"));
//emenu.setAttribute("style", "width: 500px;");
//ename.setAttribute("crop", "right");
ename.setAttribute("label", sv);
*/
sh_prev = sh;
}
ename.setAttribute("value", x_txt);
vbx.appendChild(document.createElement("menuseparator"));
return v_headers.length;
},
populate_menu_item_cookie: function(emenupopup, multi, hint) {
//var multi = cookie_value.split("; ");
for (var o in multi) {
var mo_comb = multi[o];
if (mo_comb != header_spy_options_store.defaults.status) { // it's not dumb value "* none *"
var mo = multi[o].split('=');
var mo_name = mo[0];
var mo_value = mo.length > 1 ? decodeURIComponent(mo[1]) : "";
mo_comb = mo_name + "=" + mo_value;
}
var mi = document.createElement("menuitem");
//FIXIT breaks copy2clipboard? mi.setAttribute("class", "menuitem-non-iconic");
mi.setAttribute("label", mo_comb);
mi.setAttribute("value", mo_comb);
/*
var ename, mi = document.createElement("hbox");
var evbox1 = mi.appendChild(document.createElement("vbox"));
var evbox2 = mi.appendChild(document.createElement("vbox"));
var evbox3 = mi.appendChild(document.createElement("vbox"));
ename = evbox1.appendChild(document.createElement("label"));
ename.setAttribute("value", mo_name);
ename.setAttribute("style", "font-weight: 900;"); // bold
ename = evbox2.appendChild(document.createElement("label"));
ename.setAttribute("value", "=");
ename = evbox3.appendChild(document.createElement("label"));
ename.setAttribute("value", mo_value);
*/
mi.setAttribute("onclick", "header_spy.copy2clipboard(this.value)");
mi.setAttribute("tooltiptext", hint);
emenupopup.appendChild(mi);
}
},
populate_menu_item: function(event) {
var localeProperties = document.getElementById("header-spy-locale-properties");
var hint = localeProperties.getString("header_spy.popup_hint");
var emenupopup = event.target;
// var cookie_name = emenupopup.parentNode.label;
// var cookie_value = emenupopup.parentNode.tooltip;
//var multi = emenupopup.parentNode.tooltip.split('\1');
var multi = emenupopup.parentNode.value.split('\1');
var cookie_name = multi[0];
var cookie_value = multi[1];
while (emenupopup.firstChild) emenupopup.removeChild(emenupopup.firstChild); // clear list
//var ename = emenupopup.appendChild(document.createElement("menuitem"));
var mi = document.createElement("menuitem");
//FIXIT breaks copy2clipboard? mi.setAttribute("class", "menuitem-non-iconic");
mi.setAttribute("label", cookie_value);
mi.setAttribute("value", cookie_value);
mi.setAttribute("onclick", "header_spy.copy2clipboard(this.value)");
mi.setAttribute("tooltiptext", hint);
emenupopup.appendChild(mi);
if ("COOKIE" == cookie_name.toUpperCase()) {
var multi = cookie_value.split("; ");
// if (multi.length > 1) { // more than one value
mi.setAttribute("style", "font-weight: 900;"); // bold
emenupopup.appendChild(document.createElement("menuseparator"));
// FIXIT why not "this."?
header_spy.populate_menu_item_cookie(emenupopup, multi, hint); // only one Set-Cookie
// }
} else if ("SET-COOKIE" == cookie_name.toUpperCase()) {
var multi = cookie_value.split('\n');
if (multi.length <= 1) {
if (header_spy.options.expand_cookie_in_menu) { // FIXIT why not "this."?
mi.setAttribute("style", "font-weight: 900;"); // bold
// FIXIT why not "this."?
header_spy.populate_menu_item_cookie(emenupopup, cookie_value.split("; "), hint); // only one Set-Cookie
}
} else { // more than one Set-Cookie
emenupopup.appendChild(document.createElement("menuseparator"));
for (var o in multi) {
mi = document.createElement("menuitem");
//FIXIT breaks copy2clipboard? mi.setAttribute("class", "menuitem-non-iconic");
mi.setAttribute("label", multi[o]);
mi.setAttribute("value", multi[o]);
mi.setAttribute("onclick", "header_spy.copy2clipboard(this.value)");
mi.setAttribute("tooltiptext", hint);
emenupopup.appendChild(mi);
if (header_spy.options.expand_cookie_in_menu) { // FIXIT why not "this."?
mi.setAttribute("style", "font-weight: 900;"); // bold
// FIXIT why not "this."?
header_spy.populate_menu_item_cookie(emenupopup, multi[o].split("; "), hint);
}
}
}
}
event.stopPropagation();
},
copy2clipboard: function(copyThis) {
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
if (!str) return false; // couldn't get thingamajig
str.data = copyThis.replace("\n", "\r\n", "g"); // unicode string? // FIXIT \r\n - is this portable? // "g" - Global
// str.data = copyThis;
var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if (!trans) return false; //no transferable widget found
trans.addDataFlavor("text/unicode");
trans.setTransferData("text/unicode", str, str.data.length * 2); // *2 cuz it's unicode
var clipid = Components.interfaces.nsIClipboard;
var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid);
if (!clip) return false; // couldn't get the clipboard
clip.setData(trans, null, clipid.kGlobalClipboard);
},
rebuild: function(aWebProgress) {
var do_clear_panels = true;
var do_clear_headers = true;
if (aWebProgress != null
//??? && !aWebProgress.isLoadingDocument
&& ("DOMWindow" in aWebProgress)
) {
var header_spy_headers = this.get_headers(aWebProgress.DOMWindow);
if (header_spy_headers) {
do_clear_panels = false; // don't touch states
do_clear_headers = false;
this.request_uri = header_spy_headers.request_uri;
this.headers_request_idx = [];
this.headers_response_idx = [];
this.headers_request = this.get_headers_request(header_spy_headers, this.headers_request_idx);
this.headers_response = this.get_headers_response(header_spy_headers, this.headers_response_idx);
for (i = 0 ; i < this.options.panels.length ; i++) {
var value = this.options.panels[i].header;
//value = (0 == this.options.panels[i].headersrc ? this.headers_request[value] : this.headers_response[value]);
value = (0 == this.options.panels[i].headersrc ? this.headers_request[value.toLowerCase()] : this.headers_response[value.toLowerCase()]);
this.options.panels[i].current_status = value ? value : header_spy_options_store.defaults.status;
// this.create_tooltip(i);
}
}
/*
} else if (aWebProgress != null
&& aWebProgress.isLoadingDocument
&& 0 == this.headers_request.length
) {
return; // do nothing on progress
*/
}
if (do_clear_headers) {
this.headers_request = [];
this.headers_request_idx = [];
this.headers_response = [];
this.headers_response_idx = [];
}
if (do_clear_panels) { // reset states
for (i = 0 ; i < this.options.panels.length ; i++) {
this.options.panels[i].current_status = header_spy_options_store.defaults.status;
}
}
for (i = 0 ; i < this.options.panels.length ; i++) {
var el_status = document.getElementById(this.options.panels[i].sbp_name);
if (!el_status) continue;
el_status.crop = "end";
el_status.minWidth = this.options.panels[i].min_width;
el_status.maxWidth = this.options.panels[i].max_width;
el_status.label = this.options.panels[i].show_name
? (this.options.panels[i].header + ": " + this.options.panels[i].current_status)
: this.options.panels[i].current_status;
el_status.collapsed = (
this.options.panels[i].current_status == header_spy_options_store.defaults.status
&& this.options.panels[i].show_if_exist
);
}
},
create_tooltip: function(i) {
if (null == i) i = 0;
var vbx = this.populate_tooltip_init(i);
if (vbx) {
var ttcnt = 0;
if (this.options.panels[i].popup_headers.in_tooltip) {
ttcnt += this.populate_tooltip(
this.headers_request, this.headers_request_idx, i, this.options.panels[i].popup_headers.request
, vbx, "Request");
ttcnt += this.populate_tooltip(
this.headers_response, this.headers_response_idx, i, this.options.panels[i].popup_headers.response
, vbx, "Response");
}
if (0 == ttcnt) { // there is no valid headers to show. We need to show default tooltip
var el_status = document.getElementById(this.options.panels[i].sbp_name);
if (el_status) {
var ename = document.createElement("label");
ename.setAttribute("value", el_status.label);
vbx.appendChild(ename);
}
}
}
},
options_dialog: function() {
// return toOpenWindowByType("global:HeaderSpyOptions", "chrome://header_spy/content/options.xul");
var winOptions = openDialog("chrome://header_spy/content/options.xul",
"HeaderSpyOptions",
"centerscreen,chrome,resizable=no,dialog=no");
try {
winOptions.focus();
} catch(ex) {
}
},
whoishostingthis_dialog: function(host) {
url = "http://www.whoishostingthis.com/" + host + "?source=HeaderSpy";
//window.open(url, 'WhoIsHostingThis ' + host, '');
gBrowser.selectedTab = gBrowser.addTab(url, null, null, null);
},
onclick: function(i, event) {
// return (2 == event.button) ? this.create_menu(i) : this.full_view(i);
if (0 == event.button) this.full_view(i); // Note: RClick - options
},
full_view: function(i) {
if (null == i) i = 0;
var el_status = document.getElementById(this.options.panels[i].sbp_name);
if (el_status.maxWidth == header_spy_options_store.defaults.max_expand_width) {
el_status.maxWidth = this.options.panels[i].max_width;
} else {
el_status.maxWidth = header_spy_options_store.defaults.max_expand_width;
}
el_status.collapsed = false;
},
create_menu: function(i) {
var vbx = document.getElementById(this.options.panels[i].sbp_menu)
if (!vbx) return;
while (vbx.firstChild) vbx.removeChild(vbx.firstChild);
// ---
if (this.options.panels[i].popup_headers.in_menu) {
var localeProperties = document.getElementById("header-spy-locale-properties");
var ttcnt;
ttcnt += this.populate_menu(
this.headers_request, this.headers_request_idx, i, this.options.panels[i].popup_headers.request
, vbx, "Request", localeProperties.getString("header_spy.popup_hint_request"));
ttcnt += this.populate_menu(
this.headers_response, this.headers_response_idx, i, this.options.panels[i].popup_headers.response
, vbx, "Response", localeProperties.getString("header_spy.popup_hint_response"));
//vbx.appendChild(document.createElement("menuseparator"));
}
// ---
//var host = aRequest.QueryInterface(Components.interfaces.nsIChannel).URI.host;
var host = null;
try {
var x_uri = HEADER_SPY_IOSERVICE.newURI(this.request_uri, null, null);
//if (x_uri.schemeIs("http") || x_uri.schemeIs("https") || x_uri.schemeIs("ftp")) {
host = x_uri.host.replace(/^www\./i, ""); // .asciiHost
//}
} catch (e) {
// FIXIT the URI is not an URI?
}
// ---
var mi, localeProperties = document.getElementById("header-spy-locale-properties");
/*
if (host != null) {
mi = document.createElement("menuitem");
mi.setAttribute("label", localeProperties.getString("header_spy.open_whoishostingthis"));
mi.setAttribute("onclick", "header_spy.whoishostingthis_dialog('" + host.replace(/'/g, "\\'") + "')"); // whoishostingthis.com
vbx.appendChild(mi);
}
*/
mi = document.createElement("menuitem");
mi.setAttribute("label", localeProperties.getString("header_spy.open_pageinfo"));
mi.setAttribute("onclick", "BrowserPageInfo(event.target.document, \"headerinfoTab\")"); // "Live HTTP Headers" tab
vbx.appendChild(mi);
mi = document.createElement("menuitem");
mi.setAttribute("label", localeProperties.getString("header_spy.options"));
mi.setAttribute("onclick", "header_spy.options_dialog()");
vbx.appendChild(mi);
}
};
// ---
/*
* onemen.one@gmail.com : the bug is in header_spy.js call to eval gBrowser.addTab before content is fully loaded.
* Reason: http://developer.mozilla.org/en/docs/Code_snippets:Tabbed_browser :
*** "You can access gBrowser only after the browser window is fully loaded.
*** If you need to do something with gBrowser right after the window is opened,
*** listen for the load event and use gBrowser in the event listener."
* I've removed this code because it is obsolete now. We don't support FF 1.5
eval("gBrowser.addTab =" + getBrowser().addTab.toString().replace(
"if (!blank) {",
"if (blank) header_spy.rebuild(null); if (!blank) {"
)
);
*/
var header_spy_prefs_observer = {
observe: function(aSubject, aTopic, aState)
{
if (aTopic == "header-spy-load-prefs") {
header_spy.options = header_spy_options_store.get();
//document.getElementById("header-spy-tools-menu-item").setAttribute("hidden", !header_spy.options.show_tools_menu_item);
header_spy_apply_global_options();
for (i = 0 ; i < header_spy.options.panels.length ; i++) {
var el_status = document.getElementById(header_spy.options.panels[i].sbp_name);
if (!el_status) continue;
el_status.crop = "end";
el_status.minWidth = header_spy.options.panels[i].min_width;
el_status.maxWidth = header_spy.options.panels[i].max_width;
}
for ( ; ; i++) {
var hso = header_spy_options_store.get_rec(i);
var el_status = document.getElementById(hso.sbp_name);
if (!el_status) break;
el_status.collapsed = true; // collapse unused panels
}
}
},
};
// --------------------------------
function header_spy_apply_global_options()
{
var options = header_spy_options_store.get();
var el = document.getElementById("header-spy-tools-menu-item");
if (el) el.setAttribute("hidden", !options.show_tools_menu_item);
}
function header_spy_register_ASL()
{
HEADER_SPY_OBSERVER_SERVICE.addObserver(header_spy_prefs_observer, "header-spy-load-prefs", false);
HEADER_SPY_OBSERVER_SERVICE.notifyObservers(header_spy_prefs_observer, "header-spy-load-prefs", false);
header_spy_adv_status_listener.init();
//gBrowser.addProgressListener(header_spy_adv_status_listener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
// "Error: gBrowser.addProgressListener was called with a second argument, which is not supported. See bug 608628."
gBrowser.addProgressListener(header_spy_adv_status_listener);
header_spy_apply_global_options();
header_spy.rebuild(null); // on browser window load
}
function header_spy_unregister_ASL()
{
gBrowser.removeProgressListener(header_spy_adv_status_listener);
header_spy_adv_status_listener.destroy();
HEADER_SPY_OBSERVER_SERVICE.removeObserver(header_spy_prefs_observer, "header-spy-load-prefs");
}
window.addEventListener("load", header_spy_register_ASL, false);
window.addEventListener("unload", header_spy_unregister_ASL, false);
// --------------------------------
var header_spy_adv_status_listener =
{
QueryInterface: function(aIID) {
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
aIID.equals(Components.interfaces.nsISupports) ||
aIID.equals(Components.interfaces.nsIHttpNotify) ||
aIID.equals(Components.interfaces.nsIObserver)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) {
if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START)
//&& (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_NETWORK)//STATE_IS_DOCUMENT)
) {
header_spy.rebuild(aWebProgress);
} else if ((aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
//&& (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW)//STATE_IS_DOCUMENT)
//&& !aWebProgress.isLoadingDocument
) {
header_spy.rebuild(aWebProgress);
}
},
onProgressChange: function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) {
},
onLocationChange: function(aWebProgress, aRequest, aLocation) {
header_spy.rebuild(aWebProgress);
//?window.XULBrowserWindow.onLocationChange(aWebProgress, aRequest, aLocation);
},
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {
},
onSecurityChange: function(aWebProgress, aRequest, aState) {
},
//onLinkIconAvailable: function(a) {
//},
// ---
init: function() {
},
destroy: function() {
},
};
// --------------------------------