diff --git a/lib/socket.js b/lib/socket.js index a2c9eaf3f..d0ddb363b 100644 --- a/lib/socket.js +++ b/lib/socket.js @@ -44,6 +44,7 @@ function Socket (opts) { this.transports = opts.transports || ['polling', 'websocket', 'flashsocket']; this.readyState = ''; this.writeBuffer = []; + this.policyPort = opts.policyPort; this.open(); }; @@ -78,6 +79,7 @@ Socket.prototype.createTransport = function (name) { , query: query , forceJSONP: this.forceJSONP , flashPath: this.flashPath + , policyPort: this.policyPort }); return transport; diff --git a/lib/transports/flashsocket.js b/lib/transports/flashsocket.js index 5166ec68d..38fc7ed7b 100644 --- a/lib/transports/flashsocket.js +++ b/lib/transports/flashsocket.js @@ -3,7 +3,7 @@ * Module dependencies. */ -var WebSocket = require('./websocket') +var WS = require('./websocket') , util = require('../util') /** @@ -19,15 +19,16 @@ module.exports = FlashWS; */ function FlashWS (options) { - WebSocket.call(this, options); + WS.call(this, options); this.flashPath = options.flashPath; + this.policyPort = options.policyPort; }; /** * Inherits from WebSocket. */ -util.inherits(FlashWS, WebSocket); +util.inherits(FlashWS, WS); /** * Transport name. @@ -44,7 +45,7 @@ FlashWS.prototype.name = 'flashsocket'; */ FlashWS.prototype.doOpen = function () { - if (!check()) { + if (!this.check()) { // let the probe timeout return; } @@ -59,16 +60,23 @@ FlashWS.prototype.doOpen = function () { WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') }; WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true; + WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true; // dependencies - var deps = [path + 'web_socket.js']; + var deps = [this.flashPath + 'web_socket.js']; if ('undefined' == typeof swfobject) { - deps.unshift(path + 'swfobject.js'); + deps.unshift(this.flashPath + 'swfobject.js'); } + var self = this; + load(deps, function () { - FlashWS.prototype.doOpen.call(self); + self.ready(function () { + WebSocket.__addTask(function () { + WS.prototype.doOpen.call(self); + }); + }); }); }; @@ -80,24 +88,82 @@ FlashWS.prototype.doOpen = function () { FlashWS.prototype.doClose = function () { if (!this.socket) return; - FlashWS.prototype.doClose.call(this); + var self = this; + WebSocket.__addTask(function() { + WS.prototype.doClose.call(self); + }); +}; + +FlashWS.prototype.write = function() { + var self = this, args = arguments; + WebSocket.__addTask(function () { + WS.prototype.write.apply(self, args); + }); +}; + +FlashWS.prototype.ready = function (fn) { + if (typeof WebSocket == 'undefined' + || !('__initialize' in WebSocket) || !swfobject + ) { + return; + } + + if (swfobject.getFlashPlayerVersion().major < 10) { + return; + } + + function init () { + + // Only start downloading the swf file when the checked that this browser + // actually supports it + if (!FlashWS.loaded) { + + if (self.policyPort !== 843) { + WebSocket.loadFlashPolicyFile('xmlsocket://' + self.host + ':' + self.policyPort); + } + + WebSocket.__initialize(); + FlashWS.loaded = true; + } + + fn.call(self); + } + + var self = this; + if (document.body) return init(); + + util.load(init); }; /** - * Feature detection for FlashSocket. + * Feature detection for flashsocket. * * @return {Boolean} whether this transport is available. * @api public */ -function check () { +FlashWS.prototype.check = function () { // if node return false; // end - for (var i = 0, l = navigator.plugins.length; i < l; i++) { - for (var j = 0, m = navigator.plugins[i].length; j < m; j++) { - if (navigator.plugins[i][j] == 'Shockwave Flash') return true; + if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) + return false; + + if (window.ActiveXObject) { + var control = null; + try { + control = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); + } catch (e) { } + if (control) { + return true; + } + } + else { + for (var i = 0, l = navigator.plugins.length; i < l; i++) { + for (var j = 0, m = navigator.plugins[i].length; j < m; j++) { + if (navigator.plugins[i][j].description == 'Shockwave Flash') return true; + } } } @@ -156,7 +222,7 @@ function load (arr, fn) { function process (i) { if (!arr[i]) return fn(); create(arr[i], function () { - process(arr[++i]); + process(++i); }); }; diff --git a/lib/transports/websocket.js b/lib/transports/websocket.js index c767f16d3..e1b64d9c4 100644 --- a/lib/transports/websocket.js +++ b/lib/transports/websocket.js @@ -45,7 +45,7 @@ WS.prototype.name = 'websocket'; */ WS.prototype.doOpen = function () { - if (!check()) { + if (!this.check()) { // let probe timeout return; } @@ -88,7 +88,9 @@ WS.prototype.write = function (packets) { */ WS.prototype.doClose = function () { - this.socket.close(); + if (typeof this.socket !== 'undefined') { + this.socket.close(); + } }; /** @@ -116,6 +118,18 @@ WS.prototype.uri = function () { return schema + '://' + this.host + port + this.path + query; }; +/** + * Feature detection for WebSocket. + * + * @return {Boolean} whether this transport is available. + * @api public + */ + +WS.prototype.check = function () { + var websocket = ws(); + return !!websocket && !('__initialize' in websocket && this.name === WS.prototype.name); +} + /** * Getter for WS constructor. * @@ -129,14 +143,3 @@ function ws () { return global.WebSocket || global.MozWebSocket; } - -/** - * Feature detection for WebSocket. - * - * @return {Boolean} whether this transport is available. - * @api public - */ - -function check () { - return !!ws(); -}