]> jfr.im git - irc/quakenet/qwebirc.git/blob - static/js/flash_web_socket-nc.js
Merge.
[irc/quakenet/qwebirc.git] / static / js / flash_web_socket-nc.js
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 */
4
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>
7 */
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}}}}();
9
10 //Copyright (c) 2013, Hiroshi Ichikawa
11 //All rights reserved.
12 //
13 //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
14 //
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.
19
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
25
26 (function() {
27
28 if (window.WEB_SOCKET_FORCE_FLASH) {
29 // Keeps going.
30 } else if (window.WebSocket) {
31 return;
32 } else if (window.MozWebSocket) {
33 // Firefox.
34 window.WebSocket = MozWebSocket;
35 return;
36 }
37
38 var logger;
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;
44 } else {
45 logger = {log: function(){ }, error: function(){ }};
46 }
47
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.");
51 return;
52 }
53 if (location.protocol == "file:") {
54 logger.error(
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://...");
58 }
59
60 /**
61 * Our own implementation of WebSocket class using Flash.
62 * @param {string} url
63 * @param {array or string} protocols
64 * @param {string} proxyHost
65 * @param {int} proxyPort
66 * @param {string} headers
67 */
68 window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {
69 var self = this;
70 self.__id = WebSocket.__nextId++;
71 WebSocket.__instances[self.__id] = self;
72 self.readyState = WebSocket.CONNECTING;
73 self.bufferedAmount = 0;
74 self.__events = {};
75 if (!protocols) {
76 protocols = [];
77 } else if (typeof protocols == "string") {
78 protocols = [protocols];
79 }
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);
87 });
88 }, 0);
89 };
90
91 /**
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.
95 */
96 WebSocket.prototype.send = function(data) {
97 if (this.readyState == WebSocket.CONNECTING) {
98 throw "INVALID_STATE_ERR: Web Socket connection has not been established";
99 }
100 // We use encodeURIComponent() here, because FABridge doesn't work if
101 // the argument includes some characters. We don't use escape() here
102 // because of this:
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
110 return true;
111 } else {
112 this.bufferedAmount += result;
113 return false;
114 }
115 };
116
117 /**
118 * Close this web socket gracefully.
119 */
120 WebSocket.prototype.close = function() {
121 if (this.__createTask) {
122 clearTimeout(this.__createTask);
123 this.__createTask = null;
124 this.readyState = WebSocket.CLOSED;
125 return;
126 }
127 if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
128 return;
129 }
130 this.readyState = WebSocket.CLOSING;
131 WebSocket.__flash.close(this.__id);
132 };
133
134 /**
135 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
136 *
137 * @param {string} type
138 * @param {function} listener
139 * @param {boolean} useCapture
140 * @return void
141 */
142 WebSocket.prototype.addEventListener = function(type, listener, useCapture) {
143 if (!(type in this.__events)) {
144 this.__events[type] = [];
145 }
146 this.__events[type].push(listener);
147 };
148
149 /**
150 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
151 *
152 * @param {string} type
153 * @param {function} listener
154 * @param {boolean} useCapture
155 * @return void
156 */
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) {
162 events.splice(i, 1);
163 break;
164 }
165 }
166 };
167
168 /**
169 * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
170 *
171 * @param {Event} event
172 * @return void
173 */
174 WebSocket.prototype.dispatchEvent = function(event) {
175 var events = this.__events[event.type] || [];
176 for (var i = 0; i < events.length; ++i) {
177 events[i](event);
178 }
179 var handler = this["on" + event.type];
180 if (handler) handler.apply(this, [event]);
181 };
182
183 /**
184 * Handles an event from Flash.
185 * @param {Object} flashEvent
186 */
187 WebSocket.prototype.__handleEvent = function(flashEvent) {
188
189 if ("readyState" in flashEvent) {
190 this.readyState = flashEvent.readyState;
191 }
192 if ("protocol" in flashEvent) {
193 this.protocol = flashEvent.protocol;
194 }
195
196 var jsEvent;
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);
207 } else {
208 throw "unknown event type: " + flashEvent.type;
209 }
210
211 this.dispatchEvent(jsEvent);
212
213 };
214
215 WebSocket.prototype.__createSimpleEvent = function(type) {
216 if (document.createEvent && window.Event) {
217 var event = document.createEvent("Event");
218 event.initEvent(type, false, false);
219 return event;
220 } else {
221 return {type: type, bubbles: false, cancelable: false};
222 }
223 };
224
225 WebSocket.prototype.__createMessageEvent = function(type, data) {
226 if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) {
227 return new MessageEvent("message", {
228 "view": window,
229 "bubbles": false,
230 "cancelable": false,
231 "data": data
232 });
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);
236 return event;
237 } else {
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};
240 }
241 };
242
243 /**
244 * Define the WebSocket readyState enumeration.
245 */
246 WebSocket.CONNECTING = 0;
247 WebSocket.OPEN = 1;
248 WebSocket.CLOSING = 2;
249 WebSocket.CLOSED = 3;
250
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;
258
259 /**
260 * Load a new flash security policy file.
261 * @param {string} url
262 */
263 WebSocket.loadFlashPolicyFile = function(url){
264 WebSocket.__addTask(function() {
265 WebSocket.__flash.loadManualPolicyFile(url);
266 });
267 };
268
269 /**
270 * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
271 */
272 WebSocket.__initialize = function() {
273
274 if (WebSocket.__initialized) return;
275 WebSocket.__initialized = true;
276
277 if (WebSocket.__swfLocation) {
278 // For backword compatibility.
279 window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
280 }
281 if (!window.WEB_SOCKET_SWF_LOCATION) {
282 logger.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
283 return;
284 }
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) {
290 logger.error(
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;");
296 }
297 }
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";
309 } else {
310 container.style.left = "-100px";
311 container.style.top = "-100px";
312 }
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
319 swfobject.embedSWF(
320 WEB_SOCKET_SWF_LOCATION,
321 "webSocketFlash",
322 "1" /* width */,
323 "1" /* height */,
324 "10.0.0" /* SWF version */,
325 null,
326 null,
327 {hasPriority: true, swliveconnect : true, allowScriptAccess: "always"},
328 null,
329 function(e) {
330 if (!e.success) {
331 logger.error("[WebSocket] swfobject.embedSWF failed");
332 }
333 }
334 );
335
336 };
337
338 /**
339 * Called by Flash to notify JS that it's fully loaded and ready
340 * for communication.
341 */
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]();
351 }
352 WebSocket.__tasks = [];
353 }, 0);
354 };
355
356 /**
357 * Called by Flash to notify WebSockets events are fired.
358 */
359 WebSocket.__onFlashEvent = function() {
360 setTimeout(function() {
361 try {
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]);
368 }
369 } catch (e) {
370 logger.error(e);
371 }
372 }, 0);
373 return true;
374 };
375
376 // Called by Flash.
377 WebSocket.__log = function(message) {
378 logger.log(decodeURIComponent(message));
379 };
380
381 // Called by Flash.
382 WebSocket.__error = function(message) {
383 logger.error(decodeURIComponent(message));
384 };
385
386 WebSocket.__addTask = function(task) {
387 if (WebSocket.__flash) {
388 task();
389 } else {
390 WebSocket.__tasks.push(task);
391 }
392 };
393
394 /**
395 * Test if the browser is running flash lite.
396 * @return {boolean} True if flash lite is running, false otherwise.
397 */
398 WebSocket.__isFlashLite = function() {
399 if (!window.navigator || !window.navigator.mimeTypes) {
400 return false;
401 }
402 var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
403 if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {
404 return false;
405 }
406 return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
407 };
408
409 if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
410 // NOTE:
411 // This fires immediately if web_socket.js is dynamically loaded after
412 // the document is loaded.
413 swfobject.addDomLoadEvent(function() {
414 WebSocket.__initialize();
415 });
416 }
417
418 })();
419 /* PASTE END */
420 FLASH_WEBSOCKET_LOADED = 1;