diff options
Diffstat (limited to 'plugins/cordova-plugin-websocket/www/websocket.js')
| -rw-r--r-- | plugins/cordova-plugin-websocket/www/websocket.js | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/plugins/cordova-plugin-websocket/www/websocket.js b/plugins/cordova-plugin-websocket/www/websocket.js new file mode 100644 index 00000000..09ad873e --- /dev/null +++ b/plugins/cordova-plugin-websocket/www/websocket.js @@ -0,0 +1,274 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Cordova WebSocket Plugin for Android + * @author KNOWLEDGECODE <knowledgecode@gmail.com> + * @version 0.11.0 + */ +(function (window) { + 'use strict'; + var BuiltinWebSocket = window.WebSocket, + exec = require('cordova/exec'), + identifier = 0, + listeners = {}, + taskQueue = { + uuid: require('cordova/utils').createUUID(), + tasks: [], + push: function (fn) { + this.tasks.push(fn); + window.postMessage(this.uuid, '*'); + }, + listener: function (event) { + if (event.source === window && event.data === taskQueue.uuid) { + event.stopPropagation(); + if (taskQueue.tasks.length) { + taskQueue.tasks.shift()(); + } + } + } + }, + createMessage = function (type, data, origin) { + var evt = document.createEvent('Event'); + + evt.initEvent(type, false, false); + switch (type) { + case 'message': + evt.data = data; + evt.origin = origin; + break; + case 'close': + evt.wasClean = data.substring(0, 1) === '1'; + evt.code = parseInt(data.substring(1, 5), 10) || 0; + evt.reason = data.substring(5); + break; + } + return evt; + }, + Blob = (function () { + if (typeof window.WebKitBlobBuilder === 'function') { + return function (data) { + var blob = new window.WebKitBlobBuilder(); + blob.append(data[0]); + return blob.getBlob(); + }; + } + return window.Blob; + }()), + binaryToString = function (data, onComplete) { + var blob, r; + + if (data instanceof window.ArrayBuffer || data.buffer instanceof window.ArrayBuffer) { + blob = new Blob([data.buffer || data]); + } else if (data instanceof window.Blob) { + blob = data; + } else { + throw new TypeError('\'%s\' is not a valid value for binaryType.'.replace('%s', typeof data)); + } + r = new window.FileReader(); + r.onload = function () { + onComplete(this.result); + }; + r.readAsDataURL(blob); + }, + stringToBinary = function (data, binaryType) { + var i, len, array; + + data = atob(data); + len = data.length; + array = new window.Uint8Array(len); + for (i = 0; i < len; i++) { + array[i] = data.charCodeAt(i); + } + if (binaryType === 'arraybuffer') { + return array.buffer; + } + if (binaryType === 'blob') { + return new Blob([array.buffer]); + } + throw new TypeError('\'%s\' is not a valid value for binaryType.'.replace('%s', binaryType)); + }, + EventTarget = function () { + this.addEventListener = function (type, listener) { + var el = listeners[this.__getId__()][type] || []; + + if (el.indexOf(listener) < 0) { + el.push(listener); + listeners[this.__getId__()][type] = el; + } + }; + this.removeEventListener = function (type, listener) { + var i, el = listeners[this.__getId__()][type] || []; + + i = el.indexOf(listener); + if (i >= 0) { + el.splice(i, 1); + } + }; + this.dispatchEvent = function (evt) { + var i, len, el = listeners[this.__getId__()][evt.type] || []; + + for (i = 0, len = el.length; i < len; i++) { + el[i].call(this, evt); + } + }; + }, + WebSocketPrototype = function () { + this.CONNECTING = 0; + this.OPEN = 1; + this.CLOSING = 2; + this.CLOSED = 3; + this.send = function (data) { + var that = this; + + if (typeof data === 'string') { + exec(null, null, 'WebSocket', 'send', [that.__getId__() + '0' + data]); + } else { + binaryToString(data, function (blob) { + exec(null, null, 'WebSocket', 'send', [that.__getId__() + '1' + blob]); + }); + } + }; + this.close = function (code, reason) { + if (this.readyState === this.CONNECTING || this.readyState === this.OPEN) { + this.readyState = this.CLOSING; + exec(null, null, 'WebSocket', 'close', [this.__getId__(), code || 0, reason || '']); + } + }; + }, + WebSocket = function (url, protocols) { + var i, len, that = this, id = ('0000000' + identifier.toString(16)).slice(-8); + + if (this === window) { + throw new TypeError('Failed to construct \'WebSocket\': ' + + 'Please use the \'new\' operator, ' + + 'this DOM object constructor cannot be called as a function.'); + } + if (!WebSocket.pluginOptions.override && BuiltinWebSocket) { + return new (BuiltinWebSocket.bind.apply(BuiltinWebSocket, [].concat(this, Array.prototype.slice.call(arguments))))(); + } + switch (arguments.length) { + case 0: + throw new TypeError('Failed to construct \'WebSocket\': 1 argument required, but only 0 present.'); + case 1: + protocols = ''; + break; + case 2: + if (!Array.isArray(protocols)) { + protocols = [protocols]; + } + for (i = 0, len = protocols.length; i < len; i++) { + if (!/^[0-9A-Za-z!#\$%&'\*\+\-\.\^_`|~]+$/.test(protocols[i])) { + throw new SyntaxError('Failed to construct \'WebSocket\': The subprotocol \'' + protocols[i] + '\' is invalid.'); + } + } + protocols = len ? protocols.join(', ') : ''; + break; + default: + throw new TypeError('Failed to construct \'WebSocket\': No matching constructor signature.'); + } + + this.url = url; + this.binaryType = Blob ? 'blob' : 'arraybuffer'; + this.readyState = 0; + this.bufferedAmount = 0; + this.onopen = null; + this.onmessage = null; + this.onerror = null; + this.onclose = null; + this.extensions = ''; + this.protocol = ''; + this.__getId__ = function () { + return id; + }; + listeners[id] = {}; + + exec(function (data) { + switch (data[0]) { + case 'O': + taskQueue.push(function () { + var evt = createMessage('open'), + param = JSON.parse(data.substring(1)); + + that.protocol = param[0]; + that.extensions = param[1]; + that.readyState = that.OPEN; + if (that.onopen) { + that.onopen(evt); + } + that.dispatchEvent(evt); + }); + break; + case 'T': + taskQueue.push(function () { + var evt = createMessage('message', data.substring(1), that.url); + + if (that.onmessage) { + that.onmessage(evt); + } + that.dispatchEvent(evt); + }); + break; + case 'B': + taskQueue.push(function () { + var evt = createMessage('message', stringToBinary(data.substring(1), that.binaryType), that.url); + + if (that.onmessage) { + that.onmessage(evt); + } + that.dispatchEvent(evt); + }); + break; + case 'C': + taskQueue.push(function () { + var evt = createMessage('close', data.substring(1)); + + that.readyState = that.CLOSED; + if (that.onclose) { + that.onclose(evt); + } + that.dispatchEvent(evt); + delete listeners[that.__getId__()]; + }); + break; + } + }, function () { + taskQueue.push(function () { + var evt = createMessage('error'); + + if (that.onerror) { + that.onerror(evt); + } + that.dispatchEvent(evt); + }); + }, 'WebSocket', 'create', [identifier++, url, protocols, location.origin, navigator.userAgent, WebSocket.pluginOptions || {}]); + }, + ver = /Chrome\/(\d+)/.exec(navigator.userAgent); + + WebSocketPrototype.prototype = new EventTarget(); + WebSocketPrototype.prototype.constructor = WebSocketPrototype; + WebSocket.prototype = new WebSocketPrototype(); + WebSocket.prototype.constructor = WebSocket; + WebSocket.pluginOptions = {}; + module.exports = WebSocket; + window.addEventListener('message', taskQueue.listener, true); + + if (!ver || parseInt(ver[1], 10) < 30) { + BuiltinWebSocket = undefined; + } +}(this)); |
