You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
2.8 KiB

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