iframe-bootstrap.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. 'use strict';
  2. var urlUtils = require('./utils/url')
  3. , eventUtils = require('./utils/event')
  4. , FacadeJS = require('./facade')
  5. , InfoIframeReceiver = require('./info-iframe-receiver')
  6. , iframeUtils = require('./utils/iframe')
  7. , loc = require('./location')
  8. ;
  9. var debug = function() {};
  10. if (process.env.NODE_ENV !== 'production') {
  11. debug = require('debug')('sockjs-client:iframe-bootstrap');
  12. }
  13. module.exports = function(SockJS, availableTransports) {
  14. var transportMap = {};
  15. availableTransports.forEach(function(at) {
  16. if (at.facadeTransport) {
  17. transportMap[at.facadeTransport.transportName] = at.facadeTransport;
  18. }
  19. });
  20. // hard-coded for the info iframe
  21. // TODO see if we can make this more dynamic
  22. transportMap[InfoIframeReceiver.transportName] = InfoIframeReceiver;
  23. var parentOrigin;
  24. /* eslint-disable camelcase */
  25. SockJS.bootstrap_iframe = function() {
  26. /* eslint-enable camelcase */
  27. var facade;
  28. iframeUtils.currentWindowId = loc.hash.slice(1);
  29. var onMessage = function(e) {
  30. if (e.source !== parent) {
  31. return;
  32. }
  33. if (typeof parentOrigin === 'undefined') {
  34. parentOrigin = e.origin;
  35. }
  36. if (e.origin !== parentOrigin) {
  37. return;
  38. }
  39. var iframeMessage;
  40. try {
  41. iframeMessage = JSON.parse(e.data);
  42. } catch (ignored) {
  43. debug('bad json', e.data);
  44. return;
  45. }
  46. if (iframeMessage.windowId !== iframeUtils.currentWindowId) {
  47. return;
  48. }
  49. switch (iframeMessage.type) {
  50. case 's':
  51. var p;
  52. try {
  53. p = JSON.parse(iframeMessage.data);
  54. } catch (ignored) {
  55. debug('bad json', iframeMessage.data);
  56. break;
  57. }
  58. var version = p[0];
  59. var transport = p[1];
  60. var transUrl = p[2];
  61. var baseUrl = p[3];
  62. debug(version, transport, transUrl, baseUrl);
  63. // change this to semver logic
  64. if (version !== SockJS.version) {
  65. throw new Error('Incompatible SockJS! Main site uses:' +
  66. ' "' + version + '", the iframe:' +
  67. ' "' + SockJS.version + '".');
  68. }
  69. if (!urlUtils.isOriginEqual(transUrl, loc.href) ||
  70. !urlUtils.isOriginEqual(baseUrl, loc.href)) {
  71. throw new Error('Can\'t connect to different domain from within an ' +
  72. 'iframe. (' + loc.href + ', ' + transUrl + ', ' + baseUrl + ')');
  73. }
  74. facade = new FacadeJS(new transportMap[transport](transUrl, baseUrl));
  75. break;
  76. case 'm':
  77. facade._send(iframeMessage.data);
  78. break;
  79. case 'c':
  80. if (facade) {
  81. facade._close();
  82. }
  83. facade = null;
  84. break;
  85. }
  86. };
  87. eventUtils.attachEvent('message', onMessage);
  88. // Start
  89. iframeUtils.postMessage('s');
  90. };
  91. };