1 window
.WEB_SOCKET_SWF_LOCATION
= qwebirc
.global
.staticBaseURL
+ "/WebSocketMain.swf";
2 window
.WEB_SOCKET_LOGGER
= qwebirc
.util
.logger
;
3 /* note: FLASH_WEBSOCKET_LOADED = 1; at end */
5 /* SWFObject v2.2 <http://code.google.com/p/swfobject/>
6 is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
8 var swfobject=function(){var D
="undefined",r
="object",S
="Shockwave Flash",W
="ShockwaveFlash.ShockwaveFlash",q
="application/x-shockwave-flash",R
="SWFObjectExprInst",x
="onreadystatechange",O
=window
,j
=document
,t
=navigator
,T
=false,U
=[h
],o
=[],N
=[],I
=[],l
,Q
,E
,B
,J
=false,a
=false,n
,G
,m
=true,M=function(){var aa
=typeof j
.getElementById
!=D
&&typeof j
.getElementsByTagName
!=D
&&typeof j
.createElement
!=D
,ah
=t
.userAgent
.toLowerCase(),Y
=t
.platform
.toLowerCase(),ae
=Y
?/win/.test(Y
):/win/.test(ah
),ac
=Y
?/mac/.test(Y
):/mac/.test(ah
),af
=/webkit/.test(ah
)?parseFloat(ah
.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X
=!+"\v1",ag
=[0,0,0],ab
=null;if(typeof t
.plugins
!=D
&&typeof t
.plugins
[S
]==r
){ab
=t
.plugins
[S
].description
;if(ab
&&!(typeof t
.mimeTypes
!=D
&&t
.mimeTypes
[q
]&&!t
.mimeTypes
[q
].enabledPlugin
)){T
=true;X
=false;ab
=ab
.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag
[0]=parseInt(ab
.replace(/^(.*)\..*$/,"$1"),10);ag
[1]=parseInt(ab
.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag
[2]=/[a-zA-Z]/.test(ab
)?parseInt(ab
.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O
.ActiveXObject
!=D
){try{var ad
=new ActiveXObject(W
);if(ad
){ab
=ad
.GetVariable("$version");if(ab
){X
=true;ab
=ab
.split(" ")[1].split(",");ag
=[parseInt(ab
[0],10),parseInt(ab
[1],10),parseInt(ab
[2],10)]}}}catch(Z
){}}}return{w3:aa
,pv:ag
,wk:af
,ie:X
,win:ae
,mac:ac
}}(),k=function(){if(!M
.w3
){return}if((typeof j
.readyState
!=D
&&j
.readyState
=="complete")||(typeof j
.readyState
==D
&&(j
.getElementsByTagName("body")[0]||j
.body
))){f()}if(!J
){if(typeof j
.addEventListener
!=D
){j
.addEventListener("DOMContentLoaded",f
,false)}if(M
.ie
&&M
.win
){j
.attachEvent(x
,function(){if(j
.readyState
=="complete"){j
.detachEvent(x
,arguments
.callee
);f()}});if(O
==top
){(function(){if(J
){return}try{j
.documentElement
.doScroll("left")}catch(X
){setTimeout(arguments
.callee
,0);return}f()})()}}if(M
.wk
){(function(){if(J
){return}if(!/loaded|complete/.test(j
.readyState
)){setTimeout(arguments
.callee
,0);return}f()})()}s(f
)}}();function f(){if(J
){return}try{var Z
=j
.getElementsByTagName("body")[0].appendChild(C("span"));Z
.parentNode
.removeChild(Z
)}catch(aa
){return}J
=true;var X
=U
.length
;for(var Y
=0;Y
<X
;Y
++){U
[Y
]()}}function K(X
){if(J
){X()}else{U
[U
.length
]=X
}}function s(Y
){if(typeof O
.addEventListener
!=D
){O
.addEventListener("load",Y
,false)}else{if(typeof j
.addEventListener
!=D
){j
.addEventListener("load",Y
,false)}else{if(typeof O
.attachEvent
!=D
){i(O
,"onload",Y
)}else{if(typeof O
.onload
=="function"){var X
=O
.onload
;O
.onload=function(){X();Y()}}else{O
.onload
=Y
}}}}}function h(){if(T
){V()}else{H()}}function V(){var X
=j
.getElementsByTagName("body")[0];var aa
=C(r
);aa
.setAttribute("type",q
);var Z
=X
.appendChild(aa
);if(Z
){var Y
=0;(function(){if(typeof Z
.GetVariable
!=D
){var ab
=Z
.GetVariable("$version");if(ab
){ab
=ab
.split(" ")[1].split(",");M
.pv
=[parseInt(ab
[0],10),parseInt(ab
[1],10),parseInt(ab
[2],10)]}}else{if(Y
<10){Y
++;setTimeout(arguments
.callee
,10);return}}X
.removeChild(aa
);Z
=null;H()})()}else{H()}}function H(){var ag
=o
.length
;if(ag
>0){for(var af
=0;af
<ag
;af
++){var Y
=o
[af
].id
;var ab
=o
[af
].callbackFn
;var aa
={success:false,id:Y
};if(M
.pv
[0]>0){var ae
=c(Y
);if(ae
){if(F(o
[af
].swfVersion
)&&!(M
.wk
&&M
.wk
<312)){w(Y
,true);if(ab
){aa
.success
=true;aa
.ref
=z(Y
);ab(aa
)}}else{if(o
[af
].expressInstall
&&A()){var ai
={};ai
.data
=o
[af
].expressInstall
;ai
.width
=ae
.getAttribute("width")||"0";ai
.height
=ae
.getAttribute("height")||"0";if(ae
.getAttribute("class")){ai
.styleclass
=ae
.getAttribute("class")}if(ae
.getAttribute("align")){ai
.align
=ae
.getAttribute("align")}var ah
={};var X
=ae
.getElementsByTagName("param");var ac
=X
.length
;for(var ad
=0;ad
<ac
;ad
++){if(X
[ad
].getAttribute("name").toLowerCase()!="movie"){ah
[X
[ad
].getAttribute("name")]=X
[ad
].getAttribute("value")}}P(ai
,ah
,Y
,ab
)}else{p(ae
);if(ab
){ab(aa
)}}}}}else{w(Y
,true);if(ab
){var Z
=z(Y
);if(Z
&&typeof Z
.SetVariable
!=D
){aa
.success
=true;aa
.ref
=Z
}ab(aa
)}}}}}function z(aa
){var X
=null;var Y
=c(aa
);if(Y
&&Y
.nodeName
=="OBJECT"){if(typeof Y
.SetVariable
!=D
){X
=Y
}else{var Z
=Y
.getElementsByTagName(r
)[0];if(Z
){X
=Z
}}}return X
}function A(){return !a
&&F("6.0.65")&&(M
.win
||M
.mac
)&&!(M
.wk
&&M
.wk
<312)}function P(aa
,ab
,X
,Z
){a
=true;E
=Z
||null;B
={success:false,id:X
};var ae
=c(X
);if(ae
){if(ae
.nodeName
=="OBJECT"){l
=g(ae
);Q
=null}else{l
=ae
;Q
=X
}aa
.id
=R
;if(typeof aa
.width
==D
||(!/%$/.test(aa
.width
)&&parseInt(aa
.width
,10)<310)){aa
.width
="310"}if(typeof aa
.height
==D
||(!/%$/.test(aa
.height
)&&parseInt(aa
.height
,10)<137)){aa
.height
="137"}j
.title
=j
.title
.slice(0,47)+" - Flash Player Installation";var ad
=M
.ie
&&M
.win
?"ActiveX":"PlugIn",ac
="MMredirectURL="+O
.location
.toString().replace(/&/g
,"%26")+"&MMplayerType="+ad
+"&MMdoctitle="+j
.title
;if(typeof ab
.flashvars
!=D
){ab
.flashvars
+="&"+ac
}else{ab
.flashvars
=ac
}if(M
.ie
&&M
.win
&&ae
.readyState
!=4){var Y
=C("div");X
+="SWFObjectNew";Y
.setAttribute("id",X
);ae
.parentNode
.insertBefore(Y
,ae
);ae
.style
.display
="none";(function(){if(ae
.readyState
==4){ae
.parentNode
.removeChild(ae
)}else{setTimeout(arguments
.callee
,10)}})()}u(aa
,ab
,X
)}}function p(Y
){if(M
.ie
&&M
.win
&&Y
.readyState
!=4){var X
=C("div");Y
.parentNode
.insertBefore(X
,Y
);X
.parentNode
.replaceChild(g(Y
),X
);Y
.style
.display
="none";(function(){if(Y
.readyState
==4){Y
.parentNode
.removeChild(Y
)}else{setTimeout(arguments
.callee
,10)}})()}else{Y
.parentNode
.replaceChild(g(Y
),Y
)}}function g(ab
){var aa
=C("div");if(M
.win
&&M
.ie
){aa
.innerHTML
=ab
.innerHTML
}else{var Y
=ab
.getElementsByTagName(r
)[0];if(Y
){var ad
=Y
.childNodes
;if(ad
){var X
=ad
.length
;for(var Z
=0;Z
<X
;Z
++){if(!(ad
[Z
].nodeType
==1&&ad
[Z
].nodeName
=="PARAM")&&!(ad
[Z
].nodeType
==8)){aa
.appendChild(ad
[Z
].cloneNode(true))}}}}}return aa
}function u(ai
,ag
,Y
){var X
,aa
=c(Y
);if(M
.wk
&&M
.wk
<312){return X
}if(aa
){if(typeof ai
.id
==D
){ai
.id
=Y
}if(M
.ie
&&M
.win
){var ah
="";for(var ae
in ai
){if(ai
[ae
]!=Object
.prototype[ae
]){if(ae
.toLowerCase()=="data"){ag
.movie
=ai
[ae
]}else{if(ae
.toLowerCase()=="styleclass"){ah
+=' class="'+ai
[ae
]+'"'}else{if(ae
.toLowerCase()!="classid"){ah
+=" "+ae
+'="'+ai
[ae
]+'"'}}}}}var af
="";for(var ad
in ag
){if(ag
[ad
]!=Object
.prototype[ad
]){af
+='<param name="'+ad
+'" value="'+ag
[ad
]+'" />'}}aa
.outerHTML
='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah
+">"+af
+"</object>";N
[N
.length
]=ai
.id
;X
=c(ai
.id
)}else{var Z
=C(r
);Z
.setAttribute("type",q
);for(var ac
in ai
){if(ai
[ac
]!=Object
.prototype[ac
]){if(ac
.toLowerCase()=="styleclass"){Z
.setAttribute("class",ai
[ac
])}else{if(ac
.toLowerCase()!="classid"){Z
.setAttribute(ac
,ai
[ac
])}}}}for(var ab
in ag
){if(ag
[ab
]!=Object
.prototype[ab
]&&ab
.toLowerCase()!="movie"){e(Z
,ab
,ag
[ab
])}}aa
.parentNode
.replaceChild(Z
,aa
);X
=Z
}}return X
}function e(Z
,X
,Y
){var aa
=C("param");aa
.setAttribute("name",X
);aa
.setAttribute("value",Y
);Z
.appendChild(aa
)}function y(Y
){var X
=c(Y
);if(X
&&X
.nodeName
=="OBJECT"){if(M
.ie
&&M
.win
){X
.style
.display
="none";(function(){if(X
.readyState
==4){b(Y
)}else{setTimeout(arguments
.callee
,10)}})()}else{X
.parentNode
.removeChild(X
)}}}function b(Z
){var Y
=c(Z
);if(Y
){for(var X
in Y
){if(typeof Y
[X
]=="function"){Y
[X
]=null}}Y
.parentNode
.removeChild(Y
)}}function c(Z
){var X
=null;try{X
=j
.getElementById(Z
)}catch(Y
){}return X
}function C(X
){return j
.createElement(X
)}function i(Z
,X
,Y
){Z
.attachEvent(X
,Y
);I
[I
.length
]=[Z
,X
,Y
]}function F(Z
){var Y
=M
.pv
,X
=Z
.split(".");X
[0]=parseInt(X
[0],10);X
[1]=parseInt(X
[1],10)||0;X
[2]=parseInt(X
[2],10)||0;return(Y
[0]>X
[0]||(Y
[0]==X
[0]&&Y
[1]>X
[1])||(Y
[0]==X
[0]&&Y
[1]==X
[1]&&Y
[2]>=X
[2]))?true:false}function v(ac
,Y
,ad
,ab
){if(M
.ie
&&M
.mac
){return}var aa
=j
.getElementsByTagName("head")[0];if(!aa
){return}var X
=(ad
&&typeof ad
=="string")?ad:"screen";if(ab
){n
=null;G
=null}if(!n
||G
!=X
){var Z
=C("style");Z
.setAttribute("type","text/css");Z
.setAttribute("media",X
);n
=aa
.appendChild(Z
);if(M
.ie
&&M
.win
&&typeof j
.styleSheets
!=D
&&j
.styleSheets
.length
>0){n
=j
.styleSheets
[j
.styleSheets
.length
-1]}G
=X
}if(M
.ie
&&M
.win
){if(n
&&typeof n
.addRule
==r
){n
.addRule(ac
,Y
)}}else{if(n
&&typeof j
.createTextNode
!=D
){n
.appendChild(j
.createTextNode(ac
+" {"+Y
+"}"))}}}function w(Z
,X
){if(!m
){return}var Y
=X
?"visible":"hidden";if(J
&&c(Z
)){c(Z
).style
.visibility
=Y
}else{v("#"+Z
,"visibility:"+Y
)}}function L(Y
){var Z
=/[\\\"<>\.;]/;var X
=Z
.exec(Y
)!=null;return X
&&typeof encodeURIComponent
!=D
?encodeURIComponent(Y
):Y
}var d=function(){if(M
.ie
&&M
.win
){window
.attachEvent("onunload",function(){var ac
=I
.length
;for(var ab
=0;ab
<ac
;ab
++){I
[ab
][0].detachEvent(I
[ab
][1],I
[ab
][2])}var Z
=N
.length
;for(var aa
=0;aa
<Z
;aa
++){y(N
[aa
])}for(var Y
in M
){M
[Y
]=null}M
=null;for(var X
in swfobject
){swfobject
[X
]=null}swfobject
=null})}}();return{registerObject:function(ab
,X
,aa
,Z
){if(M
.w3
&&ab
&&X
){var Y
={};Y
.id
=ab
;Y
.swfVersion
=X
;Y
.expressInstall
=aa
;Y
.callbackFn
=Z
;o
[o
.length
]=Y
;w(ab
,false)}else{if(Z
){Z({success:false,id:ab
})}}},getObjectById:function(X
){if(M
.w3
){return z(X
)}},embedSWF:function(ab
,ah
,ae
,ag
,Y
,aa
,Z
,ad
,af
,ac
){var X
={success:false,id:ah
};if(M
.w3
&&!(M
.wk
&&M
.wk
<312)&&ab
&&ah
&&ae
&&ag
&&Y
){w(ah
,false);K(function(){ae
+="";ag
+="";var aj
={};if(af
&&typeof af
===r
){for(var al
in af
){aj
[al
]=af
[al
]}}aj
.data
=ab
;aj
.width
=ae
;aj
.height
=ag
;var am
={};if(ad
&&typeof ad
===r
){for(var ak
in ad
){am
[ak
]=ad
[ak
]}}if(Z
&&typeof Z
===r
){for(var ai
in Z
){if(typeof am
.flashvars
!=D
){am
.flashvars
+="&"+ai
+"="+Z
[ai
]}else{am
.flashvars
=ai
+"="+Z
[ai
]}}}if(F(Y
)){var an
=u(aj
,am
,ah
);if(aj
.id
==ah
){w(ah
,true)}X
.success
=true;X
.ref
=an
}else{if(aa
&&A()){aj
.data
=aa
;P(aj
,am
,ah
,ac
);return}else{w(ah
,true)}}if(ac
){ac(X
)}})}else{if(ac
){ac(X
)}}},switchOffAutoHideShow:function(){m
=false},ua:M
,getFlashPlayerVersion:function(){return{major:M
.pv
[0],minor:M
.pv
[1],release:M
.pv
[2]}},hasFlashPlayerVersion:F
,createSWF:function(Z
,Y
,X
){if(M
.w3
){return u(Z
,Y
,X
)}else{return undefined}},showExpressInstall:function(Z
,aa
,X
,Y
){if(M
.w3
&&A()){P(Z
,aa
,X
,Y
)}},removeSWF:function(X
){if(M
.w3
){y(X
)}},createCSS:function(aa
,Z
,Y
,X
){if(M
.w3
){v(aa
,Z
,Y
,X
)}},addDomLoadEvent:K
,addLoadEvent:s
,getQueryParamValue:function(aa
){var Z
=j
.location
.search
||j
.location
.hash
;if(Z
){if(/\?/.test(Z
)){Z
=Z
.split("?")[1]}if(aa
==null){return L(Z
)}var Y
=Z
.split("&");for(var X
=0;X
<Y
.length
;X
++){if(Y
[X
].substring(0,Y
[X
].indexOf("="))==aa
){return L(Y
[X
].substring((Y
[X
].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a
){var X
=c(R
);if(X
&&l
){X
.parentNode
.replaceChild(l
,X
);if(Q
){w(Q
,true);if(M
.ie
&&M
.win
){l
.style
.display
="block"}}if(E
){E(B
)}}a
=false}}}}();
10 //Copyright (c) 2013, Hiroshi Ichikawa
11 //All rights reserved.
13 //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
15 //Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
16 //Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
17 //Neither the name of the Hiroshi Ichikawa nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
18 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20 /* PASTE START revision f64a2b962be1b9c3d569fa375b47b0de0427adad (including swf file) */
21 // Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
22 // License: New BSD License
23 // Reference: http://dev.w3.org/html5/websockets/
24 // Reference: http://tools.ietf.org/html/rfc6455
28 if (window
.WEB_SOCKET_FORCE_FLASH
) {
30 } else if (window
.WebSocket
) {
32 } else if (window
.MozWebSocket
) {
34 window
.WebSocket
= MozWebSocket
;
39 if (window
.WEB_SOCKET_LOGGER
) {
40 logger
= WEB_SOCKET_LOGGER
;
41 } else if (window
.console
&& window
.console
.log
&& window
.console
.error
) {
42 // In some environment, console is defined but console.log or console.error is missing.
43 logger
= window
.console
;
45 logger
= {log: function(){ }, error: function(){ }};
48 // swfobject.hasFlashPlayerVersion("10.0.0") doesn't work with Gnash.
49 if (swfobject
.getFlashPlayerVersion().major
< 10) {
50 logger
.error("Flash Player >= 10.0.0 is required.");
53 if (location
.protocol
== "file:") {
55 "WARNING: web-socket-js doesn't work in file:///... URL " +
56 "unless you set Flash Security Settings properly. " +
57 "Open the page via Web server i.e. http://...");
61 * Our own implementation of WebSocket class using Flash.
63 * @param {array or string} protocols
64 * @param {string} proxyHost
65 * @param {int} proxyPort
66 * @param {string} headers
68 window
.WebSocket = function(url
, protocols
, proxyHost
, proxyPort
, headers
) {
70 self
.__id
= WebSocket
.__nextId
++;
71 WebSocket
.__instances
[self
.__id
] = self
;
72 self
.readyState
= WebSocket
.CONNECTING
;
73 self
.bufferedAmount
= 0;
77 } else if (typeof protocols
== "string") {
78 protocols
= [protocols
];
80 // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
81 // Otherwise, when onopen fires immediately, onopen is called before it is set.
82 self
.__createTask
= setTimeout(function() {
83 WebSocket
.__addTask(function() {
84 self
.__createTask
= null;
85 WebSocket
.__flash
.create(
86 self
.__id
, url
, protocols
, proxyHost
|| null, proxyPort
|| 0, headers
|| null);
92 * Send data to the web socket.
93 * @param {string} data The data to send to the socket.
94 * @return {boolean} True for success, false for failure.
96 WebSocket
.prototype.send = function(data
) {
97 if (this.readyState
== WebSocket
.CONNECTING
) {
98 throw "INVALID_STATE_ERR: Web Socket connection has not been established";
100 // We use encodeURIComponent() here, because FABridge doesn't work if
101 // the argument includes some characters. We don't use escape() here
103 // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
104 // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
105 // preserve all Unicode characters either e.g. "\uffff" in Firefox.
106 // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require
107 // additional testing.
108 var result
= WebSocket
.__flash
.send(this.__id
, encodeURIComponent(data
));
109 if (result
< 0) { // success
112 this.bufferedAmount
+= result
;
118 * Close this web socket gracefully.
120 WebSocket
.prototype.close = function() {
121 if (this.__createTask
) {
122 clearTimeout(this.__createTask
);
123 this.__createTask
= null;
124 this.readyState
= WebSocket
.CLOSED
;
127 if (this.readyState
== WebSocket
.CLOSED
|| this.readyState
== WebSocket
.CLOSING
) {
130 this.readyState
= WebSocket
.CLOSING
;
131 WebSocket
.__flash
.close(this.__id
);
135 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
137 * @param {string} type
138 * @param {function} listener
139 * @param {boolean} useCapture
142 WebSocket
.prototype.addEventListener = function(type
, listener
, useCapture
) {
143 if (!(type
in this.__events
)) {
144 this.__events
[type
] = [];
146 this.__events
[type
].push(listener
);
150 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
152 * @param {string} type
153 * @param {function} listener
154 * @param {boolean} useCapture
157 WebSocket
.prototype.removeEventListener = function(type
, listener
, useCapture
) {
158 if (!(type
in this.__events
)) return;
159 var events
= this.__events
[type
];
160 for (var i
= events
.length
- 1; i
>= 0; --i
) {
161 if (events
[i
] === listener
) {
169 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
171 * @param {Event} event
174 WebSocket
.prototype.dispatchEvent = function(event
) {
175 var events
= this.__events
[event
.type
] || [];
176 for (var i
= 0; i
< events
.length
; ++i
) {
179 var handler
= this["on" + event
.type
];
180 if (handler
) handler
.apply(this, [event
]);
184 * Handles an event from Flash.
185 * @param {Object} flashEvent
187 WebSocket
.prototype.__handleEvent = function(flashEvent
) {
189 if ("readyState" in flashEvent
) {
190 this.readyState
= flashEvent
.readyState
;
192 if ("protocol" in flashEvent
) {
193 this.protocol
= flashEvent
.protocol
;
197 if (flashEvent
.type
== "open" || flashEvent
.type
== "error") {
198 jsEvent
= this.__createSimpleEvent(flashEvent
.type
);
199 } else if (flashEvent
.type
== "close") {
200 jsEvent
= this.__createSimpleEvent("close");
201 jsEvent
.wasClean
= flashEvent
.wasClean
? true : false;
202 jsEvent
.code
= flashEvent
.code
;
203 jsEvent
.reason
= flashEvent
.reason
;
204 } else if (flashEvent
.type
== "message") {
205 var data
= decodeURIComponent(flashEvent
.message
);
206 jsEvent
= this.__createMessageEvent("message", data
);
208 throw "unknown event type: " + flashEvent
.type
;
211 this.dispatchEvent(jsEvent
);
215 WebSocket
.prototype.__createSimpleEvent = function(type
) {
216 if (document
.createEvent
&& window
.Event
) {
217 var event
= document
.createEvent("Event");
218 event
.initEvent(type
, false, false);
221 return {type: type
, bubbles: false, cancelable: false};
225 WebSocket
.prototype.__createMessageEvent = function(type
, data
) {
226 if (window
.MessageEvent
&& typeof(MessageEvent
) == "function" && !window
.opera
) {
227 return new MessageEvent("message", {
233 } else if (document
.createEvent
&& window
.MessageEvent
&& !window
.opera
) {
234 var event
= document
.createEvent("MessageEvent");
235 event
.initMessageEvent("message", false, false, data
, null, null, window
, null);
238 // Old IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.
239 return {type: type
, data: data
, bubbles: false, cancelable: false};
244 * Define the WebSocket readyState enumeration.
246 WebSocket
.CONNECTING
= 0;
248 WebSocket
.CLOSING
= 2;
249 WebSocket
.CLOSED
= 3;
251 // Field to check implementation of WebSocket.
252 WebSocket
.__isFlashImplementation
= true;
253 WebSocket
.__initialized
= false;
254 WebSocket
.__flash
= null;
255 WebSocket
.__instances
= {};
256 WebSocket
.__tasks
= [];
257 WebSocket
.__nextId
= 0;
260 * Load a new flash security policy file.
261 * @param {string} url
263 WebSocket
.loadFlashPolicyFile = function(url
){
264 WebSocket
.__addTask(function() {
265 WebSocket
.__flash
.loadManualPolicyFile(url
);
270 * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
272 WebSocket
.__initialize = function() {
274 if (WebSocket
.__initialized
) return;
275 WebSocket
.__initialized
= true;
277 if (WebSocket
.__swfLocation
) {
278 // For backword compatibility.
279 window
.WEB_SOCKET_SWF_LOCATION
= WebSocket
.__swfLocation
;
281 if (!window
.WEB_SOCKET_SWF_LOCATION
) {
282 logger
.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
285 if (!window
.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR
&&
286 !WEB_SOCKET_SWF_LOCATION
.match(/(^|\/)WebSocketMainInsecure\.swf(\?.*)?$/) &&
287 WEB_SOCKET_SWF_LOCATION
.match(/^\w+:\/\/([^\/]+)/)) {
288 var swfHost
= RegExp
.$1;
289 if (location
.host
!= swfHost
) {
291 "[WebSocket] You must host HTML and WebSocketMain.swf in the same host " +
292 "('" + location
.host
+ "' != '" + swfHost
+ "'). " +
293 "See also 'How to host HTML file and SWF file in different domains' section " +
294 "in README.md. If you use WebSocketMainInsecure.swf, you can suppress this message " +
295 "by WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;");
298 var container
= document
.createElement("div");
299 container
.id
= "webSocketContainer";
300 // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
301 // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
302 // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
303 // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
304 // the best we can do as far as we know now.
305 container
.style
.position
= "absolute";
306 if (WebSocket
.__isFlashLite()) {
307 container
.style
.left
= "0px";
308 container
.style
.top
= "0px";
310 container
.style
.left
= "-100px";
311 container
.style
.top
= "-100px";
313 var holder
= document
.createElement("div");
314 holder
.id
= "webSocketFlash";
315 container
.appendChild(holder
);
316 document
.body
.appendChild(container
);
317 // See this article for hasPriority:
318 // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
320 WEB_SOCKET_SWF_LOCATION
,
324 "10.0.0" /* SWF version */,
327 {hasPriority: true, swliveconnect : true, allowScriptAccess: "always"},
331 logger
.error("[WebSocket] swfobject.embedSWF failed");
339 * Called by Flash to notify JS that it's fully loaded and ready
342 WebSocket
.__onFlashInitialized = function() {
343 // We need to set a timeout here to avoid round-trip calls
344 // to flash during the initialization process.
345 setTimeout(function() {
346 WebSocket
.__flash
= document
.getElementById("webSocketFlash");
347 WebSocket
.__flash
.setCallerUrl(location
.href
);
348 WebSocket
.__flash
.setDebug(!!window
.WEB_SOCKET_DEBUG
);
349 for (var i
= 0; i
< WebSocket
.__tasks
.length
; ++i
) {
350 WebSocket
.__tasks
[i
]();
352 WebSocket
.__tasks
= [];
357 * Called by Flash to notify WebSockets events are fired.
359 WebSocket
.__onFlashEvent = function() {
360 setTimeout(function() {
362 // Gets events using receiveEvents() instead of getting it from event object
363 // of Flash event. This is to make sure to keep message order.
364 // It seems sometimes Flash events don't arrive in the same order as they are sent.
365 var events
= WebSocket
.__flash
.receiveEvents();
366 for (var i
= 0; i
< events
.length
; ++i
) {
367 WebSocket
.__instances
[events
[i
].webSocketId
].__handleEvent(events
[i
]);
377 WebSocket
.__log = function(message
) {
378 logger
.log(decodeURIComponent(message
));
382 WebSocket
.__error = function(message
) {
383 logger
.error(decodeURIComponent(message
));
386 WebSocket
.__addTask = function(task
) {
387 if (WebSocket
.__flash
) {
390 WebSocket
.__tasks
.push(task
);
395 * Test if the browser is running flash lite.
396 * @return {boolean} True if flash lite is running, false otherwise.
398 WebSocket
.__isFlashLite = function() {
399 if (!window
.navigator
|| !window
.navigator
.mimeTypes
) {
402 var mimeType
= window
.navigator
.mimeTypes
["application/x-shockwave-flash"];
403 if (!mimeType
|| !mimeType
.enabledPlugin
|| !mimeType
.enabledPlugin
.filename
) {
406 return mimeType
.enabledPlugin
.filename
.match(/flashlite/i) ? true : false;
409 if (!window
.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION
) {
411 // This fires immediately if web_socket.js is dynamically loaded after
412 // the document is loaded.
413 swfobject
.addDomLoadEvent(function() {
414 WebSocket
.__initialize();
420 FLASH_WEBSOCKET_LOADED
= 1;