Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); /* * Modify Headers Header */ function ModifyHeadersHeader() { this.aAction = ""; this.aName = ""; this.aValue = ""; this.aComment = ""; this.aEnabled = false; this.aSelected = true; } ModifyHeadersHeader.prototype = { classDescription: "Modify Headers Header", classID: Components.ID("{6b2f2fc7-a26c-4602-a08d-bd6d065a86e3}"), contractID: "@modifyheaders.mozdev.org/header;1", QueryInterface: XPCOMUtils.generateQI([Components.interfaces.mhIHeader]), get action() { return this.aAction }, set action(action) { this.aAction = action }, get name() { return this.aName }, set name(name) { this.aName = name }, get value() { return this.aValue }, set value(value) { this.aValue = value }, get comment() { return this.aComment }, set comment(comment) { this.aComment = comment }, get enabled() { return this.aEnabled }, set enabled(enabled) { this.aEnabled = enabled }, get selected() { return this.aSelected }, set selected(selected) { this.aSelected = selected }, get wrappedJSObject() { return this }, equals: function(obj) { return (this.action.toLowerCase() == obj.action.toLowerCase() && this.name.toLowerCase() == obj.name.toLowerCase() && this.value.toLowerCase() == obj.value.toLowerCase()) ? true : false; } } /* Defines the modifyheaders service for getting and setting headers */ function ModifyHeadersService() { //dump("\nEntered ModifyHeadersService"); this.headers = new Array(); this.preferencesUtil = new PreferencesUtil(); // Observer service is used to notify observing ModifyHeadersProxy objects that the headers have been updated this.observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); this.initiated = false; this.winOpen = false; //dump("\nExiting ModifyHeadersService"); } /* * Modify Headers Service */ ModifyHeadersService.prototype = { classDescription: "Modify Headers Service", classID: Components.ID("{feb80fc3-9e72-4fc5-bc72-986957ada6cc}"), contractID: "@modifyheaders.mozdev.org/service;1", QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIModifyheaders]), get count() { if (!this.initiated) { this.init(); } //dump("\nReturning the header count: " + this.headers.length); return this.headers.length; }, set count(c) { /* Do nothing */ }, get alwaysOn() { return this.preferencesUtil.getPreference("bool", PreferencesUtil.prefAlwaysOn); }, set alwaysOn(alwaysOn) { this.preferencesUtil.setPreference("bool", PreferencesUtil.prefAlwaysOn, alwaysOn); }, get openAsTab() { return this.preferencesUtil.getPreference("bool", PreferencesUtil.prefOpenAsTab); }, set openAsTab(openAsTab) { this.preferencesUtil.setPreference("bool", PreferencesUtil.prefOpenAsTab, openAsTab); }, get windowOpen() { return this.winOpen; }, set windowOpen(winOpen) { this.winOpen = winOpen; }, // Load the headers from the preferences init: function() { //dump("\nEntered ModifyHeadersService.init") this.headers = new Array(); // Load the headers from the preferences var enabled; var action; var name; var value; var comment; // Read preferences into headersArray var headerCount = this.preferencesUtil.getPreference("int", PreferencesUtil.prefHeaderCount); for (var i=0; i < headerCount; i++) { name = this.preferencesUtil.getPreference("char", PreferencesUtil.prefHeaderName + i); value = this.preferencesUtil.getPreference("char", PreferencesUtil.prefHeaderValue + i); action = this.preferencesUtil.getPreference("char", PreferencesUtil.prefHeaderAction + i); comment = this.preferencesUtil.getPreference("char", PreferencesUtil.prefHeaderComment + i); enabled = this.preferencesUtil.getPreference("bool", PreferencesUtil.prefHeaderEnabled + i); this.addHeader(name, value, action, comment, enabled); } this.initiated = true; //dump("\nExiting ModifyHeadersService.init"); }, getHeader: function(index) { var objHeader = Components.classes["@modifyheaders.mozdev.org/header;1"].createInstance(Components.interfaces.mhIHeader); objHeader.action = this.headers[index]["action"]; objHeader.name = this.headers[index]["name"]; objHeader.value = this.headers[index]["value"]; objHeader.comment = this.headers[index]["comment"]; objHeader.enabled = this.headers[index]["enabled"]; return objHeader; }, getHeaders: function(count) { //dump("\nEntered ModifyHeadersService.getHeaders"); var objHeader = null; var aHeaders = new Array(); for (var i=0; i < this.headers.length; i++) { objHeader = this.getHeader(i); aHeaders[i] = objHeader; } count.value = aHeaders.length; //dump("\nReturning the header object"); return aHeaders; }, getHeadersAsXML: function(strHeaderIndices) { //dump("\nEntered ModifyHeadersService.getHeadersAsJSONString: " + strHeaderIndices); var headerIndices = strHeaderIndices.split(","); var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); var headersXML = parser.parseFromString("", "text/xml"); var root = headersXML.documentElement; // Loop over the values for (var i=0; i < headerIndices.length; i++) { objHeader = this.getHeader(headerIndices[i]); var action = headersXML.createTextNode(objHeader.action); var actionElem = headersXML.createElement("action"); actionElem.appendChild(action); var name = headersXML.createTextNode(objHeader.name); var nameElem = headersXML.createElement("name"); nameElem.appendChild(name); var value = headersXML.createTextNode(objHeader.value); var valueElem = headersXML.createElement("value"); valueElem.appendChild(value); var comment = headersXML.createTextNode(objHeader.comment); var commentElem = headersXML.createElement("comment"); commentElem.appendChild(comment); var header = headersXML.createElement("header"); header.appendChild(actionElem); header.appendChild(nameElem); header.appendChild(valueElem); header.appendChild(commentElem); root.appendChild(header); } var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"].createInstance(Components.interfaces.nsIDOMSerializer); //dump("\nExiting ModifyHeadersService.getHeadersAsJSONString"); // Return a XML string return "" + serializer.serializeToString(headersXML); }, // Adds a header to the headers array addHeader: function(name, value, action, comment, enabled) { //dump("\nEntered ModifyHeadersService.addHeader"); // TODO Validate the arguments // Add the header to the Array var header = new Array(); header["enabled"] = enabled; header["action"] = action; header["name"] = name; header["value"] = value; header["comment"] = comment; this.headers.push(header); this.savePreferences(); //dump("\nExiting ModifyHeadersService.addHeader"); }, setHeader: function(index, name, value, action, comment, enabled) { //dump("\nEntered ModifyHeadersService.setHeader"); // TODO Validate the arguments // Update the values this.headers[index]["enabled"] = enabled; this.headers[index]["action"] = action; this.headers[index]["name"] = name; this.headers[index]["value"] = value; this.headers[index]["comment"] = comment; this.savePreferences() //dump("\nExiting ModifyHeadersService.setHeader") }, // Remove the header with the specified index removeHeader: function(index) { //dump("\nEntered ModifyHeadersService.removeHeader"); this.headers.splice(index, 1); this.savePreferences(); //dump("\nExiting ModifyHeadersService.removeHeader"); }, isHeaderEnabled: function(index) { return this.headers[index]["enabled"]; }, setHeaderEnabled: function(index, enabled) { this.headers[index]["enabled"] = enabled; this.savePreferences(); }, getHeaderAction: function(index) { return this.headers[index]["action"]; }, getHeaderName: function(index) { return this.headers[index]["name"]; }, getHeaderValue: function(index) { return this.headers[index]["value"]; }, getHeaderComment: function(index) { return this.headers[index]["comment"]; }, switchHeaders: function(index1, index2) { var header = this.headers[index1]; this.headers[index1] = this.headers[index2]; this.headers[index2] = header; this.savePreferences(); }, // Persist the headers to the preferences. savePreferences: function() { //dump("\nEntered ModifyHeadersService.savePreferences"); // Only save headers if the service has been initiated if (this.initiated) { // TODO Clear the preferences first // This ensures old headers are not maintained in the preferences // I'm sure there is a better way than this // Loop over the headers for (var i=0; i < this.count; i++) { this.preferencesUtil.setPreference("char", PreferencesUtil.prefHeaderAction + i, this.headers[i]["action"]); this.preferencesUtil.setPreference("char", PreferencesUtil.prefHeaderName + i, this.headers[i]["name"]); this.preferencesUtil.setPreference("char", PreferencesUtil.prefHeaderValue + i, this.headers[i]["value"]); this.preferencesUtil.setPreference("char", PreferencesUtil.prefHeaderComment + i, this.headers[i]["comment"]); this.preferencesUtil.setPreference("bool", PreferencesUtil.prefHeaderEnabled + i, this.headers[i]["enabled"]); } this.preferencesUtil.setPreference("int", PreferencesUtil.prefHeaderCount, this.count); } //dump("\nExiting ModifyHeadersService.savePreferences"); }, // Clear the headers from their preferences clearPreferences: function() { // Loop over the headers for (var i=0; i < this.count; i++) { this.preferencesUtil.deletePreference(PreferencesUtil.prefHeaderAction + i); this.preferencesUtil.deletePreference(PreferencesUtil.prefHeaderEnabled + i); this.preferencesUtil.deletePreference(PreferencesUtil.prefHeaderName + i); this.preferencesUtil.deletePreference(PreferencesUtil.prefHeaderValue + i); this.preferencesUtil.deletePreference(PreferencesUtil.prefHeaderComment + i); } } } /* * Modify Headers Proxy */ function ModifyHeadersProxy() { //dump("\nEntered ModifyHeadersProxy"); this.headers = new Array(); this.preferencesUtil = new PreferencesUtil(); this.modifyheadersService = Components.classes["@modifyheaders.mozdev.org/service;1"].getService(Components.interfaces.nsIModifyheaders); //dump("\nExiting ModifyHeadersProxy"); } ModifyHeadersProxy.prototype = { classDescription: "Modify Headers Proxy", classID: Components.ID("{0eff9eeb-c51a-4f07-9823-27bc32fdae13}"), contractID: "@modifyheaders.mozdev.org/proxy;1", QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]), _xpcom_categories: [ { category: "profile-after-change", entry: "Modify Headers Proxy" } ], // nsIObserver interface method observe: function(subject, topic, data) { //dump("\nEntered ModifyHeadersProxy.prototype.observe"); if (topic == 'http-on-modify-request') { //dump("\ntopic is http-on-modify-request"); subject.QueryInterface(Components.interfaces.nsIHttpChannel); if (this.modifyheadersService.windowOpen || this.modifyheadersService.alwaysOn) { var headerCount = this.modifyheadersService.count; for (var i=0; i < headerCount; i++) { //dump("\niteration: " + i); if (this.modifyheadersService.isHeaderEnabled(i)) { var headerName = this.modifyheadersService.getHeaderName(i); // This is the default for action = Modify var headerValue = this.modifyheadersService.getHeaderValue(i); var headerAppend = false; if (this.modifyheadersService.getHeaderAction(i) == "Add") { headerAppend = true; } else if (this.modifyheadersService.getHeaderAction(i) == "Filter") { headerValue = ""; } //dump("\nAdded header: " + headerName); subject.setRequestHeader(headerName, headerValue, headerAppend); } } // TODO Add an optional ModifyHeaders header so that users know the tool is active // subject.setRequestHeader("x-modifyheaders", "version 0.4", true) } } else if (topic == 'profile-after-change') { //dump("\ntopic is profile-after-change"); if ("nsINetModuleMgr" in Components.interfaces) { // Should be an old version of Mozilla (before september 15, 2003 // Do Nothing as these old versions of firefox (firebird, phoenix etc) are not supported } else { // Should be a new version of Mozilla (after september 15, 2003) var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); observerService.addObserver(this, "http-on-modify-request", false); } } else { //dump("\nNo observable topic defined"); } //dump("\nExiting ModifyHeadersProxy.prototype.observe"); } } //A utility class for getting and setting user preferences function PreferencesUtil() { //dump("\nEntered PreferencesUtil"); this.prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); this.prefService = this.prefService.getBranch(""); //dump("\nExiting PreferencesUtil"); } // Static strings that specify the names of the preferences used by modifyheaders PreferencesUtil.prefAlwaysOn = "modifyheaders.config.alwaysOn"; PreferencesUtil.prefHeaderCount = "modifyheaders.headers.count"; PreferencesUtil.prefHeaderAction = "modifyheaders.headers.action"; PreferencesUtil.prefHeaderEnabled = "modifyheaders.headers.enabled"; PreferencesUtil.prefHeaderName = "modifyheaders.headers.name"; PreferencesUtil.prefHeaderValue = "modifyheaders.headers.value"; PreferencesUtil.prefHeaderComment = "modifyheaders.headers.comment"; PreferencesUtil.prefLogMsgs = "modifyheaders.config.logMsgs"; PreferencesUtil.prefOpenAsTab = "modifyheaders.config.openNewTab"; // Convenience method to get a user preference value PreferencesUtil.prototype.getPreference = function(type, name) { var prefValue; if (this.prefService.prefHasUserValue(name)) { if (type=='bool') { prefValue = this.prefService.getBoolPref(name); } else if (type=='char') { prefValue = this.prefService.getCharPref(name); } else if (type=='int') { prefValue = this.prefService.getIntPref(name); } // Set the preference with a default value } else { if (type=='bool') { this.setPreference(type, name, false); prefValue = false; } else if (type=='char') { this.setPreference(type, name, ""); prefValue = ""; } else if (type=='int') { this.setPreference(type, name, 0); prefValue = 0; } } return prefValue; } // Convenience method to set a user preference PreferencesUtil.prototype.setPreference = function(type, name, value) { if (type=='bool') { this.prefService.setBoolPref(name, value); } else if (type=='char') { this.prefService.setCharPref(name, value); } else if (type=='int') { this.prefService.setIntPref(name, value); } } PreferencesUtil.prototype.deletePreference = function(name) { this.prefService.clearUserPref(name); } /* Entry point - registers the component with the browser */ if (XPCOMUtils.generateNSGetFactory) { //dump("\nUsing NSGetFactory"); var NSGetFactory = XPCOMUtils.generateNSGetFactory([ModifyHeadersService,ModifyHeadersHeader,ModifyHeadersProxy]); } else { //dump("\nUsing NSGetModule"); var NSGetModule = XPCOMUtils.generateNSGetModule([ModifyHeadersService,ModifyHeadersHeader,ModifyHeadersProxy]); }