From 74ea762eef32df4bc459fe48247ab32049138e8a Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Tue, 9 Dec 2014 19:18:15 -0500 Subject: Add features, XHR long polling. --- src/.jshintrc | 3 + src/bootstrap.js | 143 +++++++++++++++++++++------------- src/chrome/content/igb/trusted.html | 10 +++ src/chrome/content/igb/trusted.js | 15 ++++ src/chrome/content/igb/unknown.html | 9 +++ src/chrome/content/igb/untrusted.html | 12 +++ 6 files changed, 137 insertions(+), 55 deletions(-) create mode 100644 src/.jshintrc create mode 100644 src/chrome/content/igb/trusted.html create mode 100644 src/chrome/content/igb/trusted.js create mode 100644 src/chrome/content/igb/unknown.html create mode 100644 src/chrome/content/igb/untrusted.html diff --git a/src/.jshintrc b/src/.jshintrc new file mode 100644 index 0000000..0460aba --- /dev/null +++ b/src/.jshintrc @@ -0,0 +1,3 @@ +{ + "moz": true +} diff --git a/src/bootstrap.js b/src/bootstrap.js index 162c857..0fbc56e 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -6,70 +6,88 @@ if (typeof EIB === "undefined") 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"); +const FileInputStream = CC("@mozilla.org/network/file-input-stream;1", "nsIFileInputStream", "init"); +const LocalFileFromPath = CC("@mozilla.org/file/local;1", "nsILocalFile", "initWithPath"); 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(26001, 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]; - } +var ServerListener = { + 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 = ""; + is.asyncWait({ + onInputStreamReady: function () { + while (sis.available()) + buf += sis.read(2048); + + if (buf.indexOf("\r\n\r\n") > -1) { + is.close(); + + // parse out headers + var headers = {}; + var rx = /\n(EVE_[^:]*): (.*)$/gm, arr; + while ((arr = rx.exec(buf)) !== null) + headers[arr[1]] = arr[2]; + + if (headers.EVE_TRUSTED == "Yes") 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(); + }, null); + } else { os.close(); } } - }, 0, 0, tm.mainThread); - } - }); -} + } + }, 0, 0, Services.tm.mainThread); + } +}; + +EIB.listen = function () { + this.serverSocket = Cc["@mozilla.org/network/server-socket;1"] + .createInstance(Ci.nsIServerSocket); + this.serverSocket.init(26001, true, -1); + this.serverSocket.asyncListen(ServerListener); +}; var HttpObserver = { observe: function (subject, topic, data) { @@ -108,7 +126,7 @@ var WindowListener = { var TrustedReparser = { observe: function () { EIB.trusted = EIB.prefs.prefHasUserValue("trusted") ? - JSON.parse(EIB.prefs.getCharPref("trusted").map(function (v) { return new RegExp(v); }) : + JSON.parse(EIB.prefs.getCharPref("trusted")).map(function (v) { return new RegExp(v); }) : []; } }; @@ -130,6 +148,10 @@ function shutdown(data, reason) { if (reason === APP_SHUTDOWN) return; + if (EIB.stream) + EIB.stream.close(); + delete EIB.stream; + if (EIB.serverSocket) EIB.serverSocket.close(); delete EIB.serverSocket; @@ -148,14 +170,25 @@ function checkTrusted(href) { }); } +// We can't get this from the IGB because the properties aren't enumerable and it doesn't implement Object.getOwnPropertyNames. +// We could test if the functions are available, but since there's only one IGB version, that wouldn't be particularly useful. +const exportFunctions = ["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"]; + 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) { + exportFunctions.forEach(function (n) { Object.defineProperty(CCPEVE, n, { value: Cu.exportFunction(function () { - EIB.pending.push('CCPEVE.' + n + '(' + JSON.stringify([].slice.call(arguments)).slice(1, -1) + ');'); + if (EIB.stream) { + var resp = "HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n"; + var str = JSON.stringify([n, [].slice.call(arguments)]) + "\r\n"; + resp += "Content-Length: " + str.length + "\r\n\r\n" + str; + EIB.stream.write(resp, resp.length); + EIB.stream.close(); + } + delete EIB.stream; return null; }, CCPEVE) }); diff --git a/src/chrome/content/igb/trusted.html b/src/chrome/content/igb/trusted.html new file mode 100644 index 0000000..8867b73 --- /dev/null +++ b/src/chrome/content/igb/trusted.html @@ -0,0 +1,10 @@ + + + + EVE-IGB Bridge + + + +

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.

+ + diff --git a/src/chrome/content/igb/trusted.js b/src/chrome/content/igb/trusted.js new file mode 100644 index 0000000..3c6a6c7 --- /dev/null +++ b/src/chrome/content/igb/trusted.js @@ -0,0 +1,15 @@ +window.onerror = function (e) { alert(e); }; +var xhr = new XMLHttpRequest(); +xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var obj = JSON.parse(xhr.responseText); + CCPEVE[obj[0]].apply(CCPEVE, obj[1]); + // IGB imposes a 1s delay between JS calls + setTimeout(function () { + xhr.open("GET", "trusted"); + xhr.send(); + }, 1000); + } +}; +xhr.open("GET", "trusted"); +xhr.send(); diff --git a/src/chrome/content/igb/unknown.html b/src/chrome/content/igb/unknown.html new file mode 100644 index 0000000..51170b3 --- /dev/null +++ b/src/chrome/content/igb/unknown.html @@ -0,0 +1,9 @@ + + + + EVE-IGB Bridge + + +

Please open this site in the EVE in-game browser.

+ + diff --git a/src/chrome/content/igb/untrusted.html b/src/chrome/content/igb/untrusted.html new file mode 100644 index 0000000..1cb7499 --- /dev/null +++ b/src/chrome/content/igb/untrusted.html @@ -0,0 +1,12 @@ + + + + EVE-IGB Bridge + + + +

Please grant trust to this site, then refresh the page.

+ + -- cgit v1.2.3-54-g00ecf