github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/themes/wind/static/libs/sockjs-client-1.1.0/lib/transport/iframe.js (about) 1 'use strict'; 2 3 // Few cool transports do work only for same-origin. In order to make 4 // them work cross-domain we shall use iframe, served from the 5 // remote domain. New browsers have capabilities to communicate with 6 // cross domain iframe using postMessage(). In IE it was implemented 7 // from IE 8+, but of course, IE got some details wrong: 8 // http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx 9 // http://stevesouders.com/misc/test-postmessage.php 10 11 var inherits = require('inherits') 12 , JSON3 = require('json3') 13 , EventEmitter = require('events').EventEmitter 14 , version = require('../version') 15 , urlUtils = require('../utils/url') 16 , iframeUtils = require('../utils/iframe') 17 , eventUtils = require('../utils/event') 18 , random = require('../utils/random') 19 ; 20 21 var debug = function() {}; 22 if (process.env.NODE_ENV !== 'production') { 23 debug = require('debug')('sockjs-client:transport:iframe'); 24 } 25 26 function IframeTransport(transport, transUrl, baseUrl) { 27 if (!IframeTransport.enabled()) { 28 throw new Error('Transport created when disabled'); 29 } 30 EventEmitter.call(this); 31 32 var self = this; 33 this.origin = urlUtils.getOrigin(baseUrl); 34 this.baseUrl = baseUrl; 35 this.transUrl = transUrl; 36 this.transport = transport; 37 this.windowId = random.string(8); 38 39 var iframeUrl = urlUtils.addPath(baseUrl, '/iframe.html') + '#' + this.windowId; 40 debug(transport, transUrl, iframeUrl); 41 42 this.iframeObj = iframeUtils.createIframe(iframeUrl, function(r) { 43 debug('err callback'); 44 self.emit('close', 1006, 'Unable to load an iframe (' + r + ')'); 45 self.close(); 46 }); 47 48 this.onmessageCallback = this._message.bind(this); 49 eventUtils.attachEvent('message', this.onmessageCallback); 50 } 51 52 inherits(IframeTransport, EventEmitter); 53 54 IframeTransport.prototype.close = function() { 55 debug('close'); 56 this.removeAllListeners(); 57 if (this.iframeObj) { 58 eventUtils.detachEvent('message', this.onmessageCallback); 59 try { 60 // When the iframe is not loaded, IE raises an exception 61 // on 'contentWindow'. 62 this.postMessage('c'); 63 } catch (x) { 64 // intentionally empty 65 } 66 this.iframeObj.cleanup(); 67 this.iframeObj = null; 68 this.onmessageCallback = this.iframeObj = null; 69 } 70 }; 71 72 IframeTransport.prototype._message = function(e) { 73 debug('message', e.data); 74 if (!urlUtils.isOriginEqual(e.origin, this.origin)) { 75 debug('not same origin', e.origin, this.origin); 76 return; 77 } 78 79 var iframeMessage; 80 try { 81 iframeMessage = JSON3.parse(e.data); 82 } catch (ignored) { 83 debug('bad json', e.data); 84 return; 85 } 86 87 if (iframeMessage.windowId !== this.windowId) { 88 debug('mismatched window id', iframeMessage.windowId, this.windowId); 89 return; 90 } 91 92 switch (iframeMessage.type) { 93 case 's': 94 this.iframeObj.loaded(); 95 // window global dependency 96 this.postMessage('s', JSON3.stringify([ 97 version 98 , this.transport 99 , this.transUrl 100 , this.baseUrl 101 ])); 102 break; 103 case 't': 104 this.emit('message', iframeMessage.data); 105 break; 106 case 'c': 107 var cdata; 108 try { 109 cdata = JSON3.parse(iframeMessage.data); 110 } catch (ignored) { 111 debug('bad json', iframeMessage.data); 112 return; 113 } 114 this.emit('close', cdata[0], cdata[1]); 115 this.close(); 116 break; 117 } 118 }; 119 120 IframeTransport.prototype.postMessage = function(type, data) { 121 debug('postMessage', type, data); 122 this.iframeObj.post(JSON3.stringify({ 123 windowId: this.windowId 124 , type: type 125 , data: data || '' 126 }), this.origin); 127 }; 128 129 IframeTransport.prototype.send = function(message) { 130 debug('send', message); 131 this.postMessage('m', message); 132 }; 133 134 IframeTransport.enabled = function() { 135 return iframeUtils.iframeEnabled; 136 }; 137 138 IframeTransport.transportName = 'iframe'; 139 IframeTransport.roundTrips = 2; 140 141 module.exports = IframeTransport;