| 'use strict'; |
| |
| var urlUtils = require('./utils/url') |
| , eventUtils = require('./utils/event') |
| , JSON3 = require('json3') |
| , FacadeJS = require('./facade') |
| , InfoIframeReceiver = require('./info-iframe-receiver') |
| , iframeUtils = require('./utils/iframe') |
| , loc = require('./location') |
| ; |
| |
| var debug = function() {}; |
| if (process.env.NODE_ENV !== 'production') { |
| debug = require('debug')('sockjs-client:iframe-bootstrap'); |
| } |
| |
| module.exports = function(SockJS, availableTransports) { |
| var transportMap = {}; |
| availableTransports.forEach(function(at) { |
| if (at.facadeTransport) { |
| transportMap[at.facadeTransport.transportName] = at.facadeTransport; |
| } |
| }); |
| |
| // hard-coded for the info iframe |
| // TODO see if we can make this more dynamic |
| transportMap[InfoIframeReceiver.transportName] = InfoIframeReceiver; |
| var parentOrigin; |
| |
| /* eslint-disable camelcase */ |
| SockJS.bootstrap_iframe = function() { |
| /* eslint-enable camelcase */ |
| var facade; |
| iframeUtils.currentWindowId = loc.hash.slice(1); |
| var onMessage = function(e) { |
| if (e.source !== parent) { |
| return; |
| } |
| if (typeof parentOrigin === 'undefined') { |
| parentOrigin = e.origin; |
| } |
| if (e.origin !== parentOrigin) { |
| return; |
| } |
| |
| var iframeMessage; |
| try { |
| iframeMessage = JSON3.parse(e.data); |
| } catch (ignored) { |
| debug('bad json', e.data); |
| return; |
| } |
| |
| if (iframeMessage.windowId !== iframeUtils.currentWindowId) { |
| return; |
| } |
| switch (iframeMessage.type) { |
| case 's': |
| var p; |
| try { |
| p = JSON3.parse(iframeMessage.data); |
| } catch (ignored) { |
| debug('bad json', iframeMessage.data); |
| break; |
| } |
| var version = p[0]; |
| var transport = p[1]; |
| var transUrl = p[2]; |
| var baseUrl = p[3]; |
| debug(version, transport, transUrl, baseUrl); |
| // change this to semver logic |
| if (version !== SockJS.version) { |
| throw new Error('Incompatible SockJS! Main site uses:' + |
| ' "' + version + '", the iframe:' + |
| ' "' + SockJS.version + '".'); |
| } |
| |
| if (!urlUtils.isOriginEqual(transUrl, loc.href) || |
| !urlUtils.isOriginEqual(baseUrl, loc.href)) { |
| throw new Error('Can\'t connect to different domain from within an ' + |
| 'iframe. (' + loc.href + ', ' + transUrl + ', ' + baseUrl + ')'); |
| } |
| facade = new FacadeJS(new transportMap[transport](transUrl, baseUrl)); |
| break; |
| case 'm': |
| facade._send(iframeMessage.data); |
| break; |
| case 'c': |
| if (facade) { |
| facade._close(); |
| } |
| facade = null; |
| break; |
| } |
| }; |
| |
| eventUtils.attachEvent('message', onMessage); |
| |
| // Start |
| iframeUtils.postMessage('s'); |
| }; |
| }; |