Files
socket.io/lib/transports/flashsocket.js
2013-09-19 15:15:25 +03:00

261 lines
4.8 KiB
JavaScript

/**
* Module dependencies.
*/
var WS = require('./websocket')
, util = require('../util')
, debug = require('debug')('engine.io-client:flashsocket');
/**
* Module exports.
*/
module.exports = FlashWS;
/**
* Global reference.
*/
var global = require('global');
/**
* Obfuscated key for Blue Coat.
*/
var xobject = global[['Active'].concat('Object').join('X')];
/**
* FlashWS constructor.
*
* @api public
*/
function FlashWS (options) {
WS.call(this, options);
this.flashPath = options.flashPath;
this.policyPort = options.policyPort;
};
/**
* Inherits from WebSocket.
*/
util.inherits(FlashWS, WS);
/**
* Transport name.
*
* @api public
*/
FlashWS.prototype.name = 'flashsocket';
/**
* Opens the transport.
*
* @api public
*/
FlashWS.prototype.doOpen = function () {
if (!this.check()) {
// let the probe timeout
return;
}
// instrument websocketjs logging
function log (type) {
return function(){
var str = Array.prototype.join.call(arguments, ' ');
debug('[websocketjs %s] %s', type, str);
};
};
WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') };
WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) {
WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf';
}
// dependencies
var deps = [this.flashPath + 'web_socket.js'];
if ('undefined' == typeof swfobject) {
deps.unshift(this.flashPath + 'swfobject.js');
}
var self = this;
load(deps, function () {
self.ready(function () {
WebSocket.__addTask(function () {
self.socket = new WebSocket(self.uri());
self.addEventListeners();
});
});
});
};
/**
* Override to prevent closing uninitialized flashsocket.
*
* @api private
*/
FlashWS.prototype.doClose = function () {
if (!this.socket) return;
var self = this;
WebSocket.__addTask(function() {
WS.prototype.doClose.call(self);
});
};
/**
* Writes to the Flash socket.
*
* @api private
*/
FlashWS.prototype.write = function() {
var self = this, args = arguments;
WebSocket.__addTask(function () {
WS.prototype.write.apply(self, args);
});
};
/**
* Called upon dependencies are loaded.
*
* @api private
*/
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 (843 != self.policyPort) {
WebSocket.loadFlashPolicyFile('xmlsocket://' + self.hostname + ':' + 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.
*
* @return {Boolean} whether this transport is available.
* @api public
*/
FlashWS.prototype.check = function () {
if ('undefined' == typeof window) {
return false;
}
if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) {
return false;
}
if (xobject) {
var control = null;
try {
control = new xobject('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;
}
}
}
}
return false;
};
/**
* Lazy loading of scripts.
* Based on $script by Dustin Diaz - MIT
*/
var scripts = {};
/**
* Injects a script. Keeps tracked of injected ones.
*
* @param {String} path
* @param {Function} callback
* @api private
*/
function create (path, fn) {
if (scripts[path]) return fn();
var el = document.createElement('script');
var loaded = false;
debug('loading "%s"', path);
el.onload = el.onreadystatechange = function () {
if (loaded || scripts[path]) return;
var rs = el.readyState;
if (!rs || 'loaded' == rs || 'complete' == rs) {
debug('loaded "%s"', path);
el.onload = el.onreadystatechange = null;
loaded = true;
scripts[path] = true;
fn();
}
};
el.async = 1;
el.src = path;
var head = document.getElementsByTagName('head')[0];
head.insertBefore(el, head.firstChild);
};
/**
* Loads scripts and fires a callback.
*
* @param {Array} paths
* @param {Function} callback
*/
function load (arr, fn) {
function process (i) {
if (!arr[i]) return fn();
create(arr[i], function () {
process(++i);
});
};
process(0);
};