123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /*
- Original code is Copyright (c) 2020 ZeroNet project.
- Original code was released under the GPLv2 license by ZeroNet project, December 2016.
- Original code was rereleased under the MIT license by ZeroNet project, March 2020.
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- // Version 1.0.0 - Initial release
- // Version 1.1.0 (2017-08-02) - Added cmdp function that returns promise instead of using callback
- // Version 1.2.0 (2017-08-02) - Added Ajax monkey patch to emulate XMLHttpRequest over ZeroFrame API
- // Version 1.3.0 (2018-12-05) - Added monkey patch for fetch API
- // Version 1.3.1 (2019-09-02) - Fix memory leak while handling responses
- // Version 1.4.0 (2019-12-11) - Awaitable monkeyPatchAjax function
- const CMD_INNER_READY = 'innerReady'
- const CMD_RESPONSE = 'response'
- const CMD_WRAPPER_READY = 'wrapperReady'
- const CMD_PING = 'ping'
- const CMD_PONG = 'pong'
- const CMD_WRAPPER_OPENED_WEBSOCKET = 'wrapperOpenedWebsocket'
- const CMD_WRAPPER_CLOSE_WEBSOCKET = 'wrapperClosedWebsocket'
- class ZeroFrame {
- constructor(url) {
- this.url = url
- this.waiting_cb = {}
- this.wrapper_nonce = document.location.href.replace(/.*wrapper_nonce=([A-Za-z0-9]+).*/, "$1")
- this.connect()
- this.next_message_id = 1
- this.init()
- }
- init() {
- return this
- }
- connect() {
- this.target = window.parent
- window.addEventListener('message', e => this.onMessage(e), false)
- this.cmd(CMD_INNER_READY)
- }
- onMessage(e) {
- let message = e.data
- let cmd = message.cmd
- if (cmd === CMD_RESPONSE) {
- if (this.waiting_cb[message.to] !== undefined) {
- this.waiting_cb[message.to](message.result)
- delete this.waiting_cb[message.to]
- }
- else {
- this.log("Websocket callback not found:", message)
- }
- } else if (cmd === CMD_WRAPPER_READY) {
- this.cmd(CMD_INNER_READY)
- } else if (cmd === CMD_PING) {
- this.response(message.id, CMD_PONG)
- } else if (cmd === CMD_WRAPPER_OPENED_WEBSOCKET) {
- this.onOpenWebsocket()
- } else if (cmd === CMD_WRAPPER_CLOSE_WEBSOCKET) {
- this.onCloseWebsocket()
- } else {
- this.onRequest(cmd, message)
- }
- }
- onRequest(cmd, message) {
- this.log("Unknown request", message)
- }
- response(to, result) {
- this.send({
- cmd: CMD_RESPONSE,
- to: to,
- result: result
- })
- }
- cmd(cmd, params={}, cb=null) {
- this.send({
- cmd: cmd,
- params: params
- }, cb)
- }
- cmdp(cmd, params={}) {
- return new Promise((resolve, reject) => {
- this.cmd(cmd, params, (res) => {
- if (res && res.error) {
- reject(res.error)
- } else {
- resolve(res)
- }
- })
- })
- }
- send(message, cb=null) {
- message.wrapper_nonce = this.wrapper_nonce
- message.id = this.next_message_id
- this.next_message_id++
- this.target.postMessage(message, '*')
- if (cb) {
- this.waiting_cb[message.id] = cb
- }
- }
- log(...args) {
- console.log.apply(console, ['[ZeroFrame]'].concat(args))
- }
- onOpenWebsocket() {
- this.log('Websocket open')
- }
- onCloseWebsocket() {
- this.log('Websocket close')
- }
- async monkeyPatchAjax() {
- var page = this
- XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open
- var newOpen = function (method, url, async) {
- url += "?ajax_key=" + page.ajax_key
- return this.realOpen(method, url, async)
- }
- XMLHttpRequest.prototype.open = newOpen
- window.realFetch = window.fetch
- var newFetch = function (url) {
- url += "?ajax_key=" + page.ajax_key
- return window.realFetch(url)
- }
- window.fetch = newFetch
- this.ajax_key = await page.cmdp("wrapperGetAjaxKey", [])
- }
- }
|