From 2c30652840889cd2e1c5e15574e93aefdb720fcf Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Sat, 6 Dec 2014 23:52:16 -0500 Subject: Initial commit --- src/bootstrap.js | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 src/bootstrap.js (limited to 'src/bootstrap.js') diff --git a/src/bootstrap.js b/src/bootstrap.js new file mode 100644 index 0000000..2625c92 --- /dev/null +++ b/src/bootstrap.js @@ -0,0 +1,171 @@ +const PORT = 26001; + +if (typeof EIB === "undefined") + var EIB = { + headers: {}, + pending: [] + }; + +const Cc = Components.classes, Ci = Components.interfaces, Cu = Components.utils, CC = Components.Constructor, Cr = Components.results; +const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init"); + +Cu.import("resource://gre/modules/Services.jsm"); + +function install() {} +function uninstall() {} + +EIB.listen = function () { + this.serverSocket = Cc["@mozilla.org/network/server-socket;1"] + .createInstance(Ci.nsIServerSocket); + this.serverSocket.init(PORT, true, -1); + const tm = Cc["@mozilla.org/thread-manager;1"].getService(); + this.serverSocket.asyncListen({ + onSocketAccepted: function (socket, transport) { + var is = transport.openInputStream(0, 0, 0); + var os = transport.openOutputStream(Ci.nsITransport.OPEN_BLOCKING, 0, 0); + var sis = new ScriptableInputStream(is); + var buf = ""; + // TODO: run on separate thread + is.asyncWait({ + onInputStreamReady: function () { + while (sis.available()) { + buf += sis.read(2048); + } + if (buf.indexOf("\n\n") !== 2) { + var headers = {}; + var rx = /\n(EVE_[^:]*): (.*)$/gm, arr; + while ((arr = rx.exec(buf)) !== null) { + headers[arr[1]] = arr[2]; + } + EIB.headers = headers; + + var resp = "HTTP/1.0 200 OK\r\n"; + resp += "Content-Type: text/html\r\n\r\n"; + resp += "EVE-IGB Bridge"; + if (headers["EVE_TRUSTED"]) { + resp += ""; + resp += headers["EVE_TRUSTED"] == "Yes" ? + "Connected to the EVE-IGB Bridge. Please do not close this window. You may minimize it, however. Note that this window will refresh repeatedly; this does not indicate a malfunction and will not count towards your internet data usage if you have one." : + "Please grant trust to this site, then refresh the page."; + resp += ""; + } else { + resp += "Please open this page in the EVE in-game browser."; + } + os.write(resp, resp.length); + + is.close(); + os.close(); + } + } + }, 0, 0, tm.mainThread); + } + }); +} + +var HttpObserver = { + observe: function (subject, topic, data) { + var channel = subject.QueryInterface(Ci.nsIHttpChannel); + // TODO: is this secure? + if (checkTrusted(channel.URI.specIgnoringRef)) { + for (var header in EIB.headers) { + channel.setRequestHeader(header, EIB.headers[header], false); + } + } + } +}; + +function forEachOpenWindow(todo) { + var windows = Services.wm.getEnumerator("navigator:browser"); + while (windows.hasMoreElements()) + todo(windows.getNext().QueryInterface(Ci.nsIDOMWindow)); +} + +var WindowListener = { + onOpenWindow: function(xulWindow) + { + var window = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + function onWindowLoad() + { + window.removeEventListener("load", onWindowLoad); + if (window.document.documentElement.getAttribute("windowtype") == "navigator:browser") + loadIntoWindow(window); + } + window.addEventListener("load", onWindowLoad); + }, + onCloseWindow: function(xulWindow) {}, + onWindowTitleChange: function(xulWindow, newTitle) {} +}; + +var TrustedReparser = { + observe: function () { + EIB.trusted = JSON.parse(EIB.prefs.getCharPref("trusted")); + } +}; + +function startup(data, reason) { + EIB.listen(); + + EIB.prefs = Services.prefs.getBranch("extensions.eib."); + EIB.prefs.addObserver("trusted", TrustedReparser, false); + reparseTrusted(); + + forEachOpenWindow(loadIntoWindow); + Services.wm.addListener(WindowListener); + + Services.obs.addObserver(HttpObserver, "http-on-modify-request", false); +} + +function shutdown(data, reason) { + if (reason === APP_SHUTDOWN) + return; + + if (EIB.serverSocket) + EIB.serverSocket.close(); + delete EIB.serverSocket; + + EIB.prefs.removeObserver("trusted", TrustedReparser); + + forEachOpenWindow(unloadFromWindow); + Services.wm.removeListener(WindowListener); + + Services.obs.removeObserver(HttpObserver, "http-on-modify-request"); +} + +function checkTrusted(href) { + for (var i = 0; i < EIB.trusted.length; i++) + if (href.indexOf(EIB.trusted[i]) === 0) + return true; + return false; +} + +function injectCCPEVE(e) { + var window = e.originalTarget.defaultView; + if (checkTrusted(window.location.href)) { + var CCPEVE = Cu.createObjectIn(window, {defineAs: "CCPEVE"}); + ["openEveMail", "showInfo", "showPreview", "showRouteTo", "showMap", "showFitting", "showContract", "showMarketDetails", "setDestination", "addWaypoint", "joinChannel", "joinMailingList", "createContract", "buyType", "findInContracts", "addToMarketQuickBar", "addContact", "removeContact", "addCorpContact", "removeCorpContact", "block", "addBounty", "inviteToFleet", "startConversation", "showContracts", "showOnMap", "editMember", "awardDecoration", "sendMail", "showContents", "bookmark"].forEach(function (n) { + Cu.exportFunction(function () { + EIB.pending.push('CCPEVE.' + n + '(' + Array.prototype.join.call(arguments, ',') + ');'); + return null; + }, CCPEVE, {defineAs: n}); + }); + } +} + +function loadIntoWindow(window) { + window.document.getElementById("appcontent").addEventListener("DOMContentLoaded", injectCCPEVE, false); +} + +function unloadFromWindow(window) { + window.document.getElementById("appcontent").removeEventListener("DOMContentLoaded", injectCCPEVE, false); +} -- cgit v1.2.3-54-g00ecf