diff options
author | Alex Xu <alex_y_xu@yahoo.ca> | 2014-12-09 19:18:15 -0500 |
---|---|---|
committer | Alex Xu <alex_y_xu@yahoo.ca> | 2014-12-09 22:03:17 -0500 |
commit | 74ea762eef32df4bc459fe48247ab32049138e8a (patch) | |
tree | 90d83730375d104a45571ee73f7a6211ebb4119b | |
parent | 3a93c00d336cc9e9201e41a9bacfcd2e916368b7 (diff) | |
download | eib-74ea762eef32df4bc459fe48247ab32049138e8a.tar.xz eib-74ea762eef32df4bc459fe48247ab32049138e8a.zip |
Add features, XHR long polling.
-rw-r--r-- | src/.jshintrc | 3 | ||||
-rw-r--r-- | src/bootstrap.js | 143 | ||||
-rw-r--r-- | src/chrome/content/igb/trusted.html | 10 | ||||
-rw-r--r-- | src/chrome/content/igb/trusted.js | 15 | ||||
-rw-r--r-- | src/chrome/content/igb/unknown.html | 9 | ||||
-rw-r--r-- | src/chrome/content/igb/untrusted.html | 12 |
6 files changed, 137 insertions, 55 deletions
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 += "<!DOCTYPE html><html><head><title>EVE-IGB Bridge</title>"; - if (headers["EVE_TRUSTED"]) { - resp += '<script>'; - if (headers["EVE_TRUSTED"] == "Yes") { - var delay = 100; - if (EIB.pending.length) { - resp += EIB.pending.shift(); - delay = 1000; - } - resp += 'setTimeout(function () { location.reload(); }, ' + delay + ');'; - } else { - resp += 'CCPEVE.requestTrust("http://127.0.0.1:' + EIB.serverSocket.port + '");'; + // figure out what we're responding with + var type, file, code; + switch (/ ([^ ]*) /.exec(buf)[1]) { + case '/': + type = "text/html; charset=UTF-8"; + file = headers.EVE_TRUSTED === "Yes" ? "trusted.html" : + headers.EVE_TRUSTED === "No" ? "untrusted.html" : + "unknown.html"; + break; + case '/trusted.js': + type = "application/javascript"; + file = "trusted.js"; + break; + case '/trusted': + if (EIB.stream) + EIB.stream.close(); + EIB.stream = os; + return; + } + + // build the response + var resp = "HTTP/1.0 " + (type ? + "200 OK\r\nContent-Type: " + type + "\r\n\r\n" : + "404 Not Found\r\nContent-Type: text/plain\r\n\r\n404 Not Found\r\n"); + os.write(resp, resp.length); + if (file) { + var channel = Services.io.newChannel("chrome://eib/content/igb/" + file, null, null); + channel.asyncOpen({ + onStartRequest: function () {}, + onDataAvailable: function (req, ctx, fis, offset, cnt) { + os.writeFrom(fis, cnt); + }, + onStopRequest: function (req, ctx, status) { + os.close(); } - resp += "</script></head><body>"; - 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 += "</body></html>"; - } else { - resp += "</head><body>Please open this page in the EVE in-game browser.</body></html>"; - } - 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 @@ +<!DOCTYPE html> +<html> + <head> + <title>EVE-IGB Bridge</title> + <script src="trusted.js"></script> + </head> + <body> + <p>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.</p> + </body> +</html> 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 @@ +<!DOCTYPE html> +<html> + <head> + <title>EVE-IGB Bridge</title> + </head> + <body> + <p>Please open this site in the EVE in-game browser.</p> + </body> +</html> 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 @@ +<!DOCTYPE html> +<html> + <head> + <title>EVE-IGB Bridge</title> + <script> + CCPEVE.requestTrust("http://127.0.0.1:26001"); + </script> + </head> + <body> + <p>Please grant trust to this site, then refresh the page.</p> + </body> +</html> |