shared-connection-worker.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. let manager;
  2. const Status = {
  3. ERROR: 0,
  4. CONNECTING: 1,
  5. CONNFAIL: 2,
  6. AUTHENTICATING: 3,
  7. AUTHFAIL: 4,
  8. CONNECTED: 5,
  9. DISCONNECTED: 6,
  10. DISCONNECTING: 7,
  11. ATTACHED: 8,
  12. REDIRECT: 9,
  13. CONNTIMEOUT: 10,
  14. BINDREQUIRED: 11,
  15. ATTACHFAIL: 12
  16. }
  17. /** Class: ConnectionManager
  18. *
  19. * Manages the shared websocket connection as well as the ports of the
  20. * connected tabs.
  21. */
  22. class ConnectionManager {
  23. constructor () {
  24. this.ports = [];
  25. }
  26. addPort (port) {
  27. this.ports.push(port);
  28. port.addEventListener('message', e => {
  29. const method = e.data[0];
  30. try {
  31. this[method](e.data.splice(1))
  32. } catch (e) {
  33. console?.error(e);
  34. }
  35. });
  36. port.start();
  37. }
  38. _connect (data) {
  39. this.jid = data[1];
  40. this._closeSocket();
  41. this.socket = new WebSocket(data[0], "xmpp");
  42. this.socket.onopen = () => this._onOpen();
  43. this.socket.onerror = (e) => this._onError(e);
  44. this.socket.onclose = (e) => this._onClose(e);
  45. this.socket.onmessage = (message) => this._onMessage(message);
  46. }
  47. _attach () {
  48. if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
  49. this.ports.forEach(p => p.postMessage(['_attachCallback', Status.ATTACHED, this.jid]));
  50. } else {
  51. this.ports.forEach(p => p.postMessage(['_attachCallback', Status.ATTACHFAIL]));
  52. }
  53. }
  54. send (str) {
  55. this.socket.send(str);
  56. }
  57. close (str) {
  58. if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
  59. try {
  60. this.socket.send(str);
  61. } catch (e) {
  62. this.ports.forEach(p => p.postMessage(['log', 'error', e]));
  63. this.ports.forEach(p => p.postMessage(
  64. ['log', 'error', "Couldn't send <close /> tag."]));
  65. }
  66. }
  67. }
  68. _onOpen () {
  69. this.ports.forEach(p => p.postMessage(['_onOpen']));
  70. }
  71. _onClose (e) {
  72. this.ports.forEach(p => p.postMessage(['_onClose', e.reason]));
  73. }
  74. _onMessage (message) {
  75. const o = { 'data': message.data }
  76. this.ports.forEach(p => p.postMessage(['_onMessage', o]));
  77. }
  78. _onError (error) {
  79. this.ports.forEach(p => p.postMessage(['_onError', error.reason]));
  80. }
  81. _closeSocket () {
  82. if (this.socket) {
  83. try {
  84. this.socket.onclose = null;
  85. this.socket.onerror = null;
  86. this.socket.onmessage = null;
  87. this.socket.close();
  88. } catch (e) {
  89. this.ports.forEach(p => p.postMessage(['log', 'error', e]));
  90. }
  91. }
  92. this.socket = null;
  93. }
  94. }
  95. onconnect = function (e) { // eslint-disable-line no-undef
  96. manager = manager || new ConnectionManager();
  97. manager.addPort(e.ports[0]);
  98. }