ZeroFrame.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Version 1.0.0 - Initial release
  2. // Version 1.1.0 (2017-08-02) - Added cmdp function that returns promise instead of using callback
  3. // Version 1.2.0 (2017-08-02) - Added Ajax monkey patch to emulate XMLHttpRequest over ZeroFrame API
  4. const CMD_INNER_READY = 'innerReady'
  5. const CMD_RESPONSE = 'response'
  6. const CMD_WRAPPER_READY = 'wrapperReady'
  7. const CMD_PING = 'ping'
  8. const CMD_PONG = 'pong'
  9. const CMD_WRAPPER_OPENED_WEBSOCKET = 'wrapperOpenedWebsocket'
  10. const CMD_WRAPPER_CLOSE_WEBSOCKET = 'wrapperClosedWebsocket'
  11. class ZeroFrame {
  12. constructor(url) {
  13. this.url = url
  14. this.waiting_cb = {}
  15. this.wrapper_nonce = document.location.href.replace(/.*wrapper_nonce=([A-Za-z0-9]+).*/, "$1")
  16. this.connect()
  17. this.next_message_id = 1
  18. this.init()
  19. }
  20. init() {
  21. return this
  22. }
  23. connect() {
  24. this.target = window.parent
  25. window.addEventListener('message', e => this.onMessage(e), false)
  26. this.cmd(CMD_INNER_READY)
  27. }
  28. onMessage(e) {
  29. let message = e.data
  30. let cmd = message.cmd
  31. if (cmd === CMD_RESPONSE) {
  32. if (this.waiting_cb[message.to] !== undefined) {
  33. this.waiting_cb[message.to](message.result)
  34. }
  35. else {
  36. this.log("Websocket callback not found:", message)
  37. }
  38. } else if (cmd === CMD_WRAPPER_READY) {
  39. this.cmd(CMD_INNER_READY)
  40. } else if (cmd === CMD_PING) {
  41. this.response(message.id, CMD_PONG)
  42. } else if (cmd === CMD_WRAPPER_OPENED_WEBSOCKET) {
  43. this.onOpenWebsocket()
  44. } else if (cmd === CMD_WRAPPER_CLOSE_WEBSOCKET) {
  45. this.onCloseWebsocket()
  46. } else {
  47. this.onRequest(cmd, message)
  48. }
  49. }
  50. onRequest(cmd, message) {
  51. this.log("Unknown request", message)
  52. }
  53. response(to, result) {
  54. this.send({
  55. cmd: CMD_RESPONSE,
  56. to: to,
  57. result: result
  58. })
  59. }
  60. cmd(cmd, params={}, cb=null) {
  61. this.send({
  62. cmd: cmd,
  63. params: params
  64. }, cb)
  65. }
  66. cmdp(cmd, params={}) {
  67. return new Promise((resolve, reject) => {
  68. this.cmd(cmd, params, (res) => {
  69. if (res && res.error) {
  70. reject(res.error)
  71. } else {
  72. resolve(res)
  73. }
  74. })
  75. })
  76. }
  77. send(message, cb=null) {
  78. message.wrapper_nonce = this.wrapper_nonce
  79. message.id = this.next_message_id
  80. this.next_message_id++
  81. this.target.postMessage(message, '*')
  82. if (cb) {
  83. this.waiting_cb[message.id] = cb
  84. }
  85. }
  86. log(...args) {
  87. console.log.apply(console, ['[ZeroFrame]'].concat(args))
  88. }
  89. onOpenWebsocket() {
  90. this.log('Websocket open')
  91. }
  92. onCloseWebsocket() {
  93. this.log('Websocket close')
  94. }
  95. monkeyPatchAjax() {
  96. var page = this
  97. XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open
  98. this.cmd("wrapperGetAjaxKey", [], (res) => { this.ajax_key = res })
  99. var newOpen = function (method, url, async) {
  100. url += "?ajax_key=" + page.ajax_key
  101. return this.realOpen(method, url, async)
  102. }
  103. XMLHttpRequest.prototype.open = newOpen
  104. }
  105. }